NSDate show wrong date with NSTimezone - ios

Hi I am trying to display GMT time to my device time.
my device time zone is EDT.
I got the GMT time as a string
// GMT Time-----2014-11-27 19:32:00
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"HH:mm:ss";
NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
[dateFormatter setTimeZone:gmt];
NSDate *startDate = [dateFormatter dateFromString:#"2014-11-27 19:32:00"];
I am getting this start date as -
//startDate---2014-11-27 19:32:00 +0000
Now I am trying to convert this into my local time
NSDateFormatter *dateFormatter2 = [[NSDateFormatter alloc] init];
dateFormatter2.dateFormat = #"hh:mm a";
NSTimeZone *local = [NSTimeZone localTimeZone];
[dateFormatter2 setTimeZone:[NSTimeZone localTimeZone]];
NSString *startDateStr = [dateFormatter2 stringFromDate:startDate];
As per my timezone(EDT) the result must be - 3:32 PM
But I am getting wrong time as
//startDateStr---02:32 PM
I have printed my timezone difference with GMT
NSLog(#"TimeZone %d",[[NSTimeZone localTimeZone] secondsFromGMT]);
// TimeZone -14400 - this correct and as per this the startDate must be 03:32 PM
Where I am making the mistake ?
Please help me

Very clever. The date that you converted was on January 1st 2000. So daylight savings time was different back then. 19:32 GMT on the 1st of January was 2:32pm in your time zone. But 19:32 GMT today is 3:32pm in your time zone.

Related

Converting string to date returns nil swift 4? [duplicate]

When I was trying to convert April from 04 (MM) to Apr (MMM) it turned back into nil, is this a known issue in iOS or am I doing something wrong?
Here's my code for inspection:
NSString *dateString=#"2016-04-01";
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
NSDate* myDate = [dateFormatter dateFromString:dateString];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM"];
NSString *stringFromDate = [formatter stringFromDate:myDate];
NSLog(#"%# == %#",dateString,stringFromDate);
when change dataString=#"2015-04-01" the stringFromDate returns Apr
This is my output:
this is the log image
2016-04-01 12:17:45.708[32172:2389414] 2016-04-01 == (null)
2016-04-01 12:17:47.446[32172:2389414] 2015-04-01 == Apr
This is probably a problem in your time zone. Note that when parsing a date without time, the time is assumed to be zero. However, some specific times don't exist, usually due to Daylight Saving Time changes (which happen in March around the world) or due to specific local time changes.
For example, in Jordan, the DST change is Apr 1 2016, 00:00 => Apr 1 2016, 01:00. That means that the time Apr 1 2016, 00:00 does not exist because March 31 2016, 23:59 becomes immediately Apr 1 2016, 01:00. If the date does not exist, date formatter must return nil.
You can usually fix the problem by using a preset GMT time zone that does not have this problem, e.g
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
or
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:[NSTimeZone systemTimeZone].secondsFromGMT];
Note that since you are not parsing time, time zone differences shouldn't affect you.
Steps to reproduce
Set the time zone on your machine to Jordan time zone:
NSString *dateString = #"2016-04-01";
NSDateFormatter* parsingFormatter = [[NSDateFormatter alloc] init];
parsingFormatter.dateFormat = #"yyyy-MM-dd";
NSLog(#"Parsed: %#", [parsingFormatter dateFromString:dateString]); // "(null)"
with time zone fix:
NSString *dateString = #"2016-04-01";
NSDateFormatter* parsingFormatter = [[NSDateFormatter alloc] init];
parsingFormatter.dateFormat = #"yyyy-MM-dd";
parsingFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
NSLog(#"Parsed: %#", [parsingFormatter dateFromString:dateString]); // "2016-04-01 00:00:00 +0000"
I tried your code and it gives me null for year 2022, but years 2018,2020 it gives Apr ... weird!
NSString *dateString=#"2022-04-01";
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
NSDate* myDate = [dateFormatter dateFromString:dateString];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"+5:30"]];
[dateFormatter setDateFormat:#"MMM"];
NSString *stringFromDate = [dateFormatter stringFromDate:myDate];
NSLog(#"%# == %#",dateString,stringFromDate);
UPDATE:
Please parse the string as this :
2016-04-01 01:00
Because of daylight saving in Jordan the clock will be shifted +1 hour so there's no time in the universe like this:
2016-04-01 00:00
This should resolve ur issues with the nil object.

iOS 9 : Add GMT Time Value

I had search on google how to get GMT Time in Objective-C, and I got this :
+ (NSString *)GetGMTTime{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd'T'HH:mm";
NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
[dateFormatter setTimeZone:gmt];
return [dateFormatter stringFromDate:[NSDate date]];}
Is there any way to add or set GMT Time ? (GMT+5)
The most flexible way is to use timeZoneForSecondsFromGMT. This is more typo proof than using strings like GMT+X.
Here is a fuly working example:
+ (NSString *)GetGMTTime{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd'T'HH:mm";
NSTimeZone *gmt = [NSTimeZone timeZoneForSecondsFromGMT:(60*60*5)];
[dateFormatter setTimeZone:gmt];
return [dateFormatter stringFromDate:[NSDate date]];
}
It returns 2016-08-29T12:13 (when GMT time is 2016-08-29T7:13)
Note: 60*60*5 means 5 hours X 60 minutes X 60 seconds
Can try like this.
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"GMT+5:30"];
If you create NSDate instance then it will return date in UTC or GMT format by default.
Now when you convert this date to string by any date formatter then returned string (date) will be in local timezone (i.e. device's time zone).
You can create custom timezone with it's name to get date in that timezone.
NSDate *date = [NSDate date]; //give current date in UTC or GMT
NSLog(#"current date in gmt : %#",date);
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *dateInStrFormat = [df stringFromDate:date]; // this date(string format) will be in current timezone that was set in your device and
NSLog(#"current date in local or device's default timezone : %#",dateInStrFormat);
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"Asia/Kolkata"];
NSLog(#"timezone : %#",timeZone);
[df setTimeZone:timeZone];
NSString *dateInCustomTimeZone = [df stringFromDate:date]; // this will return date in Asia/Kolkata's timezone
NSLog(#"date in custom timezone : %#",dateInCustomTimeZone);
NSLog(#"timezone : %#",timeZone); will print something like, Asia/Kolkata (IST) offset 19800. 19800 is offset, if you divide it with 3600 then you will get difference with gmt like (+/- 5.30 etc)
Link for different timezone names
Or you can got timezone like,
NSTimeZone *timezone1 = [NSTimeZone timeZoneWithName:#"GMT+5:30"];
NSLog(#"timezone : %#",timezone1);
NSTimeZone *timeAone2 = [NSTimeZone timeZoneForSecondsFromGMT:60*60*5.5];
NSLog(#"timezone : %#",timeAone2);

Bug when trying to parse date in Objective-C

When I was trying to convert April from 04 (MM) to Apr (MMM) it turned back into nil, is this a known issue in iOS or am I doing something wrong?
Here's my code for inspection:
NSString *dateString=#"2016-04-01";
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
NSDate* myDate = [dateFormatter dateFromString:dateString];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM"];
NSString *stringFromDate = [formatter stringFromDate:myDate];
NSLog(#"%# == %#",dateString,stringFromDate);
when change dataString=#"2015-04-01" the stringFromDate returns Apr
This is my output:
this is the log image
2016-04-01 12:17:45.708[32172:2389414] 2016-04-01 == (null)
2016-04-01 12:17:47.446[32172:2389414] 2015-04-01 == Apr
This is probably a problem in your time zone. Note that when parsing a date without time, the time is assumed to be zero. However, some specific times don't exist, usually due to Daylight Saving Time changes (which happen in March around the world) or due to specific local time changes.
For example, in Jordan, the DST change is Apr 1 2016, 00:00 => Apr 1 2016, 01:00. That means that the time Apr 1 2016, 00:00 does not exist because March 31 2016, 23:59 becomes immediately Apr 1 2016, 01:00. If the date does not exist, date formatter must return nil.
You can usually fix the problem by using a preset GMT time zone that does not have this problem, e.g
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
or
dateFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:[NSTimeZone systemTimeZone].secondsFromGMT];
Note that since you are not parsing time, time zone differences shouldn't affect you.
Steps to reproduce
Set the time zone on your machine to Jordan time zone:
NSString *dateString = #"2016-04-01";
NSDateFormatter* parsingFormatter = [[NSDateFormatter alloc] init];
parsingFormatter.dateFormat = #"yyyy-MM-dd";
NSLog(#"Parsed: %#", [parsingFormatter dateFromString:dateString]); // "(null)"
with time zone fix:
NSString *dateString = #"2016-04-01";
NSDateFormatter* parsingFormatter = [[NSDateFormatter alloc] init];
parsingFormatter.dateFormat = #"yyyy-MM-dd";
parsingFormatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
NSLog(#"Parsed: %#", [parsingFormatter dateFromString:dateString]); // "2016-04-01 00:00:00 +0000"
I tried your code and it gives me null for year 2022, but years 2018,2020 it gives Apr ... weird!
NSString *dateString=#"2022-04-01";
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
NSDate* myDate = [dateFormatter dateFromString:dateString];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"+5:30"]];
[dateFormatter setDateFormat:#"MMM"];
NSString *stringFromDate = [dateFormatter stringFromDate:myDate];
NSLog(#"%# == %#",dateString,stringFromDate);
UPDATE:
Please parse the string as this :
2016-04-01 01:00
Because of daylight saving in Jordan the clock will be shifted +1 hour so there's no time in the universe like this:
2016-04-01 00:00
This should resolve ur issues with the nil object.

Iphone date format

I was trying to format a time from GMT+7 to GMT+3:
I am building an app with a world clock in specific country (the user will be at the GMT+7and I want to represent the GMT+3 time )
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale];
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:118800];
NSLocale *USLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:USLocale];
NSLog(#"Date for locale %#: %#",
[[dateFormatter locale] localeIdentifier], [dateFormatter stringFromDate:date]);
I looked deep into NSDate class reference but I didn't understand how to make it.
Please if someone can help me I will be grateful.
There is 2 important parameters that works separately: Time and Time Zone.
e.g: Vietnam uses GMT+7
If I know that the time in Vietnam is 9:00 AM, then GMT time is 2:00 AM.
When you get the Date from your device you are getting Time and Time Zone: YYYY-MM-DD HH:MM:SS ±HHMM. Where ±HHMM is a time zone offset in hours and minutes from GMT.
Usually you are only using time. However with NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"GMT"] you can tell the NSDateFormatter that you want the GMT time related to your local Time Zone. So, with:
NSDateFormatter *dt = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"GMT"];
[dt setTimeZone:timeZone];
You can get the GMT date of your local time zone date.
So, If you have GMT+7: 9:00 AM and you want to print out GMT+3: 5:00 AM, you have 3 possibilities:
NSDate *localDate = [NSDate date];
OPTION 1
Add a time interval of -4 hours:
NSTimeInterval secondsInFourHours = -4 * 60 * 60;
NSDate *dateThreeHoursAhead = [localDate dateByAddingTimeInterval:secondsInFourHours];
NSDateFormatter *dt = [[NSDateFormatter alloc] init];
[dt setDateFormat:#"h:mm a"];
NSLog(#"GMT+7(-4) = %#", [dt stringFromDate:dateThreeHoursAhead]);
This is the easiest way to do it. If you are always at GMT+7 and you need GMT+3, this is a time interval of -4 hours.
OPTION 2
Set the time to GMT time zone and then add a +3hours time interval. The easiest way to do it is to add the 3 hours first and then move the time to GMT:
NSTimeInterval secondsInThreeHours = 3 * 60 * 60;
NSDate *dateThreeHoursAhead = [localDate dateByAddingTimeInterval:secondsInThreeHours];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"GMT"];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"h:mm a"];
NSString *date = [dateFormatter stringFromDate:dateThreeHoursAhead];
NSLog(#"GMT+3 = %#", date);
OPTION 3
This is the better option. GMT+3 is EAT (East Africa Time) you can set your time zone to EAT with: [NSTimeZone timeZoneWithName:#"EAT"]
NSDateFormatter *dt = [[NSDateFormatter alloc] init];
[dt setDateFormat:#"h:mm a"];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"EAT"];
[dt setTimeZone:timeZone];
NSLog(#"EAT = %#", [dt stringFromDate:localDate]);
Option 3 is always retrieving GMT+3
An example code here.

Incorrect output from NSDateFormatter

I'm getting some strange output from a NSDateFormatter. I'm converting a date from GMT to the system time zone, which is EDT. This should be -4 hours from GMT.
-(NSDate*)parseDate:(NSString*)inStrDate {
NSLog(#"Date To Parse %#", inStrDate);
NSDateFormatter* dtFormatter = [[NSDateFormatter alloc] init];
[dtFormatter setLocale:[NSLocale systemLocale]];
[dtFormatter setTimeZone:[NSTimeZone systemTimeZone]];
[dtFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss +0000"];
NSDate* dateOutput = [dtFormatter dateFromString:inStrDate];
NSLog(#"Parsed Date %# %#", dateOutput, [NSTimeZone systemTimeZone]);
return dateOutput;
}
Log output:
2012-09-15 22:32:53.358 Date To Parse 2012-09-16 02:32:53 +0000
2012-09-15 22:32:53.360 Parsed Date 2012-09-16 06:32:53 +0000 America/New_York (EDT) offset -14400 (Daylight)
But it's returning +4 hours instead of -4. So where it should output 22.30 EDT (02.30 GMT) it's actually returning 06.30 EDT. Which is 8 hours in the future.
Can anyone help me understand if I'm going wrong somewhere here? I'm scratching my head but I can't figure out why this wont seem to work.
Thanks
You just got the dateFormatter the wrong way around.
When you do
[dtFormatter setTimeZone:[NSTimeZone systemTimeZone]];
you're telling it that the input Date is in terms of your time zone. Therefore, it converts it to GMT and outputs the time +4 hours. To do it the other way around you can use this:
NSDateFormatter* df_local = [[NSDateFormatter alloc] init];
[df_local setTimeZone:[NSTimeZone timeZoneWithName:#"America/New_York"]];
[df_local setDateFormat:#"yyyy.MM.dd' 'HH:mm:ss zzz"];
NSDate* dateOutput = [dtFormatter dateFromString:dateString];
NSLog(#"Parsed Date in GMT %#", dateOutput);
NSString *yourLocalDate = [df_local stringFromDate:dateOutput];
NSLog(#"in EDT %#",yourLocalDate);
This logs
2012-09-16 05:23:53.297 TestingApplication[10109:c07] Date To Parse 2012-09-16 02:32:53 +0000
2012-09-16 05:23:53.302 TestingApplication[10109:c07] Parsed Date in GMT 2012-09-16 02:32:53 +0000
2012-09-16 05:23:53.304 TestingApplication[10109:c07] in EDT 2012.09.15 22:32:53 EDT
if you want a date as a final output you can skip the secondary NSDateFormatter and just 'add' the difference between the UTC date and the local time.
formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"UTC"]];
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSDate *date = [formatter dateFromString:dateString]; // UTC date
NSDate *date2 = [date dateByAddingTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMTForDate:date]]; // local date!

Resources