From 9f1dd4e06d425db2d91028701e9fe39baf27422d Mon Sep 17 00:00:00 2001 From: Adam Stevenson Date: Tue, 2 May 2023 17:35:11 -0600 Subject: [PATCH] Fixed FHIR Query Generation test cases that involved dates (#1150) * Fixed FHIR Query Generation test cases that involved dates Made the date calculation logic for the expected query calculation consistent with what the engine is doing for query generation to resolve an issue with test failing when an interval's start and end date are in different with respect to daylight savings time. --------- Co-authored-by: Bryn Rhodes Co-authored-by: JP --- .../retrieve/TestDstu3FhirQueryGenerator.java | 34 ++++++++------ .../retrieve/TestR4FhirQueryGenerator.java | 44 +++++++++++++------ 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestDstu3FhirQueryGenerator.java b/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestDstu3FhirQueryGenerator.java index 376b532f3..34cbc9bb2 100644 --- a/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestDstu3FhirQueryGenerator.java +++ b/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestDstu3FhirQueryGenerator.java @@ -4,7 +4,6 @@ import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.param.DateRangeParam; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.hl7.fhir.dstu3.model.*; import org.opencds.cqf.cql.engine.fhir.Dstu3FhirTest; @@ -49,7 +48,7 @@ public void setUp() throws FhirVersionMisMatchException { TerminologyProvider terminologyProvider = new Dstu3FhirTerminologyProvider(CLIENT); Dstu3FhirModelResolver modelResolver = new CachedDstu3FhirModelResolver(); this.generator = new Dstu3FhirQueryGenerator(searchParameterResolver, terminologyProvider, modelResolver); - this.evaluationOffsetDateTime = OffsetDateTime.of(2018, 11, 19, 9, 0, 0, 000, ZoneOffset.ofHours(-10)); + this.evaluationOffsetDateTime = OffsetDateTime.of(2018, 11, 19, 9, 0, 0, 000, ZoneOffset.ofHours(-7)); this.evaluationDateTime = new DateTime(evaluationOffsetDateTime); this.contextValues = new HashMap(); this.parameters = new HashMap(); @@ -158,11 +157,12 @@ void testGetFhirQueriesAppointmentWithDate() { DataRequirement.DataRequirementDateFilterComponent dateFilterComponent = new DataRequirement.DataRequirementDateFilterComponent(); dateFilterComponent.setPath("start"); - int offsetHours = java.util.TimeZone.getDefault().getRawOffset() / 3600000; - String offsetSign = offsetHours < 0 ? "-" : "+"; - int offsetAbs = Math.abs(offsetHours); - String offsetStringPadded = StringUtils.leftPad(String.valueOf(offsetAbs), 2, "0"); - String dateTimeString = String.format("2021-12-01T00:00:00.000%s%s:00", offsetSign, offsetStringPadded); + OffsetDateTime evaluationDateTimeAsLocal = OffsetDateTime.ofInstant(evaluationOffsetDateTime.toInstant(), + java.util.TimeZone.getDefault().toZoneId()); + + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"); + String dateTimeString = dateTimeFormatter.format(evaluationDateTimeAsLocal); + dateFilterComponent.setValue(new DateTimeType(dateTimeString)); dataRequirement.setDateFilter(Collections.singletonList(dateFilterComponent)); @@ -182,21 +182,27 @@ void testGetFhirQueriesObservationWithDuration() { DataRequirement.DataRequirementDateFilterComponent dateFilterComponent = new DataRequirement.DataRequirementDateFilterComponent(); dateFilterComponent.setPath("effective"); Duration duration = new Duration(); - duration.setValue(2).setCode("d").setUnit("days"); + duration.setValue(90).setCode("d").setUnit("days"); dateFilterComponent.setValue(duration); dataRequirement.setDateFilter(Collections.singletonList(dateFilterComponent)); this.contextValues.put("Patient", "{{context.patientId}}"); java.util.List actual = this.generator.generateFhirQueries(dataRequirement, this.evaluationDateTime, this.contextValues, this.parameters, null); - int offsetHours = java.util.TimeZone.getDefault().getRawOffset() / 3600000; - OffsetDateTime evaluationDateTimeAsLocal = OffsetDateTime.ofInstant(this.evaluationOffsetDateTime.toInstant(), - java.util.TimeZone.getDefault().toZoneId()); - OffsetDateTime expectedRangeStartDateTime = evaluationDateTimeAsLocal.minusDays(2); - DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"); + OffsetDateTime evaluationDateTimeAsLocal = OffsetDateTime.ofInstant(evaluationOffsetDateTime.toInstant(), + java.util.TimeZone.getDefault().toZoneId()); + Date expectedRangeStartDateTime = Date.from(evaluationDateTimeAsLocal.minusDays(90).toInstant()); + + SimpleDateFormat simpleDateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"); String actualQuery = actual.get(0); - String expectedQuery = String.format("Observation?date=ge%s&date=le%s&patient=Patient/{{context.patientId}}", fmt.format(expectedRangeStartDateTime), fmt.format(evaluationDateTimeAsLocal)); + String expectedQuery = + String.format( + "Observation?date=ge%s&date=le%s&patient=Patient/{{context.patientId}}", + simpleDateFormatter.format(expectedRangeStartDateTime), + dateTimeFormatter.format(evaluationDateTimeAsLocal) + ).replace("Z", "+00:00");; assertEquals(actualQuery, expectedQuery); } diff --git a/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestR4FhirQueryGenerator.java b/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestR4FhirQueryGenerator.java index 2a9bc42df..5ed1ed501 100644 --- a/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestR4FhirQueryGenerator.java +++ b/Src/java/engine-fhir/src/test/java/org/opencds/cqf/cql/engine/fhir/retrieve/TestR4FhirQueryGenerator.java @@ -4,7 +4,6 @@ import ca.uhn.fhir.context.FhirVersionEnum; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.param.DateRangeParam; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.hl7.fhir.r4.model.*; import org.opencds.cqf.cql.engine.fhir.R4FhirTest; @@ -49,13 +48,23 @@ public void setUp() throws FhirVersionMisMatchException { TerminologyProvider terminologyProvider = new R4FhirTerminologyProvider(CLIENT); R4FhirModelResolver modelResolver = new CachedR4FhirModelResolver(); this.generator = new R4FhirQueryGenerator(searchParameterResolver, terminologyProvider, modelResolver); - OffsetDateTime evaluationDateTime = OffsetDateTime.of(2018, 11, 19, 9, 0, 0, 000, ZoneOffset.ofHours(-7)); - this.evaluationOffsetDateTime = OffsetDateTime.of(2018, 11, 19, 9, 0, 0, 000, ZoneOffset.ofHours(-10)); + this.evaluationOffsetDateTime = OffsetDateTime.of(2018, 11, 19, 9, 0, 0, 000, ZoneOffset.ofHours(-7)); this.evaluationDateTime = new DateTime(evaluationOffsetDateTime); this.contextValues = new HashMap(); this.parameters = new HashMap(); } + @Test + public void Test() { + DateTime evaluationDateTime = new DateTime(evaluationOffsetDateTime); + OffsetDateTime evaluationDateTimeAsLocal = + OffsetDateTime.ofInstant(evaluationOffsetDateTime.toInstant(), java.util.TimeZone.getTimeZone("UTC").toZoneId()); + Date expectedRangeStartDateTime = Date.from(evaluationDateTimeAsLocal.minusDays(90).toInstant()); + + SimpleDateFormat simpleDateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + String expectedQuery = String.format("date=%s", simpleDateFormatter.format(expectedRangeStartDateTime)); + } + private ValueSet getTestValueSet(String id, int numberOfCodesToInclude) { String valueSetUrl = String.format("http://myterm.com/fhir/ValueSet/%s", id); ValueSet valueSet = new ValueSet(); @@ -188,11 +197,12 @@ void testGetFhirQueriesAppointmentWithDate() { DataRequirement.DataRequirementDateFilterComponent dateFilterComponent = new DataRequirement.DataRequirementDateFilterComponent(); dateFilterComponent.setSearchParam("date"); - int offsetHours = java.util.TimeZone.getDefault().getRawOffset() / 3600000; - String offsetSign = offsetHours < 0 ? "-" : "+"; - int offsetAbs = Math.abs(offsetHours); - String offsetStringPadded = StringUtils.leftPad(String.valueOf(offsetAbs), 2, "0"); - String dateTimeString = String.format("2021-12-01T00:00:00.000%s%s:00", offsetSign, offsetStringPadded); + OffsetDateTime evaluationDateTimeAsLocal = OffsetDateTime.ofInstant(evaluationOffsetDateTime.toInstant(), + java.util.TimeZone.getDefault().toZoneId()); + + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"); + String dateTimeString = dateTimeFormatter.format(evaluationDateTimeAsLocal); + dateFilterComponent.setValue(new DateTimeType(dateTimeString)); dataRequirement.setDateFilter(Collections.singletonList(dateFilterComponent)); @@ -212,21 +222,27 @@ void testGetFhirQueriesObservationWithDuration() { DataRequirement.DataRequirementDateFilterComponent dateFilterComponent = new DataRequirement.DataRequirementDateFilterComponent(); dateFilterComponent.setSearchParam("date"); Duration duration = new Duration(); - duration.setValue(2).setCode("d").setUnit("days"); + duration.setValue(90).setCode("d").setUnit("days"); dateFilterComponent.setValue(duration); dataRequirement.setDateFilter(Collections.singletonList(dateFilterComponent)); this.contextValues.put("Patient", "{{context.patientId}}"); java.util.List actual = this.generator.generateFhirQueries(dataRequirement, this.evaluationDateTime, this.contextValues, this.parameters, null); - int offsetHours = java.util.TimeZone.getDefault().getRawOffset() / 3600000; OffsetDateTime evaluationDateTimeAsLocal = OffsetDateTime.ofInstant(evaluationOffsetDateTime.toInstant(), - java.util.TimeZone.getDefault().toZoneId()); - OffsetDateTime expectedRangeStartDateTime = evaluationDateTimeAsLocal.minusDays(2); - DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"); + java.util.TimeZone.getDefault().toZoneId()); + Date expectedRangeStartDateTime = Date.from(evaluationDateTimeAsLocal.minusDays(90).toInstant()); + + SimpleDateFormat simpleDateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx"); String actualQuery = actual.get(0); - String expectedQuery = String.format("Observation?date=ge%s&date=le%s&subject=Patient/{{context.patientId}}", fmt.format(expectedRangeStartDateTime), fmt.format(evaluationDateTimeAsLocal)); + String expectedQuery = + String.format( + "Observation?date=ge%s&date=le%s&subject=Patient/{{context.patientId}}", + simpleDateFormatter.format(expectedRangeStartDateTime), + dateTimeFormatter.format(evaluationDateTimeAsLocal) + ).replace("Z", "+00:00"); assertEquals(actualQuery, expectedQuery); }