Below is a string represented a date
NSString *dateStr = #"2011-07-06";
And when I am trying to convert it to NSDate by doing :
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"yyyy-MM-dd"];
NSDate *tmp = [format dateFromString:dateStr];
NSLog(#"tmp is %#",[tmp description]);
What I am getting from the console is
tmp is 2011-07-06 04:00:00 +0000
I dont understand why I am getting extra info :04:00:00 +0000 for the result
Please help if you experienced it before
Your code
NSString *dateStr = #"2011-07-06";
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"yyyy-MM-dd"];
NSDate *tmp = [format dateFromString:dateStr]
will result in a NSDate object, that represents your local time at 0:00 — the beginning of the day.
but if you print a plain date object, it will result in a string that represents the time in GMT timezone, as internally all dates are normalized to that timezone.
As your string is 4 hours ahead, we can tell, that you most likely are in East Europe, maybe Moscow.
So if you want to see the string in your timezone, you need to use a NSDateFormatter to create it from the date object.
NSLog(#"tmp is %#",[formatter stringFromDate:tmp]);
to check, if it is correct, what I said, change the format to contain the time components.
formatter.format = [#"yyyy-MM-dd HH:mm"];
NSLog(#"tmp is %#",[formatter stringFromDate:tmp]);
The formatter will also take "oddities" like Leap Day, Leap Month (yes — those exits), Daylight Saving Times, Leap Seconds … in account — accordantly to the current calendar.
A great WWDC 2011 Video: Performing Calendar Calculations — a must-see for every cocoa developer.
BTW: to print a object with NSLog you dont need to call -description on it to pass in a string. NSLog will do this internally.
NSLog(#"tmp is %#", tmp);
is just fine.
The answer is simple, NSLog just converts the NSDate to a NSString, using its formatter with GMT (zero) timezone.
Your formatter is by default set to your default time zone, which is probably -4:00. When you print it out, NSLog converts it to 0:00, adding 4 hours.
In general, it's unsafe to parse dates without specifying their timezone.
Related
I am trying to get a NSDate object from a UTC time string. The example of the time string is this:
2016-07-29T11:43:55+02:00
I am usingNSDateFormatter and set the formate as: yyyy-MM-dd'T'HH:mm:ss
However this gives me the take with incorrect time zone. So the above date will be: 2016-07-29T09:43:55+00:00
How do I keep the time zone aspect as well?
I did try adding a 'Z' to the end of the formatter but that just returns a nil date.
Try this
NSDateFormatter *userFormatter = [[NSDateFormatter alloc] init];
[userFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
NSLocale *posix = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[userFormatter setLocale:posix];
NSString *dateConverted = [userFormatter stringFromDate:theDate];
Thanks to all that help. Solved the issue. The time on my iOS Simulator was correct. However when I called [NSDate date]; it show'd me a time two hours before local time. Hence the 'errors' I was seeing in the formatting of NSDate.
Use NSISO8601DateFormatter if targeting iOS 10 and above. https://developer.apple.com/documentation/foundation/nsiso8601dateformatter
I'm trying to convert a string to an NSDate,
however the format always comes out as nil
The date I'm trying to convert is:
2012-08-16T16:20:52.619000+00:00
The date format I'm trying is:
#"yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZ"
If I change the date to:
#"2012-08-16T16:20:52.619000+0000" // removing the : from +00:00
it works a treat, however I would
(I have also tried
#"yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZ:ZZ"
#"yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZ':'ZZ"
but that didn't work either).
Is it even possible to do this without doing string manipulation and removing the final ":"?
I did a final search around this and found out that you have to use
getObjectValue
rather than
dateFromString
In case someone else runs in to this issue, I post my method for converting such strings to NSDate
+ (NSDate *)dateFromString:(NSString *)dateString {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ"];
NSDate *theDate = nil;
NSError *error = nil;
[dateFormat getObjectValue:&theDate forString:dateString range:nil error:&error];
[dateFormat release];
return theDate;
}
It looks like you are using ISO 8601 formatted dates. If you are getting these from a web service, the format changes according to the format. Check this out:
http://boredzo.org/iso8601parser/
This will convert dates according to the format, and even when the format changes slightly.
How about something like
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
the Z has to be in single quotes.
I'm using the following code to set my timezone to Stockholm, Europe.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"Europe/Stockholm"]];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm"];
NSDate *webUpdateDate = [dateFormatter dateFromString:#"2011-07-22 22:10"];
// Outputs "2011-07-22 20:10 +0000"
Anyone know why?
I assume you're inspecting the date using NSLog. An NSDate object represents an absolute time -- it has no notion of time zone, so when it is asked for its description, it displays as if it were a time in GMT. If you want that absolute time represented for the Stockholm time zone, you need to use the date formatter again:
NSLog(#"%#", [dateFormatter stringFromDate:webUpdateDate]);
Since the date was originally created via the formatter, which already had its time zone set to Stockholm, I believe this will give you the same string that you used for input: #"2011-07-22 22:10".
how I can convert an epoch time value to NSDate. For example I use this value : 1310412600000. and I am in the EDT time zone.
When I try this :
NSString *bar = [[NSDate dateWithTimeIntervalSince1970:epoch] description];
I got a wrong value...
What is the good way? I spend a lot of time with that....
Thanks
Epoch time (also known as "Unix" and "POSIX" time) is the number of seconds since the start of 1970. You can convert epoch time to NSDate with this algorithm:
Instantiate NSDate object and pass the epoch time as a parameter to NSDate's initWithTimeIntervalSince1970 initializer. You're done. The NSDate object is set to the epoch time. NSDate stores times internally in the UTC time zone. It's up to you how it is displayed.
[Optional] Format your NSDate to the appropriate time zone with an NSDateFormatter.
Here's the code I used:
// Sample string epochTime is number of seconds since 1970
NSString *epochTime = #"1316461149";
// Convert NSString to NSTimeInterval
NSTimeInterval seconds = [epochTime doubleValue];
// (Step 1) Create NSDate object
NSDate *epochNSDate = [[NSDate alloc] initWithTimeIntervalSince1970:seconds];
NSLog (#"Epoch time %# equates to UTC %#", epochTime, epochNSDate);
// (Step 2) Use NSDateFormatter to display epochNSDate in local time zone
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss zzz"];
NSLog (#"Epoch time %# equates to %#", epochTime, [dateFormatter stringFromDate:epochNSDate]);
// (Just for interest) Display your current time zone
NSString *currentTimeZone = [[dateFormatter timeZone] abbreviation];
NSLog (#"(Your local time zone is: %#)", currentTimeZone);
Per the documentation, dateWithTimeIntervalSince1970: runs from January 1, 1970, 00:00 GMT. So you should be getting results four hours later than those you really want.
Hence the simplest thing — if you don't mind hard coding the offset from GMT to EDT — would seem to be:
[[NSDate dateWithTimeIntervalSince1970:epoch] dateByAddingTimeInterval:-240]
// or:
[NSDate dateWithTimeIntervalSince1970:epoch - 240]
Though to eliminate arbitrary constants (and be a little cleaner), you probably want something like:
NSTimeZone *EDTTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"EDT"];
NSInteger secondsDifferenceFromGMT =
[EDTTimeZone secondsFromGMTForDate:[NSDate dateWithTimeIntervalSince1970:0]];
NSDate *startOfEpoch =
[NSDate dateWithTimeIntervalSince1970:secondsDifferenceFromGMT];
...
NSDate *newDate = [startOfEpoch dateByAddingTimeInterval:firstInterval]; // etc
Are you passing the value in seconds?
The method accepts value in seconds , not milliseconds.
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/Reference/Reference.html
I've read the DateFormatting guide and I'm still not able to get a working formatter.
NSString *string = #"0901Z 12/17/09";
//This is a sample date. The Z stands for GMT timezone
//The 0901 is 09h 01m on a 24 hour clock not 12.
//As long as I can get the hours/min & date from the string I can deal with the time zone later
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"hhmm'Z' MM/dd/yy"];
NSDate *date = [dateFormat dateFromString:string];
That works for me when I try it. Adding NSLog(#"%#", date) to the end of your code gives me this output:
2010-02-28 12:17:22.921 app[9204:a0f] 2009-12-17 09:01:00 -0800
What is the problem you're seeing?
Edit: I figured it out, you're not having a problem with 09:01, but with other 24-hour times, like 14:25, right? Change your formatter to:
#"HHmm'Z' MM/dd/yy"
Copied from a similar question I answered here: NSDateFormatter returns nil for #"dd-MM-yy" in iOS 3.0
If you're working with user-visible dates, you should avoid setting a date format string. Formatting dates this way is not localizable and makes it impossible to predict how your format string will be expressed in all possible user configurations. Rather, you should try and limit yourself to setting date and time styles (via -[NSDateFormatter setDateStyle:] and -[NSDateFormatter setTimeStyle:]).
On the other hand, if you're working with fixed-format dates, you should first set the locale of the date formatter to something appropriate for your fixed format. In most cases the best locale to choose is "en_US_POSIX", a locale that's specifically designed to yield US English results regardless of both user and system preferences. "en_US_POSIX" is also invariant in time (if the US, at some point in the future, changes the way it formats dates, "en_US" will change to reflect the new behaviour, but "en_US_POSIX" will not), and between machines ("en_US_POSIX" works the same on iPhone OS as it does on Mac OS X, and as it it does on other platforms).
Once you've set "en_US_POSIX" as the locale of the date formatter, you can then set the date format string and the date formatter will behave consistently for all users.
The above info and more can be found in Apple's Technical Q&A QA1480
Here's a snippet of code from my app which implements the above recommendation :
static NSDateFormatter* dateFormatter = nil;
if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale = [[[NSLocale alloc]
initWithLocaleIdentifier:#"en_US_POSIX"] autorelease];
NSAssert(enUSPOSIXLocale != nil, #"POSIX may not be nil.");
[dateFormatter setLocale:enUSPOSIXLocale];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
dateFormatter.dateFormat = #"EEE, dd MMM yyyy HH:mm:ss +0000";
}