The end of the year is rolling around and it’s time to remind everyone about that yyyy
works the way you think it does and YYYY
does not. Here’s a quick example to start:
Just because you test a format quickly with the current date and get back the result you expect, does not mean you’ve constructed your date format correctly.
Speaking of which, BJ Homer points out that you can just use “y”, as “yyyy” pads to 4 digits which doesn’t usually matter but isn’t always needed. Olivier Halligon adds, further, that not all calendars use 4 digit years. “For example the Japanese start a new era every time the emperor changes, resetting to year 1 in that era; we’re currently in year Heisei 30.”
To quote The Dave™: “Nooooooo…. Please use “y”, not “yyyy”. “yyyy” zero-pads years that aren’t four digits, and there are multiple calendars w/ 2 or 3-digits years (Japanese, Chinese, Republic of China). “y” is the natural length of the year: “30” for Japanese cal, “2018” for Gregorian, etc”
What you’re actually seeing with “Dec 24, 2017” is the first day of the last full week of the preceding year. It doesn’t matter what numbers you plug into the month (“MM”) or day (“dd”). The presence of YYYY
in the date format without its expected supporting information reduces to “start of year, go back one week, report the first day”. (I’ll explain this more in just a little bit.)
Here are some examples, which you can check from the command line using the cal
utility:
As Apple’s 2014-era date formatting guide points out:
A common mistake is to use
YYYY
.yyyy
specifies the calendar year whereasYYYY
specifies the year (of “Week of Year”), used in the ISO year-week calendar. In most cases,yyyy
andYYYY
yield the same number, however they may be different. Typically you should use the calendar year.
Unicode.org’s Unicode Technical Standard #35, Date Format Patterns goes into a little more depth:
[“Y” is] Year (in “Week of Year” based calendars). This year designation is used in ISO year-week calendar as defined by ISO 8601, but can be used in non-Gregorian based calendar systems where week date processing is desired. May not always be the same value as calendar year.
ISO 8601 uses a 4-digit year (YYYY
) for “week of year” calendars from 0000 to 9999. If you’re into trivia, the years before 1583 are technically excluded except by special agreement between sending and receiving parties.
Anyway, if you’re going to use YYYY
formats, you’ll want to use additional format elements that support “week of year” date construction. For example, consider the calendar for this upcoming January, which starts on Tuesday the 1st:
January 2019 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
This year, January first can be considered as the first week of 2019 or the 53rd week of 2018, as the weeks overlap in the middle. Using e
(the numeric day of the week) and ww
(the ordinal week to count from), you can represent both dates correctly using the oddball YYYY
formatting token.
Here are examples that use the week-of-year approach counting from both 2018 and 2019:
As you can see from this, when you use YYYY
and do not supply an ordinal week or day, they both default to zero, which is why you get the behavior of the zeroth week (that is, the week before the first week) on the zeroth day (also, the first day of that week) for that calendar year, which is the week before the first week that overlaps the stated year. This explains the results of all those otherwise random late-December dates from earlier.
ISO 8601 should be updated in a few months, with a release somewhere around February.
- ISO/FDIS 8601-1 Preview and Store Expected publication date 2019-02
- ISO/FDIS 8601-2 Preview and Store Expected publication date 2019-02
From what I can tell, the first part revises the current standard and the second expands it. The only freely accessible human-viewable material I could find were the five-page TOC previews for 8601-1 and 8601-2.
(Hat tip: Thanks, Robin Malhotra)
15 Comments
a few “weak of year” in the article
Thanks for the catch. My bad.
Just a warning, lots of week/weak spelling errors in here! (Came here via HN.)
Thanks, fixed. A bad case of “oops”
What language is this? Swift? It was unclear to me from reading the article, but interesting nonetheless. Thanks!
Yes, this is in Swift, but the Apple-supplied Cocoa / Cocoa Touch libraries just provide API access, it’s not part of the core language
Nice writeup. One technicality that comes to mind.
Doesn’t this depend on what day-of-week the new year begins? If it starts Thursday or later (in other words, less than 4 days of that week being in the new year), then the overlap week itself is ISO week 0. (right?)
January 1993 starts on a Friday. The formatter returns “Dec 20, 1992 at 12:00 AM”, which still fits the rule. By your guess, it should have been Dec 27, which it is not in Apple’s
DateFormatter
implementation.Thanks, I should have given Swift a try first. I was going by the ISO 8601 week number, which is clearly not what the “ww” format uses.
Swift appears go by the first day of week being Sunday and minimum number of days in the year being one, so that the week of Jan 1 is always week number one. I do not see that clarified in Apple docs, perhaps it is just assumed?
I haven’t tried this out with any other calendars (I’m using autoupdating current), especially those that run on different weeks or years. All my tests agree that the week containing Jan 1 is week 1 and often week 53. Week 104 doesn’t work by the way and I suspect that if I tried week 54, it also would not.
Outside of specific documentation citations, my information is entirely empirical and, as you can tell, I’m learning more from those kind enough to leave comments or tweets.
ISO 8601 is explicitly defined to have largest parts be first from left (little endian). None of the formats in this article follow that.
Please don’t perpetuate the terrible convention of using hyphens for date when it’s not in ISO 8601. Hyphens were chosen for the standard in effort cause least confusion because it was least used in established regional formats. Make it less ambiguous, use the American slashes for American order.
Good to know! Thanks for the insight…
[…] Update (2018-12-27): See also: Dave DeLong and Erica Sadun. […]
“This year, January first can be considered as the first week of 2019 or the 53rd week of 2018”
Depending on the week number system in use it can also be considered the 0th week of 2019. When I wrote manufacturing software, clients would specify a data item as a week number and be surprised when I would ask how many weeks they expected in a year. Most would say 52 until I asked “so your year starts with week 0?” at which point they would get a little confused. Dates are far more complicated than most people realise.
For more fun with dates and times (and time zones, to boot,) see https://github.com/kdeldycke/awesome-falsehood#dates-and-time.