When sharing code between iOS and Android, it can be important to understand the differences in the way the platforms handle dates and times.
Here’s some key points to note when using Xamarin to handle dates and times.
Xamarin .NET Time Zone IDs are not the same as Windows.
You must use the Olson IDs when defining a timezone.
A conversion table is available here. http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html (scroll down for the windows table).
NSDate uses a different reference date
NSDate internally stores dates as the number of milliseconds since 01/01/2001. .NET DateTime uses ticks (100 nanoseconds) since 01/01/0001. I used to manage a native iOS app which used a Sqlite database. The database was generated from an iOS app, where NSDate was used for dates. It stored the dates as the number of milliseconds since 2001, as expected. So, when I needed to use this database in a Xamarin app, the date fields needed some small amount of consideration. You would think that the code below would be correct.
If you run the above code, the
validDate variable may actually contain the wrong date, depending on your computer’s timezone. The number of milliseconds was generated by iOS before it was saved to our database, and the date used was 1st April 2013 00:00, however, the DateTime generated contains 31st March 2013 23:00. This is because…
NSDate defaults to GMT, DateTime doesn’t.
If you create an NSDate object in iOS, and don’t specify a timezone, it will assume your date is GMT. In this context, GMT refers to the timezone which applies to London and Dublin, and it supports daylight saving. This means that if you create a date which is within the daylight saving time period (i.e. in UK, after the clocks have gone forward by an hour), NSDate will assume that your date has a timezone offset applied to it, and therefore will unapply the offset when storing the date internally. This behaviour is correct. The date has been converted to Coordinated Universal Time (which is abbreviated to UTC, for some reason).
When displaying this value in iOS, a standard NSDateFormatter object will assume GMT again, and add an hour, giving a value equivalent to the original. In .NET however we must convert the value to GMT in order to get the correct date.
TimeZoneInfo is broken on Android v4.3 up until Xamarin.Android v4.8.2.
The above code will fail on Android 4.3 unless you are using Xamarin.Android v4.8.2 or greater. Firstly, the
FindSystemTimeZoneById() call will throw a
TimeZoneNotFoundException. Then the call to the
TimeZoneInfo.Local property will return
null. Upgrade to 4.8.2 to fix this.