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
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.
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.
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.
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.