@@ -17,7 +17,11 @@ namespace Hl7.Cql.Primitives
17
17
/// </summary>
18
18
/// <see href="https://cql.hl7.org/09-b-cqlreference.html#datetime"/>
19
19
[ CqlPrimitiveType ( CqlPrimitiveType . DateTime ) ]
20
- public class CqlDateTime : ICqlComparable < CqlDateTime > , IEquivalentable < CqlDateTime >
20
+ public class CqlDateTime :
21
+ ICqlComparable < CqlDateTime > ,
22
+ IEquivalentable < CqlDateTime > ,
23
+ IAdditionOperators < CqlDateTime ? , CqlQuantity ? , CqlDateTime ? > ,
24
+ ISubtractionOperators < CqlDateTime ? , CqlQuantity ? , CqlDateTime ? >
21
25
{
22
26
/// <summary>
23
27
/// Defines the minimum value for System date times (@0001-01-01T00:00:00.000Z).
@@ -151,9 +155,9 @@ public static bool TryParse(string s, out CqlDateTime? cqlDateTime)
151
155
var dto = Value . DateTimeOffset ;
152
156
dto = unit switch
153
157
{
154
- "a" => dto . AddDays ( UCUMUnits . DaysPerYearDouble ) ,
158
+ "a" => dto . AddDays ( Math . Sign ( value ) * UCUMUnits . DaysPerYearDouble ) ,
155
159
"year" or "years" => dto . AddYears ( ( int ) value ) ,
156
- "mo" => dto . AddDays ( UCUMUnits . DaysPerMonthDouble ) ,
160
+ "mo" => dto . AddDays ( Math . Sign ( value ) * UCUMUnits . DaysPerMonthDouble ) ,
157
161
"month" or "months" => dto . AddMonths ( ( int ) value ) ,
158
162
"wk" or "week" or "weeks" => dto . AddDays ( ( int ) ( value ! * CqlDateTimeMath . DaysPerWeek ) ) ,
159
163
"d" or "day" or "days" => dto . AddDays ( ( int ) value ! ) ,
@@ -175,31 +179,7 @@ public static bool TryParse(string s, out CqlDateTime? cqlDateTime)
175
179
/// <param name="quantity">The quantity to subtract.</param>
176
180
/// <returns>A new date time with <paramref name="quantity"/> subtracted from it.</returns>
177
181
/// <exception cref="ArgumentException">If the quantity is not expressed in supported units, or an overflow occurs.</exception>
178
- public CqlDateTime ? Subtract ( CqlQuantity quantity )
179
- {
180
- if ( quantity is not { value : { } value , unit : { } unit } )
181
- return null ;
182
-
183
- var dto = Value . DateTimeOffset ;
184
- dto = unit switch
185
- {
186
- "a" => dto . AddDays ( - 1 * UCUMUnits . DaysPerYearDouble ) ,
187
- "year" or "years" => dto . AddYears ( ( int ) value ) ,
188
- "mo" => dto . AddDays ( - 1 * UCUMUnits . DaysPerMonthDouble ) ,
189
- "month" or "months" => dto . AddMonths ( ( int ) value ) ,
190
- "wk" or "week" or "weeks" => dto . AddDays ( ( int ) ( value ! * CqlDateTimeMath . DaysPerWeek ) ) ,
191
- "d" or "day" or "days" => dto . AddDays ( ( int ) value ! ) ,
192
- "h" or "hour" or "hours" => dto . AddHours ( Math . Truncate ( ( double ) value ) ) ,
193
- "min" or "minute" or "minutes" => dto . AddMinutes ( Math . Truncate ( ( double ) value ) ) ,
194
- "s" or "second" or "seconds" => dto . AddSeconds ( Math . Truncate ( ( double ) value ) ) ,
195
- "ms" or "millisecond" or "milliseconds" => dto . AddMilliseconds ( Math . Truncate ( ( double ) value ) ) ,
196
- _ => throw new ArgumentException ( $ "Unknown date unit { unit } supplied")
197
- } ;
198
-
199
- var newIsoDate = new DateTimeIso8601 ( dto , Value . Precision ) ;
200
- var result = new CqlDateTime ( newIsoDate ) ;
201
- return result ;
202
- }
182
+ public CqlDateTime ? Subtract ( CqlQuantity ? quantity ) => Add ( - quantity ) ;
203
183
204
184
/// <summary>
205
185
/// Gets the component of this date time.
@@ -503,15 +483,36 @@ public bool EquivalentToValue(CqlDateTime other, string? precision) =>
503
483
/// Returns <see cref="DateTimeIso8601.ToString"/> for <see cref="Value"/>.
504
484
/// </summary>
505
485
public override string ToString ( ) => Value . ToString ( ) ;
486
+
506
487
/// <summary>
507
488
/// Compares this object to <paramref name="obj"/> for equality.
508
489
/// </summary>
509
490
/// <param name="obj">The object to compare against this value.</param>
510
491
/// <returns><see langword="true"/> if equal.</returns>
511
492
public override bool Equals ( object ? obj ) => Value . Equals ( ( obj as CqlDateTime ) ? . Value ! ) ;
493
+
512
494
/// <summary>
513
495
/// Gets the value of <see cref="DateTimeIso8601.GetHashCode"/> for <see cref="Value"/>.
514
496
/// </summary>
515
497
public override int GetHashCode ( ) => Value . GetHashCode ( ) ;
498
+
499
+ /// <summary>
500
+ /// Adds a specified quantity to a CqlDateTime value, returning a new CqlDateTime that represents the result.
501
+ /// </summary>
502
+ /// <param name="left">The CqlDateTime value to which the quantity will be added. May be null.</param>
503
+ /// <param name="right">The CqlQuantity representing the amount to add to the date and time. May be null.</param>
504
+ /// <returns>A new CqlDateTime that is the result of adding the specified quantity to the original value, or null if
505
+ /// either operand is null.</returns>
506
+ public static CqlDateTime ? operator + ( CqlDateTime ? left , CqlQuantity ? right ) => left ? . Add ( right ) ;
507
+
508
+ /// <summary>
509
+ /// Subtracts a specified quantity from a CqlDateTime value, returning a new CqlDateTime that represents the
510
+ /// result.
511
+ /// </summary>
512
+ /// <param name="left">The CqlDateTime value from which to subtract. May be null.</param>
513
+ /// <param name="right">The CqlQuantity value to subtract from the CqlDateTime. May be null.</param>
514
+ /// <returns>A new CqlDateTime representing the result of subtracting the specified quantity from the original date and
515
+ /// time, or null if either operand is null.</returns>
516
+ public static CqlDateTime ? operator - ( CqlDateTime ? left , CqlQuantity ? right ) => left ? . Subtract ( right ) ;
516
517
}
517
518
}
0 commit comments