Change timestamp format.

This commit is contained in:
Luke deGruchy 2024-09-26 17:11:57 -04:00
parent d9fc74ee9d
commit f987eaa901
2 changed files with 88 additions and 62 deletions

View File

@ -43,8 +43,12 @@ public class MeasureReportPeriodRequestProcessingService {
private static final DateTimeFormatter DATE_TIME_FORMATTER_YYYY_MM_DD_INPUT = DateTimeFormatter.ISO_DATE; private static final DateTimeFormatter DATE_TIME_FORMATTER_YYYY_MM_DD_INPUT = DateTimeFormatter.ISO_DATE;
private static final DateTimeFormatter DATE_TIME_FORMATTER_YYYY_MM_DD_HH_MM_SS_INPUT = private static final DateTimeFormatter DATE_TIME_FORMATTER_YYYY_MM_DD_HH_MM_SS_INPUT =
DateTimeFormatter.ISO_LOCAL_DATE_TIME; DateTimeFormatter.ISO_LOCAL_DATE_TIME;
// LUKETODO: what's the winning format here?
// java.time.format.DateTimeParseException: Text '2023-01-01T00:00:00.0-0700'
private static final DateTimeFormatter DATE_TIME_FORMATTER_YYYY_MM_DD_HH_MM_SS_Z_OUTPUT = private static final DateTimeFormatter DATE_TIME_FORMATTER_YYYY_MM_DD_HH_MM_SS_Z_OUTPUT =
DateTimeFormatter.ISO_OFFSET_DATE_TIME; DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SXXX");
// DateTimeFormatter.ISO_OFFSET_DATE_TIME;
// DateTimeFormatter.ISO_ZONED_DATE_TIME;
private static final Map<Integer, DateTimeFormatter> VALID_DATE_TIME_FORMATTERS_BY_FORMAT_LENGTH = Map.of( private static final Map<Integer, DateTimeFormatter> VALID_DATE_TIME_FORMATTERS_BY_FORMAT_LENGTH = Map.of(
4, DATE_TIME_FORMATTER_YYYY_INPUT, 4, DATE_TIME_FORMATTER_YYYY_INPUT,
@ -106,12 +110,19 @@ public class MeasureReportPeriodRequestProcessingService {
} }
if (localDateTimeStart.isAfter(localDateTimeEnd)) { if (localDateTimeStart.isAfter(localDateTimeEnd)) {
throw new InvalidRequestException( throw new InvalidRequestException(String.format(
String.format("Start date: %s is after end date: %s", thePeriodStart, thePeriodEnd)); "Invalid Interval - the ending boundary: %s must be greater than or equal to the starting boundary: %s",
thePeriodEnd, thePeriodStart));
} }
final String periodStartFormatted = formatWithTimezone(localDateTimeStart, theZoneId);
final String periodEndFormatted = formatWithTimezone(localDateTimeEnd, theZoneId);
ourLog.info("6560: NEW START: {} formatted: {}, NEW END: {}, formatted: {}", localDateTimeStart, periodStartFormatted, localDateTimeEnd, periodEndFormatted);
return new MeasurePeriodForEvaluation( return new MeasurePeriodForEvaluation(
formatWithTimezone(localDateTimeStart, theZoneId), formatWithTimezone(localDateTimeEnd, theZoneId)); periodStartFormatted, periodEndFormatted);
} }
private String formatWithTimezone(LocalDateTime theLocalDateTime, ZoneId theZoneId) { private String formatWithTimezone(LocalDateTime theLocalDateTime, ZoneId theZoneId) {

View File

@ -5,12 +5,18 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.SystemRequestDetails; import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -21,74 +27,85 @@ class MeasureReportPeriodRequestProcessingServiceTest {
private final MeasureReportPeriodRequestProcessingService myTestSubject = new MeasureReportPeriodRequestProcessingService(ZoneOffset.UTC); private final MeasureReportPeriodRequestProcessingService myTestSubject = new MeasureReportPeriodRequestProcessingService(ZoneOffset.UTC);
@Test
void dammit() {
final String expectedResult = "2020-01-01T00:00:00.0-05:00";
final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SXXX");
final ZonedDateTime input = ZonedDateTime.of(LocalDateTime.of(2020, Month.JANUARY, 1, 0, 0, 0), ZoneId.of("America/Toronto"));
final String actualResult = input.format(dateTimeFormatter);
assertThat(actualResult).isEqualTo(expectedResult);
}
// LUKETODO: what happens if only one is null? // LUKETODO: what happens if only one is null?
@ParameterizedTest @ParameterizedTest
@CsvSource( nullValues = {"null"}, @CsvSource( nullValues = {"null"},
value={ value={
// request timezone start end expected converted start expected converted end // request timezone start end expected converted start expected converted end
"null, null, null, null, null", "null, null, null, null, null",
"Z, null, null, null, null", "Z, null, null, null, null",
"UTC, null, null, null, null", "UTC, null, null, null, null",
"America/St_Johns, null, null, null, null", "America/St_Johns, null, null, null, null",
"America/Toronto, null, null, null, null", "America/Toronto, null, null, null, null",
"America/Denver, null, null, null, null", "America/Denver, null, null, null, null",
"null, 2020, 2021, 2020-01-01T00:00:00Z, 2021-12-31T23:59:59Z", "null, 2020, 2021, 2020-01-01T00:00:00.0Z, 2021-12-31T23:59:59.0Z",
"Z, 2020, 2021, 2020-01-01T00:00:00Z, 2021-12-31T23:59:59Z", "Z, 2020, 2021, 2020-01-01T00:00:00.0Z, 2021-12-31T23:59:59.0Z",
"UTC, 2020, 2021, 2020-01-01T00:00:00Z, 2021-12-31T23:59:59Z", "UTC, 2020, 2021, 2020-01-01T00:00:00.0Z, 2021-12-31T23:59:59.0Z",
"America/St_Johns, 2020, 2021, 2020-01-01T00:00:00-03:30, 2021-12-31T23:59:59-03:30", "America/St_Johns, 2020, 2021, 2020-01-01T00:00:00.0-03:30, 2021-12-31T23:59:59.0-03:30",
"America/Toronto, 2020, 2021, 2020-01-01T00:00:00-05:00, 2021-12-31T23:59:59-05:00", "America/Toronto, 2020, 2021, 2020-01-01T00:00:00.0-05:00, 2021-12-31T23:59:59.0-05:00",
"America/Denver, 2020, 2021, 2020-01-01T00:00:00-07:00, 2021-12-31T23:59:59-07:00", "America/Denver, 2020, 2021, 2020-01-01T00:00:00.0-07:00, 2021-12-31T23:59:59.0-07:00",
"null, 2022-02, 2022-08, 2022-02-01T00:00:00Z, 2022-08-31T23:59:59Z", "null, 2022-02, 2022-08, 2022-02-01T00:00:00.0Z, 2022-08-31T23:59:59.0Z",
"Z, 2022-02, 2022-08, 2022-02-01T00:00:00Z, 2022-08-31T23:59:59Z", "Z, 2022-02, 2022-08, 2022-02-01T00:00:00.0Z, 2022-08-31T23:59:59.0Z",
"UTC, 2022-02, 2022-08, 2022-02-01T00:00:00Z, 2022-08-31T23:59:59Z", "UTC, 2022-02, 2022-08, 2022-02-01T00:00:00.0Z, 2022-08-31T23:59:59.0Z",
"America/St_Johns, 2022-02, 2022-08, 2022-02-01T00:00:00-03:30, 2022-08-31T23:59:59-02:30", "America/St_Johns, 2022-02, 2022-08, 2022-02-01T00:00:00.0-03:30, 2022-08-31T23:59:59.0-02:30",
"America/Toronto, 2022-02, 2022-08, 2022-02-01T00:00:00-05:00, 2022-08-31T23:59:59-04:00", "America/Toronto, 2022-02, 2022-08, 2022-02-01T00:00:00.0-05:00, 2022-08-31T23:59:59.0-04:00",
"America/Denver, 2022-02, 2022-08, 2022-02-01T00:00:00-07:00, 2022-08-31T23:59:59-06:00", "America/Denver, 2022-02, 2022-08, 2022-02-01T00:00:00.0-07:00, 2022-08-31T23:59:59.0-06:00",
"null, 2022-02, 2022-02, 2022-02-01T00:00:00Z, 2022-02-28T23:59:59Z", "null, 2022-02, 2022-02, 2022-02-01T00:00:00.0Z, 2022-02-28T23:59:59.0Z",
"Z, 2022-02, 2022-02, 2022-02-01T00:00:00Z, 2022-02-28T23:59:59Z", "Z, 2022-02, 2022-02, 2022-02-01T00:00:00.0Z, 2022-02-28T23:59:59.0Z",
"UTC, 2022-02, 2022-02, 2022-02-01T00:00:00Z, 2022-02-28T23:59:59Z", "UTC, 2022-02, 2022-02, 2022-02-01T00:00:00.0Z, 2022-02-28T23:59:59.0Z",
"America/St_Johns, 2022-02, 2022-02, 2022-02-01T00:00:00-03:30, 2022-02-28T23:59:59-03:30", "America/St_Johns, 2022-02, 2022-02, 2022-02-01T00:00:00.0-03:30, 2022-02-28T23:59:59.0-03:30",
"America/Toronto, 2022-02, 2022-02, 2022-02-01T00:00:00-05:00, 2022-02-28T23:59:59-05:00", "America/Toronto, 2022-02, 2022-02, 2022-02-01T00:00:00.0-05:00, 2022-02-28T23:59:59.0-05:00",
"America/Denver, 2022-02, 2022-02, 2022-02-01T00:00:00-07:00, 2022-02-28T23:59:59-07:00", "America/Denver, 2022-02, 2022-02, 2022-02-01T00:00:00.0-07:00, 2022-02-28T23:59:59.0-07:00",
// Leap year // Leap year
"null, 2024-02, 2024-02, 2024-02-01T00:00:00Z, 2024-02-29T23:59:59Z", "null, 2024-02, 2024-02, 2024-02-01T00:00:00.0Z, 2024-02-29T23:59:59.0Z",
"Z, 2024-02, 2024-02, 2024-02-01T00:00:00Z, 2024-02-29T23:59:59Z", "Z, 2024-02, 2024-02, 2024-02-01T00:00:00.0Z, 2024-02-29T23:59:59.0Z",
"UTC, 2024-02, 2024-02, 2024-02-01T00:00:00Z, 2024-02-29T23:59:59Z", "UTC, 2024-02, 2024-02, 2024-02-01T00:00:00.0Z, 2024-02-29T23:59:59.0Z",
"America/St_Johns, 2024-02, 2024-02, 2024-02-01T00:00:00-03:30, 2024-02-29T23:59:59-03:30", "America/St_Johns, 2024-02, 2024-02, 2024-02-01T00:00:00.0-03:30, 2024-02-29T23:59:59.0-03:30",
"America/Toronto, 2024-02, 2024-02, 2024-02-01T00:00:00-05:00, 2024-02-29T23:59:59-05:00", "America/Toronto, 2024-02, 2024-02, 2024-02-01T00:00:00.0-05:00, 2024-02-29T23:59:59.0-05:00",
"America/Denver, 2024-02, 2024-02, 2024-02-01T00:00:00-07:00, 2024-02-29T23:59:59-07:00", "America/Denver, 2024-02, 2024-02, 2024-02-01T00:00:00.0-07:00, 2024-02-29T23:59:59.0-07:00",
"null, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00Z, 2024-02-26T23:59:59Z", "null, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00.0Z, 2024-02-26T23:59:59.0Z",
"Z, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00Z, 2024-02-26T23:59:59Z", "Z, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00.0Z, 2024-02-26T23:59:59.0Z",
"UTC, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00Z, 2024-02-26T23:59:59Z", "UTC, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00.0Z, 2024-02-26T23:59:59.0Z",
"America/St_Johns, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00-03:30, 2024-02-26T23:59:59-03:30", "America/St_Johns, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00.0-03:30, 2024-02-26T23:59:59.0-03:30",
"America/Toronto, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00-05:00, 2024-02-26T23:59:59-05:00", "America/Toronto, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00.0-05:00, 2024-02-26T23:59:59.0-05:00",
"America/Denver, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00-07:00, 2024-02-26T23:59:59-07:00", "America/Denver, 2024-02-25, 2024-02-26, 2024-02-25T00:00:00.0-07:00, 2024-02-26T23:59:59.0-07:00",
"null, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00Z, 2024-09-26T23:59:59Z", "null, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00.0Z, 2024-09-26T23:59:59.0Z",
"Z, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00Z, 2024-09-26T23:59:59Z", "Z, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00.0Z, 2024-09-26T23:59:59.0Z",
"UTC, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00Z, 2024-09-26T23:59:59Z", "UTC, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00.0Z, 2024-09-26T23:59:59.0Z",
"America/St_Johns, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00-02:30, 2024-09-26T23:59:59-02:30", "America/St_Johns, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00.0-02:30, 2024-09-26T23:59:59.0-02:30",
"America/Toronto, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00-04:00, 2024-09-26T23:59:59-04:00", "America/Toronto, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00.0-04:00, 2024-09-26T23:59:59.0-04:00",
"America/Denver, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00-06:00, 2024-09-26T23:59:59-06:00", "America/Denver, 2024-09-25, 2024-09-26, 2024-09-25T00:00:00.0-06:00, 2024-09-26T23:59:59.0-06:00",
"null, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00Z, 2024-01-02T12:00:00Z", "null, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00.0Z, 2024-01-02T12:00:00.0Z",
"Z, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00Z, 2024-01-02T12:00:00Z", "Z, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00.0Z, 2024-01-02T12:00:00.0Z",
"UTC, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00Z, 2024-01-02T12:00:00Z", "UTC, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00.0Z, 2024-01-02T12:00:00.0Z",
"America/St_Johns, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00-03:30, 2024-01-02T12:00:00-03:30", "America/St_Johns, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00.0-03:30, 2024-01-02T12:00:00.0-03:30",
"America/Toronto, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00-05:00, 2024-01-02T12:00:00-05:00", "America/Toronto, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00.0-05:00, 2024-01-02T12:00:00.0-05:00",
"America/Denver, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00-07:00, 2024-01-02T12:00:00-07:00", "America/Denver, 2024-01-01T12:00:00, 2024-01-02T12:00:00, 2024-01-01T12:00:00.0-07:00, 2024-01-02T12:00:00.0-07:00",
"null, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00Z, 2024-09-26T12:00:00Z", "null, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00.0Z, 2024-09-26T12:00:00.0Z",
"Z, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00Z, 2024-09-26T12:00:00Z", "Z, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00.0Z, 2024-09-26T12:00:00.0Z",
"UTC, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00Z, 2024-09-26T12:00:00Z", "UTC, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00.0Z, 2024-09-26T12:00:00.0Z",
"America/St_Johns, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00-02:30, 2024-09-26T12:00:00-02:30", "America/St_Johns, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00.0-02:30, 2024-09-26T12:00:00.0-02:30",
"America/Toronto, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00-04:00, 2024-09-26T12:00:00-04:00", "America/Toronto, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00.0-04:00, 2024-09-26T12:00:00.0-04:00",
"America/Denver, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00-06:00, 2024-09-26T12:00:00-06:00", "America/Denver, 2024-09-25T12:00:00, 2024-09-26T12:00:00, 2024-09-25T12:00:00.0-06:00, 2024-09-26T12:00:00.0-06:00",
} }
) )
void validateAndProcessTimezone_happyPath(@Nullable String theTimezone, String theInputPeriodStart, String theInputPeriodEnd, String theOutputPeriodStart, String theOutputPeriodEnd) { void validateAndProcessTimezone_happyPath(@Nullable String theTimezone, String theInputPeriodStart, String theInputPeriodEnd, String theOutputPeriodStart, String theOutputPeriodEnd) {
@ -102,11 +119,9 @@ class MeasureReportPeriodRequestProcessingServiceTest {
private static Stream<Arguments> errorParams() { private static Stream<Arguments> errorParams() {
return Stream.of( return Stream.of(
Arguments.of(null, null, null, new InvalidRequestException("Either start: [null] or end: [null] or both are blank")),
Arguments.of(null, "", "", new InvalidRequestException("Either start: [] or end: [] or both are blank")),
Arguments.of(null, "2024", "2024-01", new InvalidRequestException("Period start: 2024 and end: 2024-01 are not the same date/time formats")), Arguments.of(null, "2024", "2024-01", new InvalidRequestException("Period start: 2024 and end: 2024-01 are not the same date/time formats")),
Arguments.of(null, "2024-01-01T12", "2024-01-01T12", new InvalidRequestException("Unsupported Date/Time format for period start: 2024-01-01T12 or end: 2024-01-01T12")), Arguments.of(null, "2024-01-01T12", "2024-01-01T12", new InvalidRequestException("Unsupported Date/Time format for period start: 2024-01-01T12 or end: 2024-01-01T12")),
Arguments.of(null, "2024-01-02", "2024-01-01", new InvalidRequestException("Start date: 2024-01-02 is after end date: 2024-01-01")), Arguments.of(null, "2024-01-02", "2024-01-01", new InvalidRequestException("Invalid Interval - the ending boundary: 2024-01-01 must be greater than or equal to the starting boundary: 2024-01-02")),
Arguments.of("Middle-Earth/Combe", "2024-01-02", "2024-01-03", new InvalidRequestException("Invalid value for Timezone header: Middle-Earth/Combe")), Arguments.of("Middle-Earth/Combe", "2024-01-02", "2024-01-03", new InvalidRequestException("Invalid value for Timezone header: Middle-Earth/Combe")),
Arguments.of(null, "2024-01-01T12:00:00-02:30", "2024-01-02T12:00:00-04:00", new InvalidRequestException("Unsupported Date/Time format for period start: 2024-01-01T12:00:00-02:30 or end: 2024-01-02T12:00:00-04:00")), Arguments.of(null, "2024-01-01T12:00:00-02:30", "2024-01-02T12:00:00-04:00", new InvalidRequestException("Unsupported Date/Time format for period start: 2024-01-01T12:00:00-02:30 or end: 2024-01-02T12:00:00-04:00")),
Arguments.of("Z", "2024-01-01T12:00:00-02:30", "2024-01-02T12:00:00-04:00", new InvalidRequestException("Unsupported Date/Time format for period start: 2024-01-01T12:00:00-02:30 or end: 2024-01-02T12:00:00-04:00")), Arguments.of("Z", "2024-01-01T12:00:00-02:30", "2024-01-02T12:00:00-04:00", new InvalidRequestException("Unsupported Date/Time format for period start: 2024-01-01T12:00:00-02:30 or end: 2024-01-02T12:00:00-04:00")),