Search code examples
javadatetimetimezonejava-timezoneddatetime

Is GMT and UTC same for ZonedDateTime?


I've implemented an API for International use and I'm trying to return dates of objects in GMT Time ,in ISO 8601 format. Right now I do this by

ZonedDateTime.withZoneSameInstant(ZoneOffset.UTC)

But I do know that UTC and GMT are not the same thing.

Later I will be assigning every user with their preferred Locale and return with their Locale , but now I want to do this as GMT , but I don't know how to do It the right way


Solution

  • TL;DR

    To a ZonedDateTime UTC and GMT have different names but the same zone rules, so the time will always be the same in UTC and in GMT.

    Theory

    Originally GMT and UTC were defined differently. There were never more than a second between the UTC time and the GMT time. As UTC has become the ubiquitous anchor of time, GMT is sometimes used loosely to mean UTC, so the distinction is more blurred.

    Practice: ZonedDateTme

    A ZonedDateTime uses a ZoneId for its time zone, so your question is equal to asking whether to ZoneId GMT and UTC are the same. Let’s for a start see how they may look:

        ZoneId utc = ZoneId.of("Etc/UTC");
        System.out.println("Etc/UTC:        " + utc);
    
        ZoneId gmt = ZoneId.of("Etc/GMT");
        System.out.println("Etc/GMT:        " + gmt);
    
        ZoneId utcNormalized = utc.normalized();
        System.out.println("UTC normalized: " + utcNormalized);
    
        ZoneOffset utcAsOffset = ZoneOffset.UTC;
        System.out.println("UTC as offset:  " + utcAsOffset);
    
        ZoneId gmtNormalized = gmt.normalized();
        System.out.println("GMT normalized: " + gmtNormalized);
    

    Output is:

    Etc/UTC:        Etc/UTC
    Etc/GMT:        Etc/GMT
    UTC normalized: Z
    UTC as offset:  Z
    GMT normalized: Z
    

    The first two lines show us that ZoneId can indeed distinguish between GMT and UTC. They are both valid time zones with each their time zone ID.

    The normalized() method that I use for the 3rd and 5th lines promises to convert a ZoneId to a ZoneOffset if the time zone uses a constant offset. In both cases we get an offset of zero back. So here ZoneId does not distinguish.

    To check the matter even more closely:

        System.out.println("Are GMT and UTC the same? " + utc.equals(gmt));
        System.out.println("Are GMT and UTC the same? "
                + utcNormalized.equals(gmtNormalized));
        System.out.println("Are GMT and UTC the same? "
                + utc.getRules().equals(utcAsOffset.getRules()));
    
    Are GMT and UTC the same? false
    Are GMT and UTC the same? true
    Are GMT and UTC the same? true
    

    So the ZoneId objects are not equal, and ZonedDateTime objects using the two will not be equal either even when they have the same date and time. But we get the same offset from them and they have equal zone rules, that is, they will always have the same time.

    Consequences in Java code

    This line is from your question:

    ZonedDateTime.withZoneSameInstant(ZoneOffset.UTC)
    

    This is correct and there is no compelling reason why you should want to do otherwise. If you prefer, since Java regards UTC as a zone offset, you may convert to an OffsetDateTime instead. I somehow regard it as less heavy-weight than ZonedDateTime.

    If you want your ZonedDateTime to print in GMT rather than UTC, use ZoneId.of("Etc/GMT"). Here I am using my variable from before holding that time zone:

        ZonedDateTime zdtGmt = ZonedDateTime.now(ZoneId.of("Asia/Istanbul"))
                .withZoneSameInstant(gmt);
        System.out.println("Time in GMT: " + zdtGmt);
        DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
                .withLocale(Locale.forLanguageTag("tr"));
        System.out.println("Time in GMT: " + zdtGmt.format(formatter));
    

    Output just now:

    Time in GMT: 2020-05-16T09:34:05.253696Z[Etc/GMT]
    Time in GMT: 16 Mayıs 2020 Cumartesi 09:34:05 Greenwich Ortalama Saati
    

    You further wrote:

    Later I will be assigning every user with their preferred Locale and return with their Locale …

    Locale is not relevant here. Locale and time zone are orthogonal concepts. A person from Turkey visiting Shanghai may for example want to use Turkish locale and Shanghai time zone. There is no way to deduce a time zone from a locale (at least no sound way). You will probably want to consider assigning each user a preferred time zone.