Reputation: 4385
I understand that it's pretty easy to display local time to a user given an offset from GMT for the timezone (e.g. -7 hours for Pacific Daylight Time).
But, what if I want to continue to display the correct local time for a long period of time (say 1 year). Given just an offset from GMT, you do not know what timezone the user is in. E.g. given -7, the user may live in the US or in Canada (or in some other country). These countries my have different local times at different points of the year (e.g. if the US changes to daylight time in March and CA in April).
My question is, is the above paragraph correct? Is there a standard way to take a GMT offset and make a good guess as to which timezone the user is in?
Upvotes: 2
Views: 263
Reputation: 339362
Your conclusion is correct: There is no reliable way to identify a time zone from an offset-from-UTC.
For your example of an offset of -07:00
, I count about three dozen possible time zones in the current list including: America/Boise
, America/Chihuahua
, and America/Edmonton
.
A time zone is actually a collection of offsets, recording changes made over time with a certain offset used in that region for a certain period of time but then changed over another certain period of time.
For example, in America/Los_Angeles
part of each year has an offset of -08:00
while another part of the year has -07:00
. So that time zone is accumulating a history of at least two offsets per annum. In contrast, the neighboring region using the time zone America/Phoenix
is not accumulating changes in its offset, having retained the same -07:00
offset for decades.
So we have a many-to-many relationship between offsets and time zones. An offset may appear in one or more time zones. And each time zone can have one or more offsets (having changed over history).
This is why the designers of the java.time class ZonedDateTime
have taken the liberty of having its toString
method extend the standard ISO 8601 format using only offsets to also append the name of the time zone in square brackets.
For example, instead of simply generating the standard format: 2007-12-03T10:15:30+01:00
, the class generates 2007-12-03T10:15:30+01:00[Europe/Paris]
with the name of the zone Europe/Paris appended.
ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
.toString()
2007-12-03T10:15:30+01:00[Europe/Paris]
I hope this practice of appending the time zone name catches on. The lack of time zone name is a surprising omission by the standards committees that otherwise did an outstanding job in designing ISO 8601.
You can guess about the time zone using clues from the context of your business scenario. But I advise against that. Guessing is risky, especially because politicians around the world have a penchant for frequently re-defining time zones.
The best practice in storing, serializing, and exchanging date-time values is generally to adjust into UTC. Assuming a date-time library’s tzdata is up-to-date, adjusting into UTC provides a reliable value that is always correct and unambiguous.
In Java, for example, that means using or extracting an Instant
object. The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now();
…or…
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
Instant instant = zdt.toInstant();
The standard ISO 8601 formatted string representing such a value uses a Z
as short for Zulu
and meaning UTC.
2007-12-03T09:15:30Z
OffsetDateTime
If you are given a string representing a date-time with only an offset, parse it as a OffsetDateTime
object.
OffsetDateTime odt = OffsetDateTime.parse( "2007-12-03T10:15:30+01:00" );
odt.toString(): 2007-12-03T10:15:30+01:00
From there you can extract a value in UTC, an Instant
.
Instant instant = odt.toInstant();
instant.toString(): 2007-12-03T09:15:30Z
Or you can adjust into a desired time zone to get the same moment as a ZonedDateTime
object.
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
zdt.toString(): 2007-12-03T14:45:30+05:30[Asia/Kolkata]
I suggest you avoid the term “local” when referring to a date-time adjusted into a region’s particular wall-clock time. The word “local” in the java.time classes and in other contexts means any locality, rather than a particular locality. A local date-time is not a specific moment on the timeline, only a rough idea about a range of possible moments.
For example the local date-time of the beginning of Christmas this year is 2017-12-25T00:00:00
, but that moment of midnight is much earlier in Auckland than in Kolkata, and still hours later in Paris, while even more hours later in Montréal.
I suggest instead you use the terms zoned
or wall-clock time
when you mean a specific moment seen through the lens of a particular time zone.
The Question happened to use the letters -7
when referring to an offset. I suggest always:
So use -07:00
rather than -7
.
Upvotes: 1