iPhone Calendar Bugs

I’ve finished my Maya Date iPhone application and it’s now available on the iTunes store! Hooray!

A couple of people have asked me about my earlier post regarding the bug in Apple’s date software, which causes dates chosen with the date picker before the year 1582 to come out wrong.

Before I discuss it, you can see the bug for yourself (I’ve only tested this on versions 3.0 and 3.1 of the iPhone OS). Go to Contacts and pick anyone in your list. Choose Edit, scroll down and select add field, then scroll down again and choose Birthday. You’ll see a date picker, and your chosen date in a little box above it. Give your fingertip a workout and scroll the years back, back, back, to 1583. You can see in the screenshot below that I took these pictures on September 22 (that’s why September 22 is in blue). I left the month and day alone and scrolled back to the year 1583. The window above the picker reads “September 22, 1583″. All seems well.

22Sept1583

Almost. Look at the year wheel. Uh… where did 1582 go?

And now starts the fun.

Go back one step on the year wheel. We’re now lost in time. The screenshot below tells the story:

22Sept1581

I’ve dialed September 22, 1581. The window reads September 12, 1582. Wrong day, wrong year! We’re one year and 10 days off. Is this just a one-time error? Let’s try another year:

22Sept1333

Now September 22, 1333 has become September 14, 1334. Now we’re one year and 8 days off! Just for fun, here are two other random days I dialed up, both near the start of a month. Each one turns into a day near the end of the previous month, but a year later. There’s also the Ides of March in what looks like the year 300.

Three Calendar Dates

Note that these dates aren’t just a year off, and they’re not just a year and a fixed number of days off. The number of days between the date you dial and the date that gets reported changes as you go farther back in time. In 800 we’re a year and 4 days off, and in 1300 we’re a year and 8 days off. In the year 300 we’re only one day and a year off, but … hey, wait a second. The year 300 is listed twice! What the heck?

There are three pieces interacting here. The first piece is the interface gadget with the wheels. This is a UIDatePicker, which is a standard device in the Interface Builder. To find out what date the user has selected, you read an NSDate back from the picker. This is our second piece. Finally, you typically want to convert the NSDate into a Gregorian calendar date, and for that you use the calendar associated with the picker, which is of type NSCalendar. That’s our third piece. So the user dials the UIDatePicker, we get back an NSDate, and convert it to Gregorian with NSCalendar. And it’s wrong: the result does not match what the user dialed.

These three objects, which should be the closest of friends, obviously do not play together nicely for dates prior to 1582.

I tried a few experiments to figure out where the problem is coming from (I wrote about them briefly in my previous post on this subject), but it’s not hard to guess why 1582 is where things start to go wrong. The calendar we use today is called the Gregorian calendar, named for Pope Gregory XIII who introduced it in 1582 (a good summary can be found on Wikipedia). So any dates prior to 1584 are in some sense pretend dates - nobody alive at that time was using this calendar. But it’s straightforward to run the calendar backwards, inserting leap years where they would have gone, had the calendar been in use. Dates before 1582 are referred to as dates from the proleptic Gregorian calendar. You can create a proleptic version of any calendar by running it backwards prior to its first use.

The calendar in use prior to 1582 was the Julian calendar, and it was this close to the Gregorian calendar. The difference between the two was a tiny tweak to the leap-year rule. When the Gregorian calendar was introduced, they wanted to get the new calendar to synchronize with where the older, Julian calendar would have been if it had been using the same leap-year rule. The difference was 10 days. So they just dropped 10 days out of the middle of October, and Thursday, October 4 1582 (the last day the Julian calendar was in power) was followed by Friday, October 15 1582 (the first day the Gregorian calendar was in power). Of course, not everyone was using the Julian calendar at the time, and not everyone switched to the Gregorian calendar on that date, but that’s when the changeover officially took place.

So 1582 was a weird year for calendars.

And 1582 is the year that’s missing. And dates prior to that are broken.

What to do? I tried a few other calendar algorithms that I found on the web, including several for the Julian Date Calendar, or JDC (not the same as the Julian calendar, unfortunately, but an unlucky or just poor choice of names many centuries ago). But many of the algorithms on the web are buggy. When I implemented them and ran an exhaustive day-by-day round-trip check (taking a Gregorian date, turning it into JDC, then back to Gregorian - and not by using Apple’s software, of course!) I found that each of the code fragments I found on the web had occasional errors, often around the time of February 29 on leap years.

Since I didn’t want to trust a random algorithm on the web, and I knew Apple’s calendar system was broken, I wrote my own. I replaced the UIDatePicker with my own custom picker object, and I wrote an algorithm to convert to and from a format I called Andrew’s Date Calendar, or ADC. Modeled after the Julian Date Calendar, this is simply an integer that tells how many days have gone by since Jan 1, 4000 BC. I ran this through my round-trip checker and confirmed it’s rock-solid from 4000 BC to at least AD 3000. The code can quickly convert an ADC to Gregorian, or vice-versa. And of course it can also quickly convert ADC into Mayan Long Count for my application, and vice-versa.

When I finished my application I went to the iTunes store and bought a few of the other Mayan calendar applications. To my surprise, every one I tried clearly uses Apple’s calendar, because they all work fine after 1584, but are wrong before then. It’s just crazy - either those developers didn’t test their programs, or they tested but didn’t care to fix the problem, but people are selling historical calendars that give wrong answers for historical dates! I’m sure most people use these programs for contemporary events, but still, I think a historical calendar should be accurate and reliable when used for historical dates. I’m glad to say that Maya Date is both accurate and reliable.

Leave a comment

You must be logged in to post a comment.