Search code examples
iphoneipadnsdatensdateformatter

Struggling with NSDate, formats and timezones


The deal is I want a NSDate representation of the date 18th of June 1978. I have tried to init NSDate like

dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
self.dateFormatter.timeStyle = NSDateFormatterNoStyle;
self.startDate = [dateFormatter dateFromString:@"19/06/78"];
NSLog(@"%@", self.startDate);

This produces the right date when the iPhone is set to Danish in the International settings. It does not work with a iPhone set to i.e. english/american settings.

Notice the extra day (19) because denmark is in GMT +1 and i think the NSDate defaults to time 23:00:00. That indicates that something i not working as intended.

I want the above date (18/06/1978) represented a an NSDate object regardless of the timezone, locale and International settings on the device.

How to achieve that?

Edit:

So Ole Begemann's answer seemed to resolve my issue. His solution did create the correct date both on a device in USA International settings and en European international settings. But when Apple should review the app the date created was 17th of June 1978. This makes sence since I'm setting timezone to GMT +0000. And Cupertino is like GMT -0007 or so. So this would give a day earlier.

So to correct my question: I want the 18-06-1978 no matter what locale, timezone the device is physically or settings wise in.

What I'm trying to do is setting a start date 18. june 1978 and later in my app render the date as a string formatted like "780618" (yyMMdd) regardless of the timezone or place of the device. It allways has to be "780618" as this is a key start date for my app.

So I might be attending the problem wrong. Instead of trying to force same date everywhere I maybe should accept the timezone stuff and try to configure the NSDateFormatter to output the right date.

So basically: What I want is THE NSDate instance that formats to "780618" everywhere - in any timezone with any international device settings.

How to achieve this?


Solution

  • I want the above date (18/06/1978) represented a an NSDate object regardless of the timezone, locale and International settings on the device.

    This makes no sense to NSDate. An NSDate always represents a single point in time, so by definition it includes a time and the time zone this time is in (or to be more exact, it stores the time in GMT; the time is only converted to another time zone for display purposes). If you just want the date, you have to make your own definition regarding the time, e.g. to store these dates with a time of midnight GMT.

    When setting a date programmatically, you must always set a time zone and, if you use a date formatter, set the formatter's locale and calendar. This ensures that your code is independent of the user's/device's locale settings.

    I would do it like this:

    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    [dateComponents setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
    [dateComponents setYear:1978];
    [dateComponents setMonth:6];
    [dateComponents setDay:18];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDate *date = [calendar dateFromComponents:dateComponents];
    NSLog(@"%@", date);