1
1
package org .opencds .cqf .cql .engine .runtime ;
2
2
3
+ import org .opencds .cqf .cql .engine .exception .InvalidDateTime ;
4
+
3
5
import java .math .BigDecimal ;
4
- import java .math . RoundingMode ;
5
- import java .time .* ;
6
- import java .time .temporal . ChronoField ;
6
+ import java .time . LocalDateTime ;
7
+ import java .time .OffsetDateTime ;
8
+ import java .time .ZoneOffset ;
7
9
import java .util .Calendar ;
8
10
import java .util .Date ;
9
- import java .util .Set ;
10
11
import java .util .TimeZone ;
11
- import java .util .function .Predicate ;
12
- import java .util .stream .Collectors ;
13
-
14
- import org .opencds .cqf .cql .engine .exception .InvalidDateTime ;
15
12
16
13
public class DateTime extends BaseTemporal {
17
- private final ZoneId zoneId ;
18
- private ZoneOffset zoneOffset = null ;
19
-
20
- // Performance optimization
21
- private final Set <ZoneId > allZoneIds = getAllZoneIds ();
14
+ private final ZoneOffset zoneOffset ;
22
15
23
16
private OffsetDateTime dateTime ;
24
17
public OffsetDateTime getDateTime () {
@@ -47,19 +40,18 @@ public DateTime withPrecision(Precision precision) {
47
40
public DateTime (OffsetDateTime dateTime ) {
48
41
setDateTime (dateTime );
49
42
this .precision = Precision .MILLISECOND ;
50
-
51
- zoneId = toZoneId (dateTime );
52
43
zoneOffset = toZoneOffset (dateTime );
53
44
}
54
45
55
46
public DateTime (OffsetDateTime dateTime , Precision precision ) {
56
47
setDateTime (dateTime );
57
48
this .precision = precision ;
58
- zoneId = toZoneId (dateTime );
59
49
zoneOffset = toZoneOffset (dateTime );
60
50
}
61
51
62
52
public DateTime (String dateString , ZoneOffset offset ) {
53
+ zoneOffset = offset ;
54
+
63
55
// Handles case when Tz is not complete (T02:04:59.123+01)
64
56
if (dateString .matches ("T[0-2]\\ d:[0-5]\\ d:[0-5]\\ d\\ .\\ d{3}(\\ +|-)\\ d{2}$" )) {
65
57
dateString += ":00" ;
@@ -103,16 +95,15 @@ public DateTime(String dateString, ZoneOffset offset) {
103
95
else {
104
96
setDateTime (TemporalHelper .toOffsetDateTime (LocalDateTime .parse (dateString )));
105
97
}
106
-
107
- zoneId = toZoneId (offset );
108
- zoneOffset = offset ;
109
98
}
110
99
111
100
public DateTime (BigDecimal offset , int ... dateElements ) {
112
101
if (dateElements .length == 0 ) {
113
102
throw new InvalidDateTime ("DateTime must include a year" );
114
103
}
115
104
105
+ zoneOffset = toZoneOffset (offset );
106
+
116
107
StringBuilder dateString = new StringBuilder ();
117
108
String [] stringElements = TemporalHelper .normalizeDateTimeElements (dateElements );
118
109
@@ -143,20 +134,12 @@ else if (i == 6) {
143
134
// Otherwise, parse as a LocalDateTime and then interpret that in the evaluation timezone
144
135
145
136
if (offset != null ) {
146
- // dateString.append(ZoneOffset.ofHoursMinutes(offset.intValue(), new BigDecimal("60").multiply(offset.remainder(BigDecimal.ONE)).intValue()).getId());
147
137
dateString .append (toZoneOffset (offset ).getId ());
148
138
setDateTime (OffsetDateTime .parse (dateString .toString ()));
149
139
}
150
140
else {
151
141
setDateTime (TemporalHelper .toOffsetDateTime (LocalDateTime .parse (dateString .toString ())));
152
142
}
153
-
154
- zoneId = toZoneId (offset );
155
- zoneOffset = toZoneOffset (offset );
156
- }
157
-
158
- public ZoneId getZoneId () {
159
- return zoneId ;
160
143
}
161
144
162
145
public ZoneOffset getZoneOffset () {
@@ -231,26 +214,12 @@ public Integer compare(BaseTemporal other, boolean forSort) {
231
214
}
232
215
233
216
public OffsetDateTime getNormalized (Precision precision ) {
234
- // return getNormalized(precision, zoneId);
235
217
return getNormalized (precision , zoneOffset );
236
218
}
237
219
238
- public OffsetDateTime getNormalized (Precision precision , ZoneId nullableZoneId ) {
239
- if (precision .toDateTimeIndex () > Precision .DAY .toDateTimeIndex ()) {
240
- if (nullableZoneId != null ) {
241
- return dateTime .atZoneSameInstant (nullableZoneId ).toOffsetDateTime ();
242
- }
243
-
244
- return dateTime .atZoneSameInstant (TimeZone .getDefault ().toZoneId ()).toOffsetDateTime ();
245
- }
246
-
247
- return dateTime ;
248
- }
249
-
250
220
public OffsetDateTime getNormalized (Precision precision , ZoneOffset nullableZoneOffset ) {
251
221
if (precision .toDateTimeIndex () > Precision .DAY .toDateTimeIndex ()) {
252
222
if (nullableZoneOffset != null ) {
253
- // return dateTime.atZoneSameInstant(nullableZoneId).toOffsetDateTime();
254
223
return dateTime .withOffsetSameInstant (nullableZoneOffset );
255
224
}
256
225
@@ -267,7 +236,6 @@ public Integer compareToPrecision(BaseTemporal other, Precision thePrecision) {
267
236
268
237
// adjust dates to evaluation offset
269
238
OffsetDateTime leftDateTime = this .getNormalized (thePrecision );
270
- // OffsetDateTime rightDateTime = ((DateTime) other).getNormalized(thePrecision, getZoneId());
271
239
OffsetDateTime rightDateTime = ((DateTime ) other ).getNormalized (thePrecision , getZoneOffset ());
272
240
273
241
if (!leftMeetsPrecisionRequirements || !rightMeetsPrecisionRequirements ) {
@@ -334,26 +302,6 @@ public static DateTime fromJavaDate(Date date) {
334
302
return new DateTime (OffsetDateTime .ofInstant (calendar .toInstant (), calendar .getTimeZone ().toZoneId ()), Precision .MILLISECOND );
335
303
}
336
304
337
- private ZoneId toZoneId (OffsetDateTime offsetDateTime ) {
338
- return toZoneId (offsetDateTime .getOffset ());
339
- }
340
-
341
- private ZoneId toZoneId (ZoneOffset offset ) {
342
- if (offset == null ) {
343
- return null ;
344
- }
345
-
346
- return toZoneId (zoneId -> isZoneEquivalentToOffset (zoneId , offset ));
347
- }
348
-
349
- private ZoneId toZoneId (BigDecimal offset ) {
350
- if (offset == null ) {
351
- return null ;
352
- }
353
-
354
- return toZoneId (zoneId -> isZoneEquivalentToOffset (zoneId , offset ));
355
- }
356
-
357
305
private ZoneOffset toZoneOffset (OffsetDateTime offsetDateTime ) {
358
306
return offsetDateTime .getOffset ();
359
307
}
@@ -365,66 +313,7 @@ private ZoneOffset toZoneOffset(BigDecimal offsetAsBigDecimal) {
365
313
366
314
return ZoneOffset .ofHoursMinutes (offsetAsBigDecimal .intValue (),
367
315
new BigDecimal (60 )
368
- .multiply (offsetAsBigDecimal .remainder (BigDecimal .ONE )).intValue ());
369
-
370
- // return allZoneIds.stream()
371
- // .map(zoneId -> LocalDateTime.now().atZone(zoneId).getOffset())
372
- // .filter(aZoneOffset -> {
373
- // final long offsetSeconds = aZoneOffset.getLong(ChronoField.OFFSET_SECONDS);
374
- // final BigDecimal offsetMinutes = BigDecimal.valueOf(offsetSeconds)
375
- // .divide(BigDecimal.valueOf(60), 2, RoundingMode.CEILING);
376
- // final BigDecimal offsetHours = offsetMinutes
377
- // .divide(BigDecimal.valueOf(60), 2, RoundingMode.CEILING);
378
- //
379
- // return offsetHours.doubleValue() == offsetAsBigDecimal.doubleValue();
380
- // })
381
- // .findFirst()
382
- // .orElse(null);
383
- }
384
-
385
- private ZoneId toZoneId (Predicate <ZoneId > predicate ) {
386
- // final Set<String> allDstOffsets = allZoneIds.stream().
387
- // map(zoneId -> zoneId.getId() + zoneId.getRules().getStandardOffset(LocalDateTime.of(2023, Month.JUNE, 25, 5, 15, 0).atZone(zoneId).toInstant()).toString())
388
- // .collect(Collectors.toSet());
389
- //
390
- // final Set<String> allNonDstOffsets = allZoneIds.stream().
391
- // map(zoneId -> zoneId.getId() + zoneId.getRules().getStandardOffset(LocalDateTime.of(2023, Month.DECEMBER, 25, 5, 15, 0).atZone(zoneId).toInstant()).toString())
392
- // .collect(Collectors.toSet());
393
- //
394
- // final Set<String> dstMontreal = allDstOffsets.stream().filter(offset -> offset.contains("Montreal")).collect(Collectors.toSet());
395
- // final Set<String> nonDstMontreal = allNonDstOffsets.stream().filter(offset -> offset.contains("Montreal")).collect(Collectors.toSet());
396
- //
397
- // final Set<String> dstNewfoundland = allDstOffsets.stream().filter(offset -> offset.contains("St_Johns")).collect(Collectors.toSet());
398
- // final Set<String> nonDstNewfoundland = allNonDstOffsets.stream().filter(offset -> offset.contains("St_Johns")).collect(Collectors.toSet());
399
-
400
- // LUKETODO: there is a performance issue with CQL and it's probably because we don't inline enough here:
401
- return allZoneIds .stream ()
402
- .filter (predicate )
403
- .findFirst ()
404
- .orElse (null );
405
- }
406
-
407
- private static Set <ZoneId > getAllZoneIds () {
408
- return ZoneId .getAvailableZoneIds ()
409
- .stream ()
410
- .map (ZoneId ::of )
411
- .collect (Collectors .toSet ());
412
- }
413
-
414
- private static boolean isZoneEquivalentToOffset (ZoneId zoneId , ZoneOffset zoneOffset ) {
415
- final ZoneOffset zoneIdOffset = LocalDateTime .now ().atZone (zoneId ).getOffset ();
416
-
417
- return zoneIdOffset .equals (zoneOffset );
418
- }
419
-
420
- private static boolean isZoneEquivalentToOffset (ZoneId zoneId , BigDecimal offset ) {
421
- final ZoneOffset zoneOffset = LocalDateTime .now ().atZone (zoneId ).getOffset ();
422
- final long offsetSeconds = zoneOffset .getLong (ChronoField .OFFSET_SECONDS );
423
- final BigDecimal offsetMinutes = BigDecimal .valueOf (offsetSeconds )
424
- .divide (BigDecimal .valueOf (60 ), 2 , RoundingMode .CEILING );
425
- final BigDecimal offsetHours = offsetMinutes
426
- .divide (BigDecimal .valueOf (60 ), 2 , RoundingMode .CEILING );
427
-
428
- return offsetHours .doubleValue () == offset .doubleValue ();
316
+ .multiply (offsetAsBigDecimal .remainder (BigDecimal .ONE ))
317
+ .intValue ());
429
318
}
430
319
}
0 commit comments