Skip to content

Commit 82ad161

Browse files
author
Luke deGruchy
committed
Remove all remnants of old ZoneId code. Add more unit tests.
1 parent bac08ff commit 82ad161

File tree

3 files changed

+31
-139
lines changed

3 files changed

+31
-139
lines changed

Src/java/engine/src/main/java/org/opencds/cqf/cql/engine/runtime/DateTime.java

+12-123
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
11
package org.opencds.cqf.cql.engine.runtime;
22

3+
import org.opencds.cqf.cql.engine.exception.InvalidDateTime;
4+
35
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;
79
import java.util.Calendar;
810
import java.util.Date;
9-
import java.util.Set;
1011
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;
1512

1613
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;
2215

2316
private OffsetDateTime dateTime;
2417
public OffsetDateTime getDateTime() {
@@ -47,19 +40,18 @@ public DateTime withPrecision(Precision precision) {
4740
public DateTime(OffsetDateTime dateTime) {
4841
setDateTime(dateTime);
4942
this.precision = Precision.MILLISECOND;
50-
51-
zoneId = toZoneId(dateTime);
5243
zoneOffset = toZoneOffset(dateTime);
5344
}
5445

5546
public DateTime(OffsetDateTime dateTime, Precision precision) {
5647
setDateTime(dateTime);
5748
this.precision = precision;
58-
zoneId = toZoneId(dateTime);
5949
zoneOffset = toZoneOffset(dateTime);
6050
}
6151

6252
public DateTime(String dateString, ZoneOffset offset) {
53+
zoneOffset = offset;
54+
6355
// Handles case when Tz is not complete (T02:04:59.123+01)
6456
if (dateString.matches("T[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d{3}(\\+|-)\\d{2}$")) {
6557
dateString += ":00";
@@ -103,16 +95,15 @@ public DateTime(String dateString, ZoneOffset offset) {
10395
else {
10496
setDateTime(TemporalHelper.toOffsetDateTime(LocalDateTime.parse(dateString)));
10597
}
106-
107-
zoneId = toZoneId(offset);
108-
zoneOffset = offset;
10998
}
11099

111100
public DateTime(BigDecimal offset, int ... dateElements) {
112101
if (dateElements.length == 0) {
113102
throw new InvalidDateTime("DateTime must include a year");
114103
}
115104

105+
zoneOffset = toZoneOffset(offset);
106+
116107
StringBuilder dateString = new StringBuilder();
117108
String[] stringElements = TemporalHelper.normalizeDateTimeElements(dateElements);
118109

@@ -143,20 +134,12 @@ else if (i == 6) {
143134
// Otherwise, parse as a LocalDateTime and then interpret that in the evaluation timezone
144135

145136
if (offset != null) {
146-
// dateString.append(ZoneOffset.ofHoursMinutes(offset.intValue(), new BigDecimal("60").multiply(offset.remainder(BigDecimal.ONE)).intValue()).getId());
147137
dateString.append(toZoneOffset(offset).getId());
148138
setDateTime(OffsetDateTime.parse(dateString.toString()));
149139
}
150140
else {
151141
setDateTime(TemporalHelper.toOffsetDateTime(LocalDateTime.parse(dateString.toString())));
152142
}
153-
154-
zoneId = toZoneId(offset);
155-
zoneOffset = toZoneOffset(offset);
156-
}
157-
158-
public ZoneId getZoneId() {
159-
return zoneId;
160143
}
161144

162145
public ZoneOffset getZoneOffset() {
@@ -231,26 +214,12 @@ public Integer compare(BaseTemporal other, boolean forSort) {
231214
}
232215

233216
public OffsetDateTime getNormalized(Precision precision) {
234-
// return getNormalized(precision, zoneId);
235217
return getNormalized(precision, zoneOffset);
236218
}
237219

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-
250220
public OffsetDateTime getNormalized(Precision precision, ZoneOffset nullableZoneOffset) {
251221
if (precision.toDateTimeIndex() > Precision.DAY.toDateTimeIndex()) {
252222
if (nullableZoneOffset != null) {
253-
// return dateTime.atZoneSameInstant(nullableZoneId).toOffsetDateTime();
254223
return dateTime.withOffsetSameInstant(nullableZoneOffset);
255224
}
256225

@@ -267,7 +236,6 @@ public Integer compareToPrecision(BaseTemporal other, Precision thePrecision) {
267236

268237
// adjust dates to evaluation offset
269238
OffsetDateTime leftDateTime = this.getNormalized(thePrecision);
270-
// OffsetDateTime rightDateTime = ((DateTime) other).getNormalized(thePrecision, getZoneId());
271239
OffsetDateTime rightDateTime = ((DateTime) other).getNormalized(thePrecision, getZoneOffset());
272240

273241
if (!leftMeetsPrecisionRequirements || !rightMeetsPrecisionRequirements) {
@@ -334,26 +302,6 @@ public static DateTime fromJavaDate(Date date) {
334302
return new DateTime(OffsetDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId()), Precision.MILLISECOND);
335303
}
336304

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-
357305
private ZoneOffset toZoneOffset(OffsetDateTime offsetDateTime) {
358306
return offsetDateTime.getOffset();
359307
}
@@ -365,66 +313,7 @@ private ZoneOffset toZoneOffset(BigDecimal offsetAsBigDecimal) {
365313

366314
return ZoneOffset.ofHoursMinutes(offsetAsBigDecimal.intValue(),
367315
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());
429318
}
430319
}

Src/java/engine/src/test/java/org/opencds/cqf/cql/engine/execution/CqlPerformanceIT.java

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
import static org.testng.Assert.assertTrue;
1717

18-
// LUKETODO: this test suite is failing with performance problems
1918
public class CqlPerformanceIT extends CqlTestBase {
2019

2120
private static final Integer ITERATIONS = 200;

Src/java/engine/src/test/java/org/opencds/cqf/cql/engine/runtime/DateTimeTest.java

+19-15
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class DateTimeTest {
4040
private static final ZoneOffset DST_OFFSET_NORTH_AMERICA_MOUNTAIN = ZoneOffset.of("-06:00");
4141
private static final ZoneOffset NON_DST_OFFSET_NORTH_AMERICA_MOUNTAIN = ZoneOffset.of("-07:00");
4242
private static final ZoneOffset DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND = ZoneOffset.of("-02:30");
43+
// This offset doesn't exist for an ZoneID
4344
private static final ZoneOffset NON_DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND = ZoneOffset.of("-03:30");
4445

4546
private static final BigDecimal DST_BIG_DECIMAL_OFFSET_NORTH_AMERICA_EASTERN = toBigDecimal(DST_OFFSET_NORTH_AMERICA_EASTERN);
@@ -95,20 +96,34 @@ void testDateStrings(String dateString, ZoneOffset zoneOffset, Precision precisi
9596
assertEquals(normalizedDateTime, dateTime.getDateTime());
9697
}
9798

98-
// LUKETODO: more test cases
9999
@DataProvider
100100
private static Object[][] dateStringsOtherZoneId() {
101101
return new Object[][]{
102-
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_EASTERN, DST_OFFSET_NORTH_AMERICA_MOUNTAIN}
102+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_EASTERN, DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.HOUR},
103+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_MOUNTAIN, DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.HOUR},
104+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_EASTERN, DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, Precision.HOUR},
105+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, DST_OFFSET_NORTH_AMERICA_EASTERN, Precision.HOUR},
106+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_EASTERN, NON_DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.HOUR},
107+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_MOUNTAIN, NON_DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.HOUR},
108+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_EASTERN, NON_DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, Precision.HOUR},
109+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, NON_DST_OFFSET_NORTH_AMERICA_EASTERN, Precision.HOUR},
110+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_EASTERN, DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.MILLISECOND},
111+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_MOUNTAIN, DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.MILLISECOND},
112+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_EASTERN, DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, Precision.MILLISECOND},
113+
{DST_2023_10_26_22_12_0, DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, DST_OFFSET_NORTH_AMERICA_EASTERN, Precision.MILLISECOND},
114+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_EASTERN, NON_DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.MILLISECOND},
115+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_MOUNTAIN, NON_DST_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.MILLISECOND},
116+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_EASTERN, NON_DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, Precision.MILLISECOND},
117+
{NON_DST_2024_02_27_07_28_0, NON_DST_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, NON_DST_OFFSET_NORTH_AMERICA_EASTERN, Precision.MILLISECOND},
103118
};
104119
}
105120

106121
@Test(dataProvider = "dateStringsOtherZoneId")
107-
void testDateStringsOtherZoneId(LocalDateTime localDateTime, ZoneOffset zoneOffsetInit, ZoneOffset zonedOffsetGetNormalized) {
122+
void testDateStringsOtherZoneId(LocalDateTime localDateTime, ZoneOffset zoneOffsetInit, ZoneOffset zonedOffsetGetNormalized, Precision precision) {
108123
final OffsetDateTime expectedOffsetDateTime = OffsetDateTime.of(localDateTime.minusSeconds(zoneOffsetInit.getTotalSeconds() - zonedOffsetGetNormalized.getTotalSeconds()), zonedOffsetGetNormalized);
109124
final DateTime dateTime = new DateTime(FORMATTER.format(localDateTime), zoneOffsetInit);
110125

111-
final OffsetDateTime normalizedDateTime = dateTime.getNormalized(Precision.HOUR, zonedOffsetGetNormalized);
126+
final OffsetDateTime normalizedDateTime = dateTime.getNormalized(precision, zonedOffsetGetNormalized);
112127

113128
assertEquals(normalizedDateTime, expectedOffsetDateTime);
114129
}
@@ -165,7 +180,6 @@ private static Object[][] bigDecimals() {
165180
{BigDecimal.ZERO, Precision.HOUR, NON_DST_2024_02_27_07_28_0_INTS},
166181
{NON_DST_BIG_DECIMAL_OFFSET_NORTH_AMERICA_EASTERN, Precision.HOUR, NON_DST_2024_02_27_07_28_0_INTS},
167182
{NON_DST_BIG_DECIMAL_OFFSET_NORTH_AMERICA_MOUNTAIN, Precision.HOUR, NON_DST_2024_02_27_07_28_0_INTS},
168-
// LUKETODO: This fails with an offset of "-3.50"
169183
{NON_DST_BIG_DECIMAL_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, Precision.HOUR, NON_DST_2024_02_27_07_28_0_INTS},
170184
{null, Precision.MILLISECOND, DST_2024_06_15_23_32_0_INTS},
171185
{BigDecimal.ZERO, Precision.MILLISECOND, DST_2024_06_15_23_32_0_INTS},
@@ -184,14 +198,4 @@ void testBigDecimal(BigDecimal offset, Precision precision, List<Integer> dateEl
184198

185199
assertEquals(normalizedDateTime, dateTime.getDateTime());
186200
}
187-
188-
@Test
189-
void testNewfoundlandNonDst() {
190-
final int[] dateElementsArray = NON_DST_2024_02_27_07_28_0_INTS.stream().mapToInt(anInt -> anInt).toArray();
191-
final DateTime dateTime = new DateTime(NON_DST_BIG_DECIMAL_OFFSET_NORTH_AMERICA_NEWFOUNDLAND, dateElementsArray);
192-
193-
final OffsetDateTime normalizedDateTime = dateTime.getNormalized(Precision.HOUR);
194-
195-
assertEquals(normalizedDateTime, dateTime.getDateTime());
196-
}
197201
}

0 commit comments

Comments
 (0)