Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write an ISO 8601 date with a timezone but no time component

An ISO 8601 datetime with a timezone is formatted like this:

2018-09-07T05:28:42Z

However, I need to represent some dates in my system where the precision is days, not seconds, which means that it would be an ISO 8601 calendar date. Calendar dates are formatted like this:

2018-09-07

In the Wikipedia article about the standard (I don't have access to the standard itself, as you have to pay for that privilege), there is no mention of timezone when discussing dates. It does talk about omitting parts of the time:

Either the seconds, or the minutes and seconds, may be omitted from the basic or extended time formats for greater brevity but decreased accuracy: [hh]:[mm], [hh][mm] and [hh] are the resulting reduced accuracy time formats.

From this, it seems that you cannot omit hours, so I could not write a calendar date like this:

2018-09-07TZ

It appears that the best I can do is truncating down to the hour:

2018-09-07T00Z

I don't want to do this if I can avoid it, however, as I am adding more precision to a date than is really there. The date means "sometime during the day of 07 September, 2018 in the UTC timezone", not "sometime during the midnight hour of 07 September, 2018 in the UTC timezone".

Any suggestions?

like image 771
Josh Glover Avatar asked Sep 07 '18 05:09

Josh Glover


People also ask

Does ISO 8601 include timezone?

Time zone designators. Time zones in ISO 8601 are represented as local time (with the location unspecified), as UTC, or as an offset from UTC.

Is ISO 8601 always UTC?

Date.prototype.toISOString() The toISOString() method returns a string in simplified extended ISO format (ISO 8601), which is always 24 or 27 characters long ( YYYY-MM-DDTHH:mm:ss.sssZ or ±YYYYYY-MM-DDTHH:mm:ss.sssZ , respectively). The timezone is always zero UTC offset, as denoted by the suffix Z .

How do I find the timezone in an ISO date?

Converts a date to extended ISO format (ISO 8601), including timezone offset. Use Date. prototype. getTimezoneOffset() to get the timezone offset and reverse it.

How do I convert a date to ISO 8601?

The date. toISOString() method is used to convert the given date object's contents into a string in ISO format (ISO 8601) i.e, in the form of (YYYY-MM-DDTHH:mm:ss. sssZ or ±YYYYYY-MM-DDTHH:mm:ss.


1 Answers

Officially, the ISO 8601 spec does not allow for a date with a time zone unless a time is provided. Thus, if you wish to remain ISO 8601 compliant, you cannot provide additional information for date-only values than year, month, and day (without resorting to time intervals - mentioned further below).

One format that does allow for this is XML Schema (aka "XSD"), in the xs:date type. There, it is optional, and would immediately follow the day, such as 2018-09-07Z. The XSD spec calls out in Section D.3 Deviations from ISO 8601 Formats:

D.3.4 Time zone permitted
The lexical representations for the datatypes date, gYearMonth, gMonthDay, gDay, gMonth and gYear permit an optional trailing time zone specificiation.

I realize you weren't asking about XSD, but this the only normative reference I'm aware of that's freely available online that calls out the time zone on a date is a deviation from ISO 8601.

As others have pointed out - thinking about a date with a time zone is a tricky thing. In many aspects, a date-only value is ambiguous. Consider if I presented you a calendar such as this one:

calendar image

Pointing at any given date on this calendar doesn't tell me anything about time zones. I can give the calendar to someone in a different time zone and they will still be able to talk about dates. It's simply that if we both point at "today" simultaneously, we might not be pointing at the same date. Thus, time zones only apply when we apply a time context, whether "now" or a specific one.

However, we do tend to rationalize about all points in time on a given day in terms of a time zone. In your example, the "UTC Day". We mean that it runs from T00:00Z of one day, to just before T00:00Z of the next. This is generally the reasoning behind things like xs:date allowing a time zone offset.

If we wanted to be strictly ISO 8601 compliant and represent the same meaning, we'd have to provide a range of date+time values, which are called "time intervals" in section 4.4 of the ISO 8601 spec, and are separated with a forward slash (/) character. An example of such a value would be 2018-09-07T00:00Z/2018-09-08T00:00Z. However, be careful because ISO 8601 says nothing about whether the end date should be interpreted inclusively or exclusively. More on that here.

Another ISO 8601 representation of an interval allows for a start time and a duration component, such as 2018-09-07T00:00Z/P1D. This feels to me like the closest fully ISO 8601 compliant way to represent a whole date interpreted in UTC.

Still, personally, if I needed to convey time zone with a date, I would use 2018-09-07Z even if it wasn't strictly compliant. Just make sure all consumers of your data agree on this format. If you can't do that, just pass 2018-09-07 and name your field something like utcDate.

like image 75
Matt Johnson-Pint Avatar answered Oct 13 '22 03:10

Matt Johnson-Pint