DateFormatter and the year 12100

Why does the date formatter yield the year 12,100 for time zones that are GMT + hh:mm for dates between 2000/01/01 00:00:00 UTC and 2000/01/01 at the time offset at that time zone?

It has been mentioned here.

let str = "00/01/01"

let inputFormatter = DateFormatter()
inputFormatter.dateFormat = "yy/MM/dd"

inputFormatter.timeZone = TimeZone(identifier: "Asia/Calcutta")
//inputFormatter.timeZone = TimeZone(identifier: "Africa/Addis_Ababa")
//inputFormatter.timeZone = TimeZone(identifier: "Europe/Moscow")
//inputFormatter.timeZone = TimeZone(identifier: "Asia/Hong_Kong")

if let showDate = inputFormatter.date(from: str) {
   inputFormatter.dateFormat = "dd/MM/yyyy"
   let resultString = inputFormatter.string(from: showDate)
   print(resultString)
 }

Where does 12,100 come from?

The year 1 BC was followed by the year 1 AD; there is no "year 0" in the Gregorian calendar. So the calendaring API is trying to parse something nonsensical, and is giving you a nonsensical answer.

1 Like

But two-digit years yy should be interpreted as 19yy or 20yy (depending on the value of twoDigitStartDate). A two-digit 00 should be interpreted as 2000, not as "year 0".

Hm yeah, that's a good point.

@Clicket I'd recommend filing a bug over at bugreport.apple.com, because this is all powered by Foundation.framework

I'm not sure this is accurate, The DateFormatter is based on the Unicode Standard: https://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Field_Symbol_Table

And there is no mention of special interpretation of 2 digit years here. For instance, 01 is year AD 1.

That behavior is controlled by the twoDigitStartDate property of DateFormatter:

If the two-digit start date is set to January 6, 1976, then “January 1, 76” is interpreted as New Year's Day in 2076, whereas “February 14, 76” is interpreted as Valentine's Day in 1976.

Examples:

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yy/MM/dd"
formatter.timeZone = TimeZone(secondsFromGMT: 0)

print(formatter.date(from: "00/01/01")!) // 2000-01-01 00:00:00 +0000
print(formatter.date(from: "49/12/31")!) // 2049-12-31 00:00:00 +0000
print(formatter.date(from: "50/01/01")!) // 1950-01-01 00:00:00 +0000

It fails only for certain dates, and (apparently) only for time zones with a positive GMT offset.
Here the first result is correct, the second one obviously not:

formatter.timeZone = TimeZone(secondsFromGMT: 3600)
print(formatter.date(from: "00/01/02")!) // 2000-01-01 23:00:00 +0000
print(formatter.date(from: "00/01/01")!) // 12099-12-31 23:00:00 +0000
2 Likes

By the way, and perhaps a bit OT, where has the list of conversion specifiers (like "yyyy", "MM", "dd", "ccccc" etc) in .dateFormat gone?

The documentation for .dateFormat says:

See Data Formatting Guide for a list of the conversion specifiers permitted in date format strings.

But I can't find any list of conversion specifiers in the Data Formatting Guide. And it has this warning:

Important: This document is no longer being updated. For the latest information about Apple SDKs, visit the documentation website.


Has the list of conversion specifiers been removed, and if so why?

The Date Formatters chapter in the Data Formatting Guide (still) has a section “ Fixed Formats” with links to the Unicode Technical Standard #35 where the date format patterns are documented.

However, the latest OS versions in that list are OS X v10.9 and iOS 7. I do not know if newer OS versions use newer revisions of that standard.

2 Likes
Terms of Service

Privacy Policy

Cookie Policy