12 ms·
Start sending dates the right way (aka The ISO8601 101)
- cirwin 14y agoVery good advice! ISO8601 is a perfect tradeoff between the machine readable Unix timestamp, and the human readable mess used in http. The only thing libraries often get wrong is that the timestamp should always be present and default to 'Z'. It's pretty rare to want timestamps in local time except during debugging, but that's often the default. It catches a lot of people out.
- Keithamus 14y agoYes, this is one thing that I've had a lot of difficulty with when trying to implement a reliable ISO parser. I've found that Python is one of the worst offenders with this, as by default the datetime classes have no concept of tz, and it is significantly more difficult to attach tz info to a Python date. (Loosely mentioned in the article).
- d0mine 14y agoTake a look at pytz and python-dateutil
- lifthrasiir 14y agoISO 8601 defines a number of lesser known features. For example, it allows for not only fractional seconds (12:34:56.78) but also fractional hours (12.3) and minutes (12:34.93). There is a special notation for the midnight of certain day (24:00:00 or 24:00), and obviously another for a positive leap second (08:59:60 etc.). There are three ways to write a date: 2012-05-21, 2012-W21-1 and 2012-142. Intervals can be specified in terms of start and end, start and duration, duration and end, just a duration (i.e. no context). There are also recurring intervals which can be bounded in the number of recurrences or not. And so on and on and on. That said, ISO 8601 tries to cover most cases for date/time representation. Implementing every bit of ISO 8601 is not desirable of course, but it is certainly worth looking at.
- geon 14y ago> 2012-142 Does that represent the 142:nd day of the year? Isn't that ambiguous when you can specify a year and month in the same format?
- estel 14y agoThe format is YYYY-DDD with leading zeroes.
- geon 14y agoSo 2012-142 is not a valid date? Should it be 2012-0142?
- evilduck 14y agoI don't see the need for a placeholder for the n-thousandth day of the year. Unless we want to accomodate something like 2011-0367 also equating to 2012-0002?
- sanxiyn 14y ago2012-142 is valid. 2012-012 is valid. 2012-12 is not. For nth day specify exactly three digits. No confusion with months.
- djpowell 14y agoRFC3339 is a pretty reasonable profile of ISO8601 http://www.ietf.org/rfc/rfc3339.txt http://www.ietf.org/rfc/rfc3339.txt I'm always a bit nervous when people talk about ISO8601, given that very few people have probably read the spec, and are likely guessing as to its content.
- Keithamus 14y agoI agree. The main barrier to actually reading the ISO8601 spec is that it costs money, and is not cheap (if memory services its ~$150), leaving people to read the draft specs (which are harder to get a hold of in their full form) or the Wikipedia entry.
- d0mine 14y agoFull ISO 8601 is complicated. Try to restrict yourself to RFC 3339 http://tools.ietf.org/html/rfc3339 http://tools.ietf.org/html/rfc3339 a profile of ISO8601 if possible.
- Keithamus 14y agoThis is a great recommendation but if you're trying to be interoperable with other languages it's just not possible. If you're in control of the output format though, I would fully agree.
- obtu 14y agoThe original article is about generating date strings, and I would give it more credence if it mentioned the RFC 3339 profile. (edit: I just noticed you're probably the author; please excuse my abrupt tone)
- Keithamus 14y agoIt's true, I should have mentioned RFC3339 in the article. I will make some amendments to it later today.
- suprememoocow 14y agoBeware that older browsers, including IE8, won't automatically parse ISO8601 dates, so Date.parse('2012-05-04T12:20:34.000343+01:00') or new Date('2012-05-04T12:20:34.000343+01:00') return the date representation of 'invalid date'. ISO8601 parsing was only introduced with JavaScript 1.8.5. This means that if you're supporting older browsers, you'll need to write your own parser on the client side or use a third-party library (I generally use my own regexp based parser)
- hesselink 14y agoSafari still does not parse partial dates, i.e. new Date("2012-05-04") gives 'Invalid Date'. Very annoying.
- Keithamus 14y agoIf you look at the website this article is on (http://tempus-js.com/ http://tempus-js.com/) it is a JavaScript library for replacing the Date object with something that offers more functionality and is browser compatible down to IE6 & co.
- metabrew 14y agoYou can pry my "<milli|micro>seconds since the epoch" timestamps from my cold dead hands.
- roel_v 14y agoSo you software doesn't support timezones? Good luck with that.
- TazeTSchnitzel 14y agoYes it does. Store UTC times, display in local timezone.
- mitchty 14y agoI suppose the only drawback to using epoch alone would be if you need to remember the timezone the date was stored from. But thats easy enough to fix.
- ZenPsycho 14y agowhich, if you think the problem through enough you'll have to conclude that you do need to store the time zone, unless you just don't really care about having accurate times. Read through some of the other comments and you'll realize that there's certain kinds of calculations and comparisons you just can't do without the time zone, and a historical time zone database, and a leap seconds database. Do not make the mistake of assuming that dealing with times and dates can be easy.
- mitchty 14y agoMad late reply but i use epoch when my time needs don't matter. Aka: I can get by without worrying about epoch not being second precise and I don't need to worry about dates except to display them in non UTC. For my needs 90% of the time iso8601 is overkill and unnecessary. But dates in what I do don't need to be complicated. Which is rare. Also I never said working with times and dates is easy, evaluate your needs for the situation. Going full tilt with timezones and full date parsing for some general server logs for example doesn't always make sense is all I'm saying. Tschuss!
- ams6110 14y ago... with ISO8601 intervals you can express this as a string format, rather than using something ghastly like seconds or milliseconds: 'P6Y4M4DT3H45M15S' To me, that is absolutely no less "ghastly" as just saying the period is 3600 seconds (or whatever...)
- Keithamus 14y agoWell, 3600 seconds can be expressed much more simply than that: 'PT1H'. Which is more human readable than '3600'. The point in intervals is a compromise between human and machine readability - the point being that we can more easily determine long periods of time expressed in unit values rather than milli/microseconds.
- lloeki 14y ago> 'PT1H'. Which is more human readable than '3600' Not to mention six years, four months, four days, three hours, forty five minutes and fifteen seconds, which is nothing short of 200072715 seconds (which my brain definitely wants to parse as two billions and something).
- swombat 14y agoYeah, I was going to say that too... > The nice thing about ISO intervals is that they are human readable That P6 monstrosity is not human-readable. Not by 99.999% of humans, anyway.
- rmc 14y agoNonsense, it's very readible. You could tell someone who can't code to say "period" for "P", "hour" for "H", "time" for "T" etc. and they'd be able to read out the period exactly, accurately all the time. They would also know how write their own forms of this. Humans can also look at it and know, intuitavely, without a calculator how long it is. Trying to get them to multiple seconds (incl all the fun with leap seconds!) would be hard.
- tomelders 14y agoWhat is all this "Human Readable" nonsense. Who the hell is reading all these date times? If two pieces of software are passing dates around, use a UNIX, UTC timestamp. If a human wants to read it they're probably a programmer and know how to parse a timestamp. If they're not a programmer, then you shouldn't be showing them unformatted date times anyway.
- tow21 14y agoFor 99% of use cases on the web, you'll probably manage to get away with the W3 subset: http://www.w3.org/TR/NOTE-datetime http://www.w3.org/TR/NOTE-datetime which avoids most of the awkward corners, and for which a parser is a bit easier to write.
- jlarocco 14y agoPossibly true, except that parsing dates and times should almost always be done with strptime() or a similar library function.
- mbq 14y agoI don't get the argument that timestaps are not human readable -- they are, the only thing you need is a good viewing software. And yes, it is worth it since at least 99.999999% of accesses to this data come from machines.
- Keithamus 14y agoTo paraphrase your own comment: Timestamps are human readable. You just need a machine to change them into a human readable format
- mbq 14y agoI was trying to say that it is better to invest a bit of time in improving data viewers/editors to present timestamps in a nice form than to waste huge amount of effort on parsing and serializing stuff no human will ever see. Besides, human readable is a relative term -- even ASCII text requires serious machine processing to become human readable pixel pattern.
- tomelders 14y agoThey're certainly not human readable, but I want to know who these people are that are reading the date times being passed around by two pieces of software. Also, why are people passing around date times for specific timezones? Converting a UTC timestamp to local time is trivial in every language I've used. Converting a local time to another local time isn't. It sounds to me like a problem that doesn't exist, and a solution that causes more problems. I'll be sticking with unix timestamps thank you very much.
- lmm 14y ago+01:00 is not a useful timezone. If you want human-friendly semantics for things like "+1 day", you need to use the symbolic name for the timezone (Europe/Lisbon or whatever). If you just want an absolute time, you're better off expressing it in UTC, possibly even as seconds since epoch.
- apaprocki 14y agoCorrect, these are time offsets, not time zones. Although, absolute times are exactly what they are for and the reason why e-mail headers use this format. Whenever referring to offsets ("+1 day") or reoccurring events such as in a calendar app ("every 4/1 at midnight"), a real timezone is needed. I've seen plenty of code introduce DST related bugs by taking the current timezone offset and using it to do date/time calculation throughout the life of the application.
- rmc 14y agoThere is a difference between "+01:00" and "Europe/Lisbon". One is always 1 hour away from UTC, the other isn't and includes summer time.
- lmm 14y agoYes, exactly. My point is: what is the use case where you would ever want "+01:00"? If you want to express an absolute[1] time, you use UTC or seconds since epoch. If you want to express a time that's meaningful to humans, you need a symbolic timezone (otherwise the answers to questions like "what is the time 1 day after this" will be surprising). [1] Yes, I know there's no such thing as absolute time; perhaps "machine time" expresses what I mean.
- rmc 14y agoExactly. One should just about always store UTC time.
- Corun 14y agoI don't understand why you would ever use anything other than seconds/micros/millis since epoch. Basically no parsing; Efficiently storable; Simpler; Easier; Better. Only argument I've ever heard is human readability... If you're reading these by hand so often then just write a script/tool/whatever to convert them to human readable. This is still easier since you don't have to find an acceptable ISO8601 implementation. And frankly, how often are you reading the dates manually but not as part of some log output of your program where it could convert it to human readable before logging? This is sending dates the wrong way.
- apaprocki 14y agoSo every mail header in the world should represent: Date: Thu, 17 May 2012 08:36:04 -0700 (PDT) as Date: 1337268964 because no one needs to look at mail headers and it should be the job of the user's mail reader to display it in a human readable form? I do not think it is so black and white. In the case of mail headers, the benefit of keeping the timestamps human readable outweighs the programmer cost for parsing them correctly.
- Corun 14y ago"no one needs to look at mail headers and it should be the job of the user's mail reader to display it in a human readable form". Exactly... Who reads email headers? Maybe some server admin who's going through some backups of emails looking for something. He might even appreciate having a date format that's lexicographically ordered for his searching purposes. Having a human readable date is like changing HTTP Content-Length to say "one million four hundred and fifty thousand and sixty four" so that when I'm reading through my raw server logs I can easily see the magnitude of the length of the responses.
- joezydeco 14y agoWhat do we do about date calculations that cross an epoch wrap?
- Corun 14y ago
- joezydeco 14y agoThe article doesn't mention the fact that ISO8601 strings will also sort correctly in chronological order, or does this not matter since epoch-seconds do as well (as long as there are enough leading zeroes)?
- gpvos 14y agoIf you're sending or storing local dates and times, it may actually be better to use the local time (as ISO 8601 does) with the (Olson tz) name of the time zone it's in, instead of the time zone offset as in ISO 8601. This is more resilient against future time zone rule changes, at least that's what this article argues: http://fanf.livejournal.com/104586.html http://fanf.livejournal.com/104586.html .
- Kilimanjaro 14y agoI never understood what the T was for, besides being visual noise. why not just use spaces? 2012-05-04 12:20:34.000343 +01:00 Or, if spaces are not allowed for an unknown reason then: 2012.05.04-12:20:34.000343+01:00 Much better, still I prefer the simplicity of this: 20120504.122034 In UTC, almost as compact as an epoch, but human readable. Add as many digits as nano precision is needed.
- rmc 14y agoYou say "visual noise", I say "readability".
- tantalor 14y agoPostgres's timestamp type uses a space instead of a "T", e.g., "1999-01-08 04:05:06" http://www.postgresql.org/docs/8.0/static/datatype-datetime.html#AEN4516 http://www.postgresql.org/docs/8.0/static/datatype-datetime....
- Tobu 14y agoThe first option is generally allowed by protocols where spaces are appropriate. Using the other alternatives would get one into the business of defining standards, which no sane person with an appreciation for the subtlety of that task would do unless they had no choice. Having multiple separators or mashing the numbers together would undermine the distinctiveness of ISO8601, and the distinctiveness allows someone to know the precise semantics of a date even when it is taken out of context.
- aidenn0 14y agoSince nobody else has mentioned this, an interesting essay on time by Erik Naggum; it was done with thought to implementing a time library for common-lisp, but should be readable for non-lisp users: http://naggum.no/lugm-time.html http://naggum.no/lugm-time.html