Intended audience: users, HTML coders, script developers (PHP, JSP, etc.), CSS coders, schema developers (DTDs, XML Schema, RelaxNG, etc.), XSLT developers, Web project managers, and anyone who is new to internationalization and needs guidance on topics to consider and ways to get into the material on the site. yyy adapt this to describe the intended reader of the article.
What is a floating time and how do I handle floating times in my Web application?
A floating time or a floating date is a date/time value that isn't tied to a specific time zone. Applications that work with floating times need to avoid pitfalls that can arise from implicit conversion to incremental time values or the improper use of time zones when displaying or processing a floating time value.
The Working with Timezones WG Note says:
Some observed time values are not related to a specific moment in incremental time. Instead, they need to be combined with local information to determine a range of acceptable incremental time values. We refer to these sorts of time values as "floating times" because they are not fixed to a specific incremental time value. Floating times are not attached and should never be attached to a particular time zone.
That is, a floating time value is a time value that is associated with many different discrete instants in time which share some specific relationship. Common examples of floating times include concepts such as birth date, starting or ending dates for a worldwide event, holidays, or publication dates.
As an example, let's consider the publication date of an online newspaper. On 30 April 2017 this newspaper published an online Sunday edition.
Martina is a subscriber who lives in Buenos Aires, Argentina. When she visits the newspaper's web site, she is given the option of selecting which edition she wants to view. The HTML for the form control might look like this:
When Martina fills in the form and submits it, though, she is surprised to see that the edition she receives is dated Saturday, 29 April 2017 instead. The actual newspaper is the correct Sunday edition. But the screen says the wrong date. What's going on?
Date object with the value: 1493510400000 (in milliseconds since the epoch). That long integer value corresponds to the instant of midnight, 30 April, 2017 in Coordinated Universal Time (UTC). At that moment in Buenos Aires, Argentina, it was still only 9:00 PM (21:00) on the previous day, Saturday, 29 April, 2017. When the
Date with value 1493510400000 is displayed in the local time zone, it's interpreted as the preceding Saturday.
Here's an example. Suppose the
publicationDateInput above contained the value used in the example ("2017-04-30"). The code might look like this:
You'd expect the element whose ID is
date-target to contain a string representing Sunday, April 30th. However, if you live in a time zone west of UTC (such as Martina does, in the
America/Buenos_Aires time zone) you would see something like this instead:
Many of the
midnight, so anyone displaying the underlying value in a time zone following UTC will naturally see the previous day. In the case of a system running in the
time portion of the publication date is zeroed out. Subtracting two or three hours from the
Date object results in a presentation string that is on the previous day. That day might be in the wrong month or even the wrong year.
Intl extension interacts with date values:
Because the local interpretation of a given date depends on the local time—that is, it depends on the local calendar, clock, and time zone rules—the range of incremental times that might be described as 2017-04-30 turns out to span as many as fifty hours. The earliest time that can be called "30 April 2017" starts in Kiribati in the South Pacific, some 14 hours before midnight on 30 April 2017 occurs in UTC. The last moment that can be called part of "30 April 2017" occurs just before midnight of "1 May 2017" on the island of Midway's time zone, some 11 hours after "30 April 2017" has ended in UTC (there is an even later zone, but it is uninhabited). Depending on the time zone used to create and then later to display an incremental time value, the same floating date value could appear to be as much as two days off.
There are several ways to work around this. One method is to always use the UTC time zone for processing floating time values. Developers have to be careful to convert time values into incremental time objects using an offset of zero and segregate code that deals with floating times (especially formatting these time values for display) from code dealing with actual incremental time values such as time stamps.
In some programming languages and environments there are data types or APIs that can help by keeping floating times "floating". For example, if you're a Java developer writing server code, you can (carefully) use data types from Joda time (part of the JDK since 1.8), such as
LocalDate to create and process time values without imposing a specific time zone. A Java
LocalDate is an example of a floating time value. The care that must be excercised is that implicit or explict conversion to incremental time values such as
Date often takes place in formatting code or when applying certain date processes, such as comparison.
Date single argument string constructor uses UTC, with a local time offset of 0, to compute the underlying incremental time value. Methods that use the local time zone of the browser, such as
toString will cause the problems such as Martina experienced above.
If instead the developer uses the field-based time constructor
new Date(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]]);, then the browser's local time offset is used to compute the underlying incremental time. In the Martina example,
var Date = new Date(2017,04,30); creates a time value
1493521200000, which seems to work if only the date is shown. But when Martina visits her friend Noboyuki in Japan, the problem appears in the opposite direction:
This is even visible in the MDN article on Intl.DateTimeFormat:
If this code is executed on a browser in a time zone west of UTC, the "expected output" won't be shown: instead one sees values such as
Ultimately, Web developers need to remain aware of the use of incremental times in the underlying APIs. Using floating or "local" time formats is one way to accmoplish this. Or developers can use UTC or a consistent local time offset for floating time values to allow these values to be processed and displayed consistently.