Understanding specific UTC time format YYYY-MM-DDTHH:MM:SS.SSSZ
Asked Answered
N

2

17

I have two related questions.

Assume a program running in (British Standard Time)BST generates a date time value for current time in UTC (YYYY-MM-DDTHH:MM:SS.SSSZ) format.

Also assume current time in London is 2016-06-01 12:33:54.

  1. If the current time given by the program is 2016-06-01T11:33:54.000Z , is the program wrong?

  2. How is summertime offset for BST noted in the corresponding time format for YYYY-MM-DDTHH:MM:SS.SSSZ

I assume YYYY-MM-DDTHH:MM:SS+0001. Am I correct ?

Natatory answered 2/6, 2016 at 10:48 Comment(4)
1) no, as there is a summer offset. UTC doesn't change with summer offset. 2) YYYY-MM-DDTHH:MM:SS+01:00Disharmony
So the time given by the program for the above example should be 2016-06-01T11:33:54.000+01:00 you mean?Natatory
No it should be either 2016-06-01T11:33:54.000Z or 2016-06-01T12:33:54.000+01:00 or 2016-06-01T13:33:54.000+02:00 or 2016-06-01T15:03:54.000+03:30 or or or anythingDisharmony
thanks !! This helped.Natatory
C
16

Firstly please have a read of the iso8601 information. It's becoming more common place to deal with times in different time zones (e.g. server time zone and client time zone) and the standard is really useful.

In particular please read about UTC or "Zulu" time here.

  1. The program is correct, since the London time is one hour ahead of "UTC" time in summer

  2. The trailing 'Z' is a short notation for UTC (Zulu). You could also write "+00:00" instead of 'Z'. The SS.SSS refer to seconds and milliseconds - not related to the time zone. In devnull's comment he shows you how to apply an offset for summer.

Edit:

There's been some discussion in the comments about whether iso8601 timezone includes timezone or not, and whether timezone will in fact be printed out.

This depends completely on the date/time implementation. If we are using SimpleDateFormat then timezone is supported and will be printed.

Here's a code example to illustrate

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(formatter.format(new Date()));
formatter.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println(formatter.format(new Date()));

Output

2016-06-02T12:53:14.924Z
2016-06-02T13:53:14.925+01:00

Naturally, if you are using a different date/time library such as joda-time, then the implentation details will be different.

Edit: As @DerrylThomas pointed out with SimpleDateFormat wise to use lower case y for years - unless it's intended to use week year - explained in a bit of detail in another answer to a similar question https://stackoverflow.com/a/56911450.

Curvy answered 2/6, 2016 at 12:18 Comment(13)
2) No, you can't. ISO 8601 clearly says that zero offset is Z only.Pushup
You can still use either Z or +00:00Disharmony
In your notation SS.SSS it's milliseconds rather than microseconds. But you can use any fraction you likeDisharmony
@Curvy The Wikipedia entry is either ambigiuous or false. I have just opened up ISO 8601:2006, original German version, chapter 4.2.4 (translated): "Time in UTC. To express time in UTC you have to.., no space followed by UTC character [Z]..."Pushup
@Pushup Fair enough, maybe it is misleading - in any case java data formats support usage of the timezone.Curvy
@Curvy Parsing yes, but not printing. XXX will always write Z. I'd recommend to change your answer.Pushup
Printing - how... SimpleDateFormat? It uses the timezone of the Locale, not 'Z'. Example: I live in Oslo, output is 2016-06-154T14:06:98.098+0200.Curvy
@Curvy After the edit it is a lot more clear. , then in the example in question, the correct output should be 2016-06-01T12:33:54.000+01:00 right? Which means I will have to assume for 1) the program is buggy and I have to correct? I have accepted anser. You could correct the details? Thanks a lot!Natatory
It depends completely on how the code in the program works. Do you have access to the program's code, can we see if it uses a SimpleDateFormat and if so what is the String? In any case, both 2016-06-01T11:33:54.000Z and 2016-06-01T12:33:54.000+01:00 are correct because they are the same point in time! A preference for one or the other depends completely on your program and the problem domain you are working in (do you have a specification?).Curvy
This is an issue I faced in an application UI while testing. Since I was more familiar with Java I asked it with a java tag first. Thought this is a generic issue and I can apply the answer in the context of the application.I do not have access to the exact methods being used unfortunately.Natatory
It looks like your program will always give a date/time in Zulu and that's actually the best situation from an interoperability standpoint (for example if you need to send the date/time to another program) but from a UI standpoint then the output will most possibly need to be localised somehow.Curvy
Random FYI - you should perhaps use yyyy instead of YYYY in the SimpleDateFormat. They don't mean the same and could break your program towards the end of the year. Learnt this the hard way. Stay safe!Cathiecathleen
Please, you shouldn’t teach the young ones to use the long outdated and notoriously troublesome SimpleDateFormat class. At least not as the first option. And not without any reservation. We have so much better in java.time, the modern Java date and time API, and its DateTimeFormatter. Also the java.time classes produce ISO 8601 format from toString(), so without any explicit formatter.Constellation
S
1

if the current time given by the program is 2016-06-01T11:33:54.000Z , is the program wrong?

The format is correct and conforms to ISO 8601 but it does not represent Europe/London time. In London, in 2016, the DST started at Sunday, March 27, 1:00 am and ended at Sunday, October 30, 2:00 am and therefore a date-time representation for Europe/London during this time should have a timezone offset of +01:00 hours. The Z at the end specifies Zulu time which is UTC time and thus has a timezone offset of +00:00 hours. The same instant can be represented for Europe/London as 2016-06-01T12:33:54+01:00.

java.time

The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to java.time, the modern date-time API* .

Even Joda-Time should not be used anymore. Notice the following note at the Home Page of Joda-Time

Joda-Time is the de facto standard date and time library for Java prior to Java SE 8. Users are now asked to migrate to java.time (JSR-310).

java.time API is based on ISO 8601 and the date-time string, 2016-06-01T11:33:54.000Z can be parsed into java.time.ZonedDateTime and java.time.OffsetDateTime without needing a date-time parsing/formatting type.

Demo:

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        ZonedDateTime zdt = ZonedDateTime.parse("2016-06-01T11:33:54.000Z");
        System.out.println(zdt);

        ZoneId zoneId = ZoneId.of("Europe/London");
        ZonedDateTime zdtInLondon = zdt.withZoneSameInstant(zoneId);
        System.out.println(zdtInLondon);
    }
}

Output:

2016-06-01T11:33:54Z
2016-06-01T12:33:54+01:00[Europe/London]

How to deal with Daylight Saving Time (DST)?

As mentioned earlier, the date-time string, 2016-06-01T11:33:54.000Z can also be parsed into java.time.OffsetDateTime without needing a date-time parsing/formatting type. However, OffsetDateTime has been designed to deal with a fixed timezone offset whereas ZonedDateTime has been designed to deal with a timezone and thus it take care of DST automatically. You can convert a ZonedDateTime to OffsetDateTime using ZonedDateTime#toOffsetDateTime if required.

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS z", Locale.ENGLISH);

        String strDateTime = "2016-03-01T11:33:54.000 Europe/London";
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);

        strDateTime = "2016-06-01T11:33:54.000 Europe/London";
        zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);
    }
}

Output:

2016-03-01T11:33:54Z[Europe/London]
2016-06-01T11:33:54+01:00[Europe/London]

Notice how the timezone offset has automatically changed from Z to 01:00 to reflect DST change. On the other hand,

import java.time.OffsetDateTime;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2016-03-01T11:33:54.000+01:00";
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
        System.out.println(odt);

        strDateTime = "2016-06-01T11:33:54.000+01:00";
        odt = OffsetDateTime.parse(strDateTime);
        System.out.println(odt);
    }
}

Output:

2016-03-01T11:33:54+01:00
2016-06-01T11:33:54+01:00

In this case, you do not talk about a timezone (e.g. Europe/London); rather, you talk about a fixed timezone offset of +01:00 hours.

Learn more about the modern date-time API from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Simms answered 10/4, 2021 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.