Bug when trying to parse date in Objective-C - ios

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.

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.

NSDate show wrong date with NSTimezone

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.

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!

NSDateFormatter will not work for the date before 1970?

double seconds = -62167464057.000;
NSDate *oldDate = [NSDate dateWithTimeIntervalSince1970:seconds];
MELog("oldDate = %#", oldDate);//oldDate = 0002-12-29 03:59:03 +0000
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateStyle:NSDateFormatterNoStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
NSString *formattedDateString = [dateFormatter stringFromDate:oldDate];
NSLog(#"formattedDateString = %#", formattedDateString);//formattedDateString = 3:57 AM
In the above code, the date component has the time 3:59, But when we format it to extract the time field, we are getting 3:57
My timezone is London, so it should return 3:59
Is this because of we are trying to format a date before 1970 ? Please confirm if anyone knows.
Yes, that's exactly the reason. It is because of the "beginning" of timestamp:
Unix time, the number of seconds since 00:00:00 UTC on January 1, 1970
More on wikipedia.
IN YOUR CODE YOU ARE SETTING THE TIME INTERVAL TO 1970 .IT MIGHT BE BECAUSE OF THAT.TRY NOT TO USE THAT AND SET THE MINIMUM DATE BY URSELF.

NSDateFormatter giving me time 4 hours ahead

I'm converting a string "Jun 11, 2012 9:30 PM" to an NSDate and I keep getting 4 hours ahead for some reason. The funny thing is I'm using this same string to feed a UIDatePicker in a detailed view where I have to do the same conversion, and the UIDatePicker renders the time fine. Only when I now try to NSLog it in my main and detailed view do I have problems.
This is in my views :
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM dd, yyyy h:mma"];
NSDate *dateFromString = [[[NSDate alloc] init]autorelease];
NSLog(#"DATE %#", _date);
dateFromString = [formatter dateFromString:_date];
NSLog(#"NSDATEFROMSTRING %#", dateFromString);
NSLog returns :
2012-06-11 00:02:09.136 LocalDeals[78090:207] DATE Jun 11, 2012 9:30 PM
2012-06-11 00:02:09.137 LocalDeals[78090:207] NSDATEFROMSTRING 2012-06-12 01:30:00 +0000
Even when I add:
[formatter setTimeZone:[NSTimeZone defaultTimeZone]];
I still get the same results from any time I choose. Any ideas? This is on the simulator by the way and yes my Region Format is set to United States.
When you NSLog an NSDate it will print the time as a GMT time zone
In order to see the correct data you will have to convert the NSDate to string using stringFromDate
NSDate *dateFromString = [[[NSDate alloc] init]autorelease];
NSLog(#"DATE %#", _date);
//Instead of nslog directly, use this stringFromDate:remindOn
NSString *str = [formatter stringFromDate:dateFromString];
NSLog(#"date is %#", str); //This will log the correct data
The problem you are getting is not in the NSDate but it is in Logging it
UPDATE In order to save the data to a file or database i would suggest that you save it like this
NSTimeInterval timeInterval = [dateFromString timeIntervalSince1970];
Now when you read it again from the database you would do
NSDate *data = [[NSDate alloc] initWithTimeIntervalSince1970:timeInterval]
The following code will show your time with your time zone:
NSString *_date = #"Jun 11, 2012 9:30 PM";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMMM dd, yyyy h:mma"];
[formatter2 setDateFormat:#"MMMM dd, yyyy h:mma Z"];
NSDate *dateFromString = [[NSDate alloc] init];
NSLog(#"DATE %#", _date);
dateFromString = [formatter dateFromString:_date];
NSLog(#"NSDATEFROMSTRING %#", dateFromString);
NSLog(#"NSDATEFROMSTRING %#", [formatter stringFromDate:dateFromString]);
NSLog(#"NSDATEFROMSTRING %#", [formatter2 stringFromDate:dateFromString]);
Result:
DATE Jun 11, 2012 9:30 PM
NSDATEFROMSTRING 2012-06-12 04:30:00 +0000
NSDATEFROMSTRING June 11, 2012 9:30PM
NSDATEFROMSTRING June 11, 2012 9:30PM -0700
If you Google for UTC Time now, it does give you a time that is close to the second line in the output, which confirms it is printing out the time as a UTC time.
(We are in different time zone and dateFromString is interpreting the time in the string as your local time.)

Resources