Why isn't my time zone being saved into my NSDate? - objective-c

I must initialize an NSDate object from NSString in objective-c. I do it like this:
NSString *dateString = [[webSentence child:#"DateTime"].text stringByReplacingOccurrencesOfString:#"T" withString:#" "];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-mm-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"Europe/Budapest"]];
NSDate *date = [[NSDate alloc] init];
date = [dateFormatter dateFromString:dateString];
E.g: when I try it with string value #"2011-01-02 17:49:54" I get an NSDate 2011-01-02 16:49:54 +0000. As you can see there is a one hour difference between the two values. NSDate has a wrong value, it should be exactly the same I defined in my string in the timezone I set in dateFormatter. It seems it uses my date defined it string as UTC, even if I set its timezone to "Europe/Budapest". How can I fix this problem?
Thanks!

NSDate stores dates relative to a standard reference date. From the class docs:
"The sole primitive method of NSDate, timeIntervalSinceReferenceDate, provides the basis for all the other methods in the NSDate interface. This method returns a time value relative to an absolute reference date—the first instant of 1 January 2001, GMT."
NSDate does not itself have any concept of time zones. So the NSDateFormatter did the right thing: it converted a date which you told it had a GMT offset (by specifying a time zone), and gave you a "normalized" NSDate for that date.
If you want to see the date represented in the Europe/Budapest time zone, either use your existing date formatter (-stringFromDate:) or the appropriate NSDate description method (e.g. -descriptionWithCalendarFormat:timeZone:locale:).
P.S.- You don't need an alloc/init at all in your code as written. In non-ARC that would be a leak.
P.P.S.- Your date format is incorrect and giving nonsensical results. I've gone ahead and cleaned up your code as follows (tested under ARC):
NSString *dateString = #"2011-09-02 17:49:54";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *tz = [NSTimeZone timeZoneWithName:#"Europe/Budapest"];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:tz];
NSDate *date = [dateFormatter dateFromString:dateString];
NSLog(#"%#", [dateFormatter stringFromDate:date]);
NSLog(#"%#", [date descriptionWithCalendarFormat:nil timeZone:tz locale:nil]);

Two things:
1) you have an error in your date format string. You should use MM for month, not mm (lowercase mm is for minutes)
2) after you create you NSDate object, you'll need to use the NSDateFormatter method stringFromDate: to generate a date string localized to a particular timezone. If you just do a straight NSLog() on the NSDate object it will show the date as GMT by default (GMT is one hour behind Budapest time)

Related

Not getting NSDate from string

I have following date in string formate "date string : 2014-09-28 17:30:00"
Now, I want to convert it into NSDate.
I have use following code for this.
NSString *date = #"2014-09-28 17:30:00";
NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *dateFromString = [[NSDate alloc] init];
dateFromString = [dateFormatter1 dateFromString:date];
NSLog(#"date from string: %#", dateFromString);
I got the following output.
date from string: 2014-09-28 12:00:00 +0000
So, Here Time is changed.
Please tell me, How can I convert into NSDate. What I am missing here?
When you pass an NSDate object into NSLog, it will print the NSDate in GMT time, which may not be your timezone (and why you were getting 12:00 instead of 17:30), this would also cause the output of your NSLog statement to be different for people who are running your code in different timezones, so what you want to do is call the [NSDateFormatter stringFromDate:] method if you want to keep your specified time from your date object:
So replace this line of code:
// Will print out GMT time by default (+0000)
NSLog(#"date from string: %#", dateFromString);
With this line:
// Will honor the timezone of your original NSDate object:
NSLog(#"date from string: %#", [dateFormatter1 stringFromDate:dateFromString]);
And that should print out the value you were hoping for.
// --------------------------//
Note: It is important to understand that NSDate objects do not have any concept of timezones, so it is up to the developer to manage and track their timezones with the provided platform methods.
On iOS, you can look into using this class:
NSTimeZone, which can help you manage/assign your timezone(s) on iOS platforms.
If you are developing for OSX, you can assign a timezone and locale with this method: -descriptionWithCalendarFormat:timeZone:locale:. (Sadly, this method is OSX-only)
Hope that helps.
There is a time zone component attached to your log at the end that means the date is converted to the specified time zone..here greenwhich mean time
So converting into your time locale can give you the right value you inserted
In your first string add +0000 to the end and check again you can see the value is the same you get.ie the conversion is done on the GMT format
visit https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html
This documentation provides you how to convert NSString to date.
this code is provided by apple documentation.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:162000];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
NSLog(#"formattedDateString: %#", formattedDateString);
// Output for locale en_US: "formattedDateString: Jan 2, 2001".
To make string as date
NSString *formattedDateString = [dateFormatter stringFromDate:date];
stringFromDate:
Returns a string representation of a given date formatted using the receiver’s current settings.
what you had used
dateFromString:
Returns a date representation of a given string interpreted using the receiver’s current settings.

NSDateFormatter: Converting "5/13/2012 6:05am" (US, EDT) to "13/05/2012 12:05" (IT, GMT+1)

I am retrieving a time value from a server. The format is:
"5/13/2012 6:05am"
It is not specified in the string but I know it is "EDT".
I need to:
1) Get rid of the am/pm thing.
2) Convert it from EDT (or other timezone) to the local GMT+/-x time.
For my timeZone (Italy, GMT+1) it should become:
"13/05/2012 12:05"
How can I do this with NSDateFormatter?
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale: [NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
[dateFormatter setDateFormat:#"dd-MM-yyyy HH:mm"];
...?
Thanks
Nicola
First of all, you set your NSDateFormatters dateFormat to the source format. In your case:
[dateFormatter setDateFormat:#"M/d/yyyy h:mma"];
NSDate *myDate = [dateFormatter dateFromString:#"5/13/2012 6:05am"];
This creates a new instance of NSDate. Now you set the formatters dateFormat to your target format:
[dateFormatter setDateFormat:#"dd/MM/yyyy hh:mm"];
NSString *myString = [dateFormatter stringFromDate:myDate];
You could also use two date formatters, one for converting you'r string into NSDate instance and one to convert it back to the corrected NSString.
For further informations and the complete list of the current format specs refer to the unicode reference and the Apple Docs

Objective-C – NSDateFormatter dateFromString ignore time

If I'm not interested in the time can I ignore it? I.e I have a date string that looks like this #"2012-12-19T14:00:00" but I'm only interested in getting the date (2012-12-19) but if I set NSDateFormatter like [dateFormatter setDateFormat:#"yyyy-MM-dd"]; it will return me a nil NSDate.
An NSDate object will always contain a time component as well, as it is representing a point in time — from this perspective one could argue the name NSDate is misleading.
You should create a date formatter for creating dates from string, set the time to the start of the day and use a second date formatter to output the date without time component.
NSString *dateString = #"2012-12-19T14:00:00";
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
[inputFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss"];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateStyle:NSDateFormatterShortStyle];
[outputFormatter setTimeStyle:NSDateFormatterNoStyle];
NSDate *date = [inputFormatter dateFromString:dateString];
//this will set date's time components to 00:00
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
startDate:&date
interval:NULL
forDate:date];
NSString *outputString = [outputFormatter stringFromDate:date];
NSLog(#"%#", outputString);
results in
19.12.12
while the format — as it is chosen by styling — will be dependent of your environment locale
all date string returns 10 characters for the date, what i mean is the date of todayy will be 2012-11-19
you can easily substring the date and use it as you want:
Example :
NSString* newDate = #"";
newDate = [[NSDate date]substringToIndex:10];
the out put will be : 2012-11-19

Create NSDate timezone issue

I am loading in dates from my web service, I'm sending dates in the format (GMT times): 02/11/11 10:56:09
I am creating an NSDate form this using NSDateFormatter as such:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss"];
NSDate *journeyDate = [dateFormatter dateFromString:str];
[dateFormatter release];
This works great, after I'm comparing this to the current date to get relative time intervals.
The problem is when the phone is set up in a different timezone, when I load in the date from my api, and use the date formatter, what seems to be happening is the phone is assuming the date string is local time and it's converting it to GMT.
Example:
I load in a date with the time 10am from the api.
The phone is set to PDT.
The date formatter is creating an NSDate assuming that my date string with 10am, is actually relevant to the phone.
I end up with a date and time equal to 5pm, adding 10 hours.
I am trying to specify in my date formatter that the string is GMT, but I'm having trouble, I've tried the following, adding GMT to the format:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss GMT"];
NSDate *journeyDate = [dateFormatter dateFromString:str];
[dateFormatter release];
This is not working.
Can anyone give any advice ?
Solution
Just a recap, I got it working with a terrible work around by appending GMT to the original string, and formatting that:
NSString * cheat = [NSString stringWithFormat:#"%# GMT", str];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss zzzz"];
NSDate *journeyDate = [dateFormatter dateFromString:cheat];
[dateFormatter release];
return journeyDate;
This was a kind of unstable hack, because if the string changed to include a timezone, it wouldn't work anymore. For anyone who needs to do as myself, the following is just a quick example on how to create an NSTimeZone.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"UTC"]];
NSDate *journeyDate = [dateFormatter dateFromString:str];
[dateFormatter release];
return journeyDate;
Thanks for the quick help.
I suspect you just want to use NSDateFormatter.setTimeZone to force it to use UTC. You don't want to change the format string because presumably the string doesn't include the letters "GMT" - instead, you want to change which time zone the string is interpreted in, which is what setTimeZone will do.
You should use the setTimeZone method: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html

Issues with String to NSDate

My dateFromString is not working and i'm not sure why
NSString *purchase = #"2011-09-30 17:47:57";
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSDate *date = [dateFormat dateFromString:purchase];
date is 'invalid CFStringRef'
See anything i might be overlooking?
Try changing the hours in the formatter to capitals, i.e. yyyy-MM-dd HH:mm:ss
I'm not sure if that will solve your error, but that is the correct way to parse a 24 hour time
in the format
"hh" means Hour [1-12].
"HH" means Hour [0-23].
See UTS Date Field Symbol Table for the date format specifiers.
Try this:
NSString *purchase = #"2011-09-30 17:47:57";
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [dateFormat dateFromString:purchase];
Date Formatters Guide - HH is used for 24 hour times, hh for 12 hour.
If you mean that "date" is not accepted as an NSString by another function, that's because it's not a string, it's an NSDate.
(Where, precisely, are you getting the error message, and what is the full text?)