3

I have to input the date time in this format :

"2018-07-17T12:16:50.52Z"

Hence I am using :

private static final SimpleDateFormat LIVETRACK_DATE_TIME_FORMATTER =
  new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

DATE_TIME_FORMATTER.parse(timeFrameFrom);

But I'm getting the below error when I run test case :

Tue Jul 17 1[2:20:50 CES]T 2018> but was:<Tue Jul 17 1[0:20:50 GM]T 2018>

Does that mean I should convert the date to GMT format? How do I convert it?

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
pgman
  • 493
  • 3
  • 12
  • 21
  • I recommend you avoid the `SimpleDateFormat` class. It is not only long outdated, it is also notoriously troublesome. Today we have so much better in [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). Also don’t hardcode `Z` as a literal in your format pattern string. It’s a UTC offset and needs to be parsed as such, or you get incorrect results. – Ole V.V. Jul 17 '18 at 12:18
  • You code doesn’t produce the `Tue Jul 17 10:20:50 GMT 2018 Uhr` that your unit test reports as the observed result, at least not the “Uhr”. Could you [create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve), please? Then we can help you a lot better. – Ole V.V. Jul 17 '18 at 14:19
  • What’s with the square brackets in your example? Typo? – Basil Bourque Jul 17 '18 at 15:02
  • @BasilBourque When comparing expected and actual strings JUnit (and possibly other test frameworks?) insert/s square brackets around the part that differs. So apparently the test compares strings, but `DATE_TIME_FORMATTER.parse` doesn’t produce a string, so there’s something we haven’t been told yet. – Ole V.V. Jul 17 '18 at 16:42

4 Answers4

3
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "EEE MMM dd HH:mm:ss zzz yyyy 'Uhr'", Locale.ROOT);

    String input = "2018-07-17T12:16:50.52Z";
    ZonedDateTime dateTime = Instant.parse(input)
            .atZone(ZoneId.of("Europe/Berlin"));
    String output = dateTime.format(formatter);
    System.out.println(output);

Output:

Tue Jul 17 14:16:50 CEST 2018 Uhr

Your test case is expecting the wrong result. The Z in your input string means UTC (offset zero from UTC or the so-called Zulu time zone). The time of 12:16:50.52 in UTC is the same as 14:16:50.52 in Central European Summer Time (CEST). So requiring Tue Jul 17 12:20:50 CEST 2018 Uhr is wrong.

In your code you hardcoded Z as a literal rather than parsing it as an offset as you should. Funnily this produced the wrong point in time that the unit test expected, only not in the expected time zone. This may have to do with Date.toString using the time zone setting of your JVM and the test expecting this to be CEST, when it really was GMT. However your SimpleDateFormat didn’t use GMT for parsing the string (probably CEST), so you haven’t given us enough information to explain everything that has happened in your test. SimpleDateFormat would use the same JVM setting unless you have explicitly set its time zone, which doesn’t happen in the code you have posted.

Link: Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

If you are using Java8 you can use java.time API where you can parse your String using the default date time format of Instant :

ZonedDateTime zdt = Instant.parse("2018-07-17T12:16:50.52Z")
        .atZone(ZoneId.of("Europe/Berlin"));

Outputs

2018-07-17T14:16:50.520+02:00[Europe/Berlin]
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • But Z indicates GMT timezone right? and i want the time in Tue Jul 17 1[0:20:50 GM]T 2018 – pgman Jul 17 '18 at 11:11
  • @pgman you mean `ZonedDateTime zdt = Instant.parse("2018-07-17T12:16:50.52Z").atZone(ZoneId.of("GMT"));` or just `Instant ins = Instant.parse("2018-07-17T12:16:50.52Z");` I don't understand about what you talk! – Youcef LAIDANI Jul 17 '18 at 11:18
0

Here is an example for converting a date from Calendar to different time zones.

TimeZone tzLA = TimeZone.getTimeZone("America/Los_Angeles");
    TimeZone tzIN = TimeZone.getTimeZone("Asia/Calcutta");

    Calendar calendar = new GregorianCalendar();

    calendar.setTimeZone(tzLA);

    long timeLA = calendar.getTimeInMillis();

    System.out.println("Time at America in milliseconds = " +timeLA);
    System.out.println("Hour at America = " +calendar.get(Calendar.HOUR_OF_DAY));

    calendar.setTimeZone(tzIN);

    long timeIN = calendar.getTimeInMillis();
    System.out.println("Time at Asia in millis = " + timeIN);
    System.out.println("Hour at Asia = " + calendar.get(Calendar.HOUR_OF_DAY));

here is the output.

Time at America in milliseconds = 1515136660357
Hour at America = 23
Time at Asia in millis = 1515136660357
Hour at Asia = 12
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Umer Farooq
  • 168
  • 1
  • 12
0

Does that mean i should convert the date to GMT format??

No, it means the 'Z' shouldn't be taken as a constant separator like the 'T', but as a full-fledge field that indicates the date's time zone. Where Z means GMT time zone.

Your format should really have been

"yyyy-MM-dd'T'HH:mm:ss.SSX"

This would have let the SimpleDateFormat recognize that the Z indicates GMT time zone, and therefore the Date it produces as a result would be aligned with GMT time zone. When converting it to String and thus to German time zone, it will add the difference and produce expected results.

That being said, a better solution is to move on from obsolete classes java.util.Date and SimpleDateFormat, and use Java 8's java.time.* APIs instead. See the other answer for inspiration.

kumesana
  • 2,495
  • 1
  • 9
  • 10
  • by using this format it just increases the hours by 2 hours doesnt convert to GMT – pgman Jul 17 '18 at 10:55
  • u mean using Z indicates GMT? and here with my format it is not actually converting to GMT?? but by using this format with SSX it just increases the hours by 2 hours doesnt convert to GMT – pgman Jul 17 '18 at 11:01
  • 1
    @pgman with java.util.Date there is no such thing as "convert to GMT". This class doesn't contain information about time zones. It represents an instant in time, regardless of how that instant would be pronounced in New York, Berlin or Greenwich. There is no time zone there. Which means that when converting a java.util.Date to or from String, a time zone needs to be specified to tell where in the world is that instant written like that (as it would be written differently in a different time zone). Here your tests indicate that they expect a date written as CEST. So, let them have that. – kumesana Jul 17 '18 at 11:32