Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing an absolute NSDate, not relative to a timezone

I am creating an iOS app to track attendance. Each attendance entry is stored in an object which has a status attribute (e.g. present, absent) and an NSDate attribute called date which denotes the day which that attendance record was taken. When I select a particular date (using a UIDatePickerView or alike) I want all the attendance records (objects) for that date to appear in a table view.

While this sounds simple in principle, I am running into an issue relating to timezones. I am aware that NSDates are stored independent of timezones (i.e. they are stored relative to UTC/GMT +0000). This means that if I am in Sydney and take attendance on, for example, Sunday 4 November 2012 because the date is stored as timezone independent, if I take my iPhone/iPad to a different time zone (such as San Francisco) all the attendance records would shift one day back, in this case to Saturday 3 November 2012, because that was the moment in time when the attendance was taken in San Francisco local time (which was actually the next day, in Sydney local time).

I don't want this to happen - I want the date to be absolute. In other words, if the attendance is taken on Sunday 4 November 2012 then it needs to stay on that date, no matter where in the world (and whichever timezone) I may go. As you can see, this is quite in contrast to, say, a calendar application where it is desirable for the timing of appointments to change depending on the timezone.

Any suggestions on a better way to approach this problem would be appreciated. Please keep in mind that I am selecting the date to display using a UIDatePickerView which returns the current NSDate in the timezone independent format, so I also need a way to do an easy comparison (preferably in an NSPredicate since the attendance objects are stored in Core Data) to get all the attendance objects for that particular day.

like image 508
Skoota Avatar asked Nov 04 '12 03:11

Skoota


2 Answers

Have you tried converting the time to it's NSDateComponents? you can then recreate an NSDate from it regardless of the time zone.

Edited to add

// This is just so I can create a date from a string.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];


// Create a date as recorded in a timezone that isn't mine.
NSDate *localDate = [formatter dateFromString:@"2012-10-30 10:30:00 +0200"];
NSLog(@"Initial Date: %@", localDate);
// this logs 2012-10-30 08:30:00 +0000
// Which is what you would expect, as the original time was 2 hours ahead

NSDateComponents *components = [[NSDateComponents alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
components = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit fromDate:localDate];

NSLog(@"Components: %@", components);


// Create a date from these time components in some other time zone
[gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"EST"]];
NSDate *newDate = [gregorian dateFromComponents:components];

NSLog(@"New Date: %@", newDate);
// This logs 2012-10-30 12:30:00 +0000
// Which is the local EST of 8:30 am expressed in UTC

Which demonstrates how I can turn make 8:30 am in +2 time zone look the same as for a -4 timezone.

like image 145
Abizern Avatar answered Oct 08 '22 05:10

Abizern


I believe the better way for you is to use timestamp since it independ of any time zone. You can use vary methods to convert timestamps to date and back. And implement any logic you wish.

Also you can easily compare them.

like image 1
Vlad Polyanskiy Avatar answered Oct 08 '22 05:10

Vlad Polyanskiy