2

I've got a quarkus application where I'm converting a String timestamp with a GMT offset to Europe/Berlin time.

For example this time: "2022-08-13 10:13:56.48382+03"

I've got unit tests that runs completely fine locally but fails remotely in the pipeline?

I thought I wrote code to explicitly create a time instance with the given timezone, but I'm thinking it still picks up the local timezone of the pipeline server somehow?

I've also been looking into maybe changing the pipeline timezone to solve the test? https://support.circleci.com/hc/en-us/articles/115015772847-Setting-Timezone-in-2-0-MacOS-Builds

Does anyone have answers why these tests fails?

When application starts this will get invoked TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));

Logic to convert time

public static Date convertTime(String timestamp) {

    // offset being f.e. +01, +12, -03
    String gmtZone = "GMT" + getOffset(timestamp);
    // removes the milliseconds from time
    timestamp = stripMilliseconds(timestamp);

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern(INCOMING_TIMESTAMP_FORMAT);
    LocalDateTime localDateTime = LocalDateTime.parse(timestamp, dtf);
    ZonedDateTime zdtGmt = ZonedDateTime.of(localDateTime, ZoneId.of(gmtZone));
    ZonedDateTime zdtBerlin = zdtGmt.withZoneSameInstant(ZoneId.of(TIME_ZONE_EUROPE_BERLIN));

    return Date.from(zdtBerlin.toInstant());
}

TESTS

@ParameterizedTest
@MethodSource("timestampsWithOffsetWithCorrectlyConvertedTime")
void offsetShouldBeCorrectlyConvertedToBerlinTime(String timestamp, Date expectedConvertedTime) {

    Date date = TimeZoneConverter.convertTime(timestamp);

    assertEquals(expectedConvertedTime, date);
}


private static Stream<Arguments> timestampsWithOffsetWithCorrectlyConvertedTime() throws ParseException {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return Stream.of(
            Arguments.of("2022-08-13 10:13:56.48382+00", sdf.parse("2022-08-13 12:13:56")),
            Arguments.of("2022-09-20 22:33:16.4271382-03", sdf.parse("2022-09-21 03:33:16")),
            Arguments.of("2022-11-25 16:00:00.482+12", sdf.parse("2022-11-25 05:00:00")),
            Arguments.of("2022-03-03 11:33:16.483829+02", sdf.parse("2022-03-03 10:33:16"))

    );
}
bob
  • 198
  • 1
  • 10
  • Which is incorrect in `assertEquals(expectedConvertedTime, date);`? The actual or the expected value? It could be a problem with the sdf... – assylias Sep 22 '22 at 09:21
  • 2
    You said that the default timezone is set when the application starts. Is it also set when the tests run? Maybe you need a setUp method in your tests that sets it. – Dawood ibn Kareem Sep 22 '22 at 09:23
  • Another thing you could try is setting the timezone on your local machine, then stepping through the test with the debugger to see what goes wrong with the assertion. – Dawood ibn Kareem Sep 22 '22 at 09:24
  • 2
    **`LocalDateTime` is the wrong class** to use here. Your input contains an indicator of offset from UTC, `+03`. Your use of `LocalDateTime` ignores that vital information. Instead, use `OffsetDateTime`. If you don’t understand this, post another Question specific to the parsing alone, without Quarkus details. – Basil Bourque Sep 22 '22 at 15:47
  • 2
    Do you indispensably need your method to return an old-fashioned `Date`? I recommend you avoid that. Use `Instant`. I unconditionally recommend you don’t use `SimpleDateFormat` in your test, that class is notoriously troublesome. Use the `of` method of one of the modern date-time classes. I believe that your `convertTime` method can be considerably simplified. – Ole V.V. Sep 22 '22 at 16:12
  • 2
    `OffsetDateTime.parse("2022-09-20 22:33:16.4271382-03", FORMATTER).toInstant()` where `FORMATTER` is built from `new DateTimeFormatterBuilder() .append(DateTimeFormatter.ISO_LOCAL_DATE) .appendLiteral(' ') .append(DateTimeFormatter.ISO_LOCAL_TIME) .appendOffset("+HH", "+00")`. – Ole V.V. Sep 22 '22 at 18:49
  • 2
    Brussels and Berlin are not in the same time zone (and as my code in the previous comment demonstrates, there is no need to go via any of those two in your conversion, it’s nothing but a detour). – Ole V.V. Sep 22 '22 at 18:54
  • Thank you @BasilBourque and Olev V.V! I'll do some research on this topic so I know the correct way to implement this. :) I'll post another question if I feel it's a bit tricky for me to understand. – bob Sep 29 '22 at 07:17

1 Answers1

1

Thanks to @Dawood ibn Kareem!

I managed to solve this issue by adding @QuarkusTest above the test class declaration.

I believe this runs the tests with the context that I've set up in the Quarkus Application. Meaning that TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")); now is invoked when running the tests.

bob
  • 198
  • 1
  • 10