Creating NSDate object with specific time zone - ios

I've written a method that accepts a NSDate object and should turn it into a NSDate object with EST time zone. The way I've seen other people accomplish this is by using a date formatter to change the date to a string with the specified time zone. The issue is when I try to change that string back to a NSDate object using "dateFromString".
- (NSDate*)turnToEST:(NSDate*)date
{
NSLog(#"turnToEST called with date %#", date);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"EST"]];
NSString *stringFromDate = [dateFormatter stringFromDate:date];
NSLog(#"date formatted is %#", stringFromDate);
NSDate *dateFromString = [[NSDate alloc] init];
NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc]init];
[dateFormatter2 setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
dateFromString = [dateFormatter2 dateFromString:stringFromDate];
NSLog(#"date has been changed to %#", dateFromString);
return date;
}
With output...
turnToEST called with date 2013-12-19 14:15:17 +0000
date formatted is 2013-12-19 09:15:17
date has been changed to 2013-12-19 14:15:17 +0000
I'm not sure why this is any different than
Converting NSString to NSDate (and back again)

NSDate values do not have an associated time zone, they represent an abstract moment in time. So "a NSDate object with EST time zone" isn't a thing that exists. Time zones only come into play when formatting them for output, or trying to do calendar-based math.
NSLog always uses UTC when printing its output.
So you're taking a moment in time, formatting it to a string in a particular time zone, and then parsing it back into the same moment in time. That's working as intended.

Related

dateFromString results wrong date

Am Trying to convert NSString to NSDate and then store it on Core Data. I added the timezone to NSDateFormatter still it returns wrong output. And is stored in different format in Core Data.
NSString *dateString=#"2015-09-17 01:06:44";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
dateFormatter.locale = [NSLocale currentLocale];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *date_f = [dateFormatter dateFromString:dateString];
NSLog(#"date string %#",dateString);
NSLog(#"date %#",date_f);
NSManagedObject *events=[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:app.context];
[events setValue:date_f forKey:#"start_date"];
Console Output was
date string 2015-09-17 01:06:44
date 2015-09-16 19:36:44 +0000
Data is stored in Core Data as below
start_date = "September 17, 2015";
Thanks.
This looks like a misunderstanding of time zone conversion. A thing that also gave me some headaches in the past :)
Here is what is done:
You have a date string
You tell that this date string is in local time zone
You convert the string to NSDate
NSDate is now an UTC date because there is no time zone information in a NSDate object
Now, about Core Data and NSManagedObject, you can check this answer. I don't know how your are currently getting this start_date value but first thing is to check you Core Data configuration.
Hope this helps.

NSDateFormatter return Date in GMT specific timezone

I want to get the date and time in a specific time zone. I am getting most of the things right but just at the end when i get the date from NSString using NSDateFormatter method it returns me the date in the GMT specific time zone. The method [formatter stringFromDate:gmtDate]; return me the expected date and time. The problem happen when i get the date from the string i-e when i execute this method self.localTime = [formatter dateFromString:str];. self.localTime is a NSDate property in my class.
So when i print the str it gives me the date and time in that specific time zone which is represented as self.timeZoneID, which is also a property on my class
NSDate *gmtDate = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:self.timeZoneID]];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *str = [formatter stringFromDate:gmtDate];
NSLog(#"Date string : %#", str);
self.localTime = [formatter dateFromString:str];
Any idea that what could be the reason that i am getting the right string output but when i assign it to my property localTime it give me the time in GMT
Reason is that NSDate have a default time zone that is GMT for consideration and when a user wants to have time specific for some time zone then NSDateFormatter provides way to set specific time zone which you are using for gmtDate object and not for self.localTime(this is taking GMT ,default time zone).

Why does stringFromDate NSString still have GMT time even though I set timezone on the NSDateFormatter?

The output for the actual NSDate object (firstTime) is what I want it to be (the iOS device's time). The NSString object (secondTime) still seems to be showing the GMT time (which is 4 hours ahead of my local time, EST) even though I set the date formatter (df) to the localTimeZone. Why is it not working?
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm:ss"];
[df setTimeZone:[NSTimeZone localTimeZone]];
NSDate *firstTime = [NSDate dateWithTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT] sinceDate:[NSDate date]];
NSLog(#"%#", firstTime);
NSString *secondTime = [df stringFromDate:firstTime];
NSLog(#"%#", secondTime);
Output:
FIRST TIME: 2014-05-07 17:41:29 +0000, SECOND TIME: 13:41:29
One should let NSDate capture the real date/time, without trying to perform any timezone adjustment, and then let the NSDateFormatter format the string so that it's represented in the desired timezone.
So, looking at your code:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm:ss"];
[df setTimeZone:[NSTimeZone localTimeZone]];
That's fine, though the setting of the timezone to the local timezone is unnecessary. Date formatters default to the current timezone.
But then you proceed to attempt to grab the current time, and adjust it:
NSDate *firstTime = [NSDate dateWithTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT] sinceDate:[NSDate date]];
NSLog(#"%#", firstTime);
While I understand why you attempted to do that, this is incorrect. No adjustment for timezone should be performed. So, that assignment of firstTime should be:
NSDate *firstTime = [NSDate date];
NSLog(#"%#", firstTime);
So, if you did this at 5:41pm (eastern), this NSLog will now report 2014-05-07 21:41:29 +0000, but that's correct (because the +0000 indicates that it's showing you the time in UTC/GMT/Zulu).
Then, if you want to display that in the local timezone, you can take this un-adjusted [NSDate date] and use it with your formatter, like you did in your question:
NSString *secondTime = [df stringFromDate:firstTime];
NSLog(#"%#", secondTime);
That will then report 17:41:29, like you expected it to.
An NSDate does not have a time zone. Read that five times until you understand it.
This:
[NSDate date]
Returns the date that means now. It does not have a time zone. It is not in GMT or in any other time zone. It does not have one. Your code:
[NSDate dateWithTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT] sinceDate:[NSDate date]];
Means a time that isn't now for any user outside GMT. I'll repeat that: your NSDate doesn't describe now. It's like sitting in San Francisco, looking at your watch which is set in the correct local time and it saying 12:00 then telling everybody "that means it is 4AM because we're 8 hours behind GMT".
As a result:
[df stringFromDate:firstTime]
Will build a string that will show a time that isn't now.
Stop thinking you're smarter than everybody that's ever worked at Apple and try this:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm:ss"];
[df setTimeZone:[NSTimeZone localTimeZone]];
NSString *secondTime = [df stringFromDate:[NSDate date]];
NSLog(#"%#", secondTime);
So that says "give me a string of 'now' in the local time zone". Tell me: does it output the correct thing?

Problems converting a string date to NSDate

I have this string date:
2014-04-21T07:55:13Z
when I convert that to NSDate I have the hour like 6:55... 1 hours less. WHY?
This is the code I am using to convert:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
NSDate *newDate = [dateFormatter dateFromString:dateStr];
newDate is now 2014-04-21 06:55:13 +0000 !!!???
what is wrong?
NOTE: That one hour less would make sense if the date was my local time (GMT+1) being converted to GMT. But if that Z is zero offset ( = GMT) the date is already GMT.
I don't think your code is wrong. using this code:-
NSString *dateStr = #"2014-04-21T07:55:13Z";
// Convert string to date object
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
NSDate *date = [dateFormat dateFromString:dateStr];
NSLog(#" date log %#",date); //2014-04-21 02:25:13 +0000 output
// Convert date object to desired output format
[dateFormat setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
dateStr = [dateFormat stringFromDate:date];
NSLog(#"string %#",dateStr); //2014-04-21T07:55:13Z output
but NSLog of NSDATE is not output correct according to this NSDate Format outputting wrong date so your code is right.
The NSDate doesn't know anything about formatting (just date information), and the NSDateFormatter doesnt really know anything about dates, just how to format them. So you have to use methods like -stringFromDate: for know that is current or not to actually format the date for pretty human-readable display.
NSLog(#" date is %#",[dateFormat stringFromDate:date]);

Convert Date with TimeStamp into NSString iOS

I am trying to convert my device current time into Zone (America/New_york)
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"America/New_York"]];
NSDate *start = [NSDate date];
start now has the device current time in IST. How can I convert it into zone 'America'
I planned to do the below
start = [dateFormatter dateFromString:<start date String>];
A Day is categorised into 3 divisions based on a time period.
Say 08:00 - 15:00 AS PHASE1
15:00 - 17:00 AS PHASE2
17:00 - 20:00 AS PHASE3
20:00 - 08:00 AS TRANSITION PHASE and can be ignored.
Am just taking device's date and append the time string to identify in which phase it is.
Example: Indian Time is 05-FEB-2014 01:25 AM (Device Date)
Considering 15:00 as first cutoff.. I append the '05-FEB-2014' to 15:00 and digest it as American timezone.. Which resolves and gives me 06-FEB-2014 02:30 IST(Cut off Date).. So the difference between the both days goes greater than one day!
My expected result could be take device time also in American Timezone and compare with the compare with the nearest cut off time.
NSDate does not have a time zone. It's a single time reference that's valid anywhere. It's basically just an object wrapper for NSTimeInterval-- all it stores is the number of seconds since a reference date. Time zones only apply when converting to/from user-visible strings.
You can get a user-visible string from your date formatter as
NSString *localizedDateString = [dateFormatter stringFromDate:start];
But converting NSDate to a particular time zone is not a meaningful goal. There's no time zone on NSDate, so it's not a conversion that can be applied.
Date of new york :
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
[dateFormatter setTimeZone:timeZone];
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSLog(#"Date : %#", dateString);
Date of all zones :
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSArray *timeZoneNames = [NSTimeZone knownTimeZoneNames];
for (NSString *name in timeZoneNames) {
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:name];
[dateFormatter setTimeZone:timeZone];
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSLog(#"timeZone abbreviation : %#\nName : \"%#\"\nDate : %#\n\n", [timeZone abbreviation], name, dateString);
}
See the stringFromDate Method in the dateformatter. You pass in an NSDateand it converts to the specified format.
UPDATE: Here is how you set the current time zone [dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html

Resources