Artem Z.
Artem Z.

Reputation: 1243

iOS 7: Convert NSDate to string with custom timezone and get back new NSDate

I wish to modify current system time (set a custom NSTimeZone) and get back a new NSDate object.

The code I've made

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
NSLog(@"System time: %@", [dateFormatter stringFromDate:[NSDate date]]);
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Aqtobe"]];
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSLog(@"Aqtobe time: %@", dateString);

The output

System time: 2014-02-05 10:00:46 +0000

Aqtobe time: 2014-02-05 15:00:46 +0500

But if I try to get new NSDate object from Aqtobe time:

NSLog(@"New NSDate: %@", [dateFormatter dateFromString:dateString]);

I get

New NSDate: 2014-02-05 10:02:40 +0000

Where I was wrong? Thanks in advance

Upvotes: 1

Views: 13160

Answers (3)

Nitesh Borad
Nitesh Borad

Reputation: 4663

NSDate always returns date in GMT +0:00. So, it (NSDate object) always have correct converted value but in GMT +0:00. So for using it as text you will always have to use same date formatter with same zone. If you want to use date as string from date in other places (out of dateformatter object scope), it is better to make special method for conversion.

It is explained clearly below with example:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss Z";

NSLog(@"System time: %@", [dateFormatter stringFromDate:[NSDate date]]);

[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Aqtobe"]];

NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSLog(@"Aqtobe time: %@", dateString);

// date will always contain value in GMT +0:00
NSDate *date = [dateFormatter dateFromString:dateString];
NSLog(@"New NSDate (NSDate): %@", [dateFormatter stringFromDate:date]);

// converts date into string
NSLog(@"New NSDate (NSString): %@", [dateFormatter stringFromDate:date]);

For detailed explaination you can refer this question: Does [NSDate date] return the local date and time?

Upvotes: 3

Gad
Gad

Reputation: 2877

NSDate has many methods for comparing date such as isEqualToDate: (for a more detailed of the methods and usage you can see this SO question). This method, that I took from here, will let you determine if date is between firstDate and lastDate.

- (BOOL)isDate:(NSDate *)date inRangeFirstDate:(NSDate *)firstDate lastDate:(NSDate *)lastDate {
   return [date compare:firstDate] == NSOrderedDescending &&
          [date compare:lastDate]  == NSOrderedAscending;
}

I hope this is what you meant. If not please explain exactly what you're trying to do.

Upvotes: 1

Gianluca Tranchedone
Gianluca Tranchedone

Reputation: 3598

You can use NSDateComponents and NSCalendar to create a new date. From the Date and Time Programming Guide

Creating Dates with Time Zones

Time zones play an important part in determining when dates take place. Consider a simple calendar application that keeps track of appointments. For example, say you live in Chicago and you have a dentist appointment coming up at 10:00 AM on Tuesday. You will be in New York for Sunday and Monday, however. When you created that appointment it was done with the mindset of an absolute time. That time is 10:00 AM Central Time; when you go to New York, the time should be presented as 11:00 AM because you are in a different time zone, but it is the same absolute time. On the other hand, if you create an appointment to wake up and exercise every morning at 7:00 AM, you do not want your alarm to go off at 1:00 PM simply because you are on a business trip to Dublin—or at 5:00 AM because you are in Los Angeles.

NSDate objects store dates in absolute time. For example, the date object created in Listing 16 represents 4:00 PM CDT, 5:00 EDT, and so on.

Listing 16 Creating a date from components using a specific time zone

NSCalendar *gregorian=[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar
[gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"CDT"]];

NSDateComponents *timeZoneComps=[[NSDateComponents alloc] init]; [timeZoneComps setHour:16];
//specify whatever day, month, and year is appropriate
NSDate *date=[gregorian dateFromComponents:timeZoneComps];

If you need to create a date that is independent of timezone, you can store the date as an NSDateComponents object—as long as you store some reference to the corresponding calendar.

In iOS, NSDateComponents objects can contain a calendar, a timezone, and a date object. You can therefore store the calendar along with the components. If you use the date method of the NSDateComponents class to access the date, make sure that the associated timezone is up-to-date.

Anyway, keep in mind that a date is a unique point in time. What you display to the user is different based on their locale and time zone.

Upvotes: 0

Related Questions