7vikram7
7vikram7

Reputation: 2824

Xamarin 'iOS Foundation NSDate to C# DateTime conversion' and vice versa not accounting for DayLight saving

I need to convert Cocoa NSDate to C# DateTime and vice versa.

I am using the following method to achieve this:

 public static DateTime NSDateToDateTime (Foundation.NSDate date)
 {
    DateTime reference = TimeZone.CurrentTimeZone.ToLocalTime (
        new DateTime (2001, 1, 1, 0, 0, 0));
   return reference.AddSeconds (date.SecondsSinceReferenceDate);
 }

 public static Foundation.NSDate DateTimeToNSDate (DateTime date)
 {
    DateTime reference = TimeZone.CurrentTimeZone.ToLocalTime (
        new DateTime (2001, 1, 1, 0, 0, 0));
    return Foundation.NSDate.FromTimeIntervalSinceReferenceDate (
        (date - reference).TotalSeconds);
 }

But it turns out, this way it is not accounting for Daylight Saving.

Eg. DateTime object in which the time was 5AM in DST returns NSDate with time 6AM.

Upvotes: 10

Views: 4996

Answers (3)

Lug
Lug

Reputation: 430

There is a creepy bug on direct casting to NSDate

My solution was:

    public static NSDate DateTimeToNSDate(this DateTime date)
    {
        var calendar = new NSCalendar(NSCalendarType.Gregorian);
        calendar.TimeZone = NSTimeZone.FromName("UTC");
        var components = new NSDateComponents { Day = date.Day, Month = date.Month, Year = date.Year, Hour = date.Hour,
            Minute = date.Minute, Second = date.Second, Nanosecond = date.Millisecond * 1000000 };
        var result = calendar.DateFromComponents(components);

        return result;
    }

I hope this helps

Upvotes: 0

Chris Koiak
Chris Koiak

Reputation: 1059

I'm pretty sure this is an outdated approach. You can cast a NSDate directly to a DateTime now.

 Foundation.NSDate nsDate = // someValue
 DateTime dateTime = (DateTime)nsDate;

Upvotes: 12

7vikram7
7vikram7

Reputation: 2824

Based on inputs from: https://forums.xamarin.com/discussion/27184/convert-nsdate-to-datetime

Local Time changes during Daylight Saving. Hence, always convert to UTC to do the calculations, then convert to Local time if needed.

     public static DateTime NSDateToDateTime (Foundation.NSDate date)
     {
        DateTime reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        var utcDateTime = reference.AddSeconds(date.SecondsSinceReferenceDate);
        return utcDateTime.ToLocalTime();
     }

     public static Foundation.NSDate DateTimeToNSDate (DateTime date)
     {
        DateTime reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        var utcDateTime = date.ToUniversalTime();
        return Foundation.NSDate.FromTimeIntervalSinceReferenceDate((utcDateTime - reference).TotalSeconds);
     }

Upvotes: 6

Related Questions