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 ?

EternalObserver
  • 517
  • 7
  • 19
QVSJ
  • 1,165
  • 2
  • 12
  • 22
  • 1
    1) no, as there is a summer offset. UTC doesn't change with summer offset. 2) YYYY-MM-DDTHH:MM:SS+01:00 – devnull69 Jun 02 '16 at 12:17
  • So the time given by the program for the above example should be 2016-06-01T11:33:54.000+01:00 you mean? – QVSJ Jun 02 '16 at 12:50
  • 1
    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 anything – devnull69 Jun 02 '16 at 12:56
  • thanks !! This helped. – QVSJ Jun 02 '16 at 12:57

2 Answers2

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.

Mr R
  • 754
  • 7
  • 19
vikingsteve
  • 38,481
  • 23
  • 112
  • 156
  • 2) No, you can't. ISO 8601 clearly says that zero offset is `Z` only. – Michael-O Jun 02 '16 at 12:20
  • You can still use either Z or +00:00 – devnull69 Jun 02 '16 at 12:21
  • 2
    In your notation `SS.SSS` it's milliseconds rather than microseconds. But you can use any fraction you like – devnull69 Jun 02 '16 at 12:24
  • @vikingsteve 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]..." – Michael-O Jun 02 '16 at 12:30
  • @Michael-O Fair enough, maybe it is misleading - in any case java data formats support usage of the timezone. – vikingsteve Jun 02 '16 at 12:36
  • @vikingsteve Parsing yes, but not printing. `XXX` will always write `Z`. I'd recommend to change your answer. – Michael-O Jun 02 '16 at 12:38
  • 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`. – vikingsteve Jun 02 '16 at 12:43
  • @vikingsteve 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! – QVSJ Jun 02 '16 at 12:56
  • 1
    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?). – vikingsteve Jun 02 '16 at 13:01
  • 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. – QVSJ Jun 02 '16 at 13:10
  • 1
    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. – vikingsteve Jun 02 '16 at 13:14
  • 1
    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! – Derryl Thomas Feb 25 '20 at 10:00
  • 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,](https://docs.oracle.com/javase/tutorial/datetime/) and its `DateTimeFormatter`. Also the java.time classes produce ISO 8601 format from `toString()`, so without any explicit formatter. – Ole V.V. Apr 10 '21 at 14:28
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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110