I have the following method that takes a given Time (in UTC) as a parameter and converts it to the current time in a let's say 'friendlier format'.
A valid/normal input might be: '11:30' or '1:30' My problem is although the Time Zone set in my device is New York (-4 GMT) and even hardcode in this example! this functions keeps on transforming the time to -5 GMT (6:30 AM and 8:30 PM respectively)
-(NSString*) convertServerTimeToAppTimeFormat:(NSString*) input {
NSDateFormatter *dateFormatInput = [[NSDateFormatter alloc] init];
[dateFormatInput setDateFormat:@"HH:mm"];
[dateFormatInput setTimeZone :[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *date = [dateFormatInput dateFromString:input];
NSDateFormatter *dateFormatInputOutput = [[NSDateFormatter alloc] init];
[dateFormatInputOutput setDateFormat:@"h:mm a"];
[dateFormatInputOutput setTimeZone: [NSTimeZone localTimeZone]];
[dateFormatInputOutput setTimeZone:[NSTimeZone timeZoneWithName:@"America/New_York"]];
return [dateFormatInputOutput stringFromDate:date];
}
There definitely must be something very obvious that I am not seeing. I would normaly use:
[NSTimeZone localTimeZone]
To get the current Time Zone where my user is instead of hard-coding it as I am doing here, but I think that the hard coded version should help to make the bug even more obvious.
The issue is that whether NY is 4 or 5 hours behind GMT/UTC depends upon whether you’re currently in daylight savings or not. We’re currently in “daylight savings” time, but the date formatter is, in the absence of information to the contrary, is going to assume a date of January 1st, 2000, which is not in daylight savings. Hence the disconnect.
But you can set the defaultDate
of the formatter to be today:
NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]];
[dateFormatInput setDefaultDate:today];
The above will have the formatter default to today’s date. Obviously, if your input has a separate field to which identifies what day this time is relevant, then use that.
But by setting defaultDate
, that will let a time-only string know whether it should apply daylight savings or not, yielding the desired timezone conversion.
By the way, I would suggest not using dateFormat
for the output string. Specify the timeStyle
and it will format it appropriately for the user’s device’s settings:
NSDateFormatter *dateFormatInputOutput = [[NSDateFormatter alloc] init];
[dateFormatInputOutput setTimeStyle:NSDateFormatterShortStyle];
return [dateFormatInputOutput stringFromDate:date];
Specifically, if the user has their device configured for 24 hour clock, the above will honor whatever the user has indicated, rather than forcing a format that might not be to their liking.
Also note that you don’t have to force the timezone or locale (unless you really meant to force it to NY even if the user is in CA), as it, too, will default to the user’s device’s settings. That just depends upon whether you really wanted to force it to the Eastern timezone or not.
If you’re reading your date/time strings from web service, you may want to also specify a consistent locale, pursuant to Technical Note 1480. Technically, it a time-only string, this may not be needed, but it’s good practice:
[dateFormatInput setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];