NSDateFormatter wrong date - ios

As simple as
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd/MM/yyyy"];
NSLog(#"Current date in event %# %#",currentDate,[df stringFromDate:currentDate]);
But in the log
Current date in event 2013-10-01 22:00:00 +0000 02/10/2013
Why?

When you log an NSDate it always prints in UTC time. When you use stringFromDate: you get a date in local time unless you change the timezone of the date formatter.
In this case you are in a timezone two hours ahead of UTC (assuming you are in Italy).
Since the NSDate object is October 1, 2013 at 22:00 UTC, this is the same as midnight of October 2, 2013 at UTC+2. This is why you see the string showing October 2.
Here's another way to look at it. You are not seeing a 1 day difference. You are actually seeing a 2 hour difference due to your timezone. From midnight to 0200 hours your time, you will see what appears to be a 1 day difference.

Related

How to get the correct year from NSDate in all circumstances?

I know about NSDateComponents, but the thing is that some sort of week-based mechanism will mess up the result when the date is at the head or at the foot of a year.
For example:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit calendarUnit = NSYearCalendarUnit;
NSDateComponents *dateComponents = [calendar components:calendarUnit fromDate:self.date];
(lldb) po self.date
2015-12-31 16:00:00 +0000
(lldb) po dateComponents
<NSDateComponents: 0x12f4c83f0>
Calendar Year: 2016
Changing minimumDaysInFirstWeek doesn't make much difference either, and NSDateFormatter doesn't seem to be a better way.
As #Larme indicated in his comment, your local timezone is affecting your result;
You have specified 4 pm on the 31 Dec 2015 at UTC. This is midnight on the 1st of January 2016 in your local timezone (UTC+8).
You can use the NSCalendar method componentsInTimeZone to get the year in a specific time zone:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSTimeZone *tz=[NSTimeZone timeZoneForSecondsFromGMT:0];
NSDateComponents *dateComponents = [calendar componentsInTimeZone:tz fromDate:self.date];
int year=dateComponents.year; // This will be 2015
Your code is perfectly fine. The po command displays the time description dependent on UTC while NSCalendar / NSDateComponents considers the current time zone.
2015-12-31 16:00:00 +0000
and
2016-01-01 00:00:00 +0800
are both the same moment in time.
If you have to deal always with UTC based dates set the time zone of the NSCalendar instance to UTC.
The "year" component will always return the correct year - based on the calendar that is being used! NSDate is logged in UTC, but the year is calculated using your local timezone. The date you gave was in 2015 in London where the use GMT (close to UTC), but in 2016 in other areas of the world. For example in Australia, where the New Year fireworks have long gone off at that time.
When you were looking at calendar weeks, that's a totally different and completely unrelated subject. 31st of December can be in the last week of one year, or the first week of the next week. But that's not returned by "year". It's returned by "yearForWeekOfYear".

Date conversion from string to NSDate in ios

I have searched over internet for a long time to get this but I can't find the solution. I have received a date string from web services as "22 May 2014", I have to convert into NSDate format for check it with current date. And I have to find out the date from web service is in future or in past time.
The actual problem is that when I convert this using
NSDate *date;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd MMMM YYYY"];
date = [dateFormatter dateFromString:dateString];
But I get an entirely Different Date, Sample Input dateString:22 June 2014 and Output I get is 2013-12-21 18:30:00+0000
Please suggest any solutions.
Thanks in advance. :)
You're using YYYY, which doesn't mean what you think it means. From the TR35-31 documentation, Y is the symbol for "year in week-of-year calendars".
You want dd MMMM yyyy instead as your format string. Mixing week-of-year-based fields and regular day/month/year fields is a recipe for odd problems.
Additionally, you may well want to set the time zone in your formatter - if you're just parsing a date, then you should consider using UTC, and make sure that all your calculations and formatting/parsing use UTC.
(I suspect the issue here is that week-of-year hasn't been set, so is assumed to be 1... and the week-year 2014 started on December 30th. Then the day-of-month is set to 22 by the dd part, and then your time zone offset of UTC+05:30 is taken into account.)

NSDate dateFromString 2 months wrong?

I have the following code:
NSDateFormatter *dateFormater = [[NSDateFormatter alloc] init];
[dateFormater setDateFormat:#"yyyy-MM-DD HH:mm:ss"];
[dateFormater setLocale:[NSLocale currentLocale]];
[dateFormater setTimeZone:[NSTimeZone systemTimeZone]];
NSDate *localDate = [dateFormater dateFromString:localUpdate];
NSDate *serverDate = [dateFormater dateFromString:serverUpdate];
The input strings for localUpdate and serverUpdate are:
2014-01-31 23:42:17
2014-02-01 00:09:37
When converting those from NSString to NSDate, the second one is 2 months behind?
2014-01-31 22:42:17 +0000
2013-12-31 23:09:37 +0000
Can anyone explain this?
check this line:
[dateFormater setDateFormat:#"yyyy-MM-DD HH:mm:ss"];
the correct date format is #"yyyy-MM-dd HH:mm:ss" with "dd" not "DD"
I had the same problem once... and if the date format it's incorrect, when you use the dateFormatter, it will subtract or add one month to the date.
Your date format string "yyyy-MM-DD HH:mm:ss" is not quite right.
You're telling NSDateFormatter to parse the 01 in your second example as the day of the year (DD) instead of the day of the month (dd), which you want instead.
yyyy-MM-DD HH:mm:ss
2014-02-01 00:09:37
^^~~~~~~~~~~~ these digits are being parsed as day of year rather
than as day of month
This is an easy mistake, and one that is confusingly hidden by your first example, in which the day of month and the day of year are the same.
See the Unicode reference for the date formats used by iOS 6 and up. (For older versions, choose the right link in Apple's documentation.)
Academic tangent: why NSDateFormatter interprets the second date as being on the last day of 2013 (rather than 1st day of 2014, as specified) is probably a bug caused by specifying a month and a day of year (which are mutually exclusive), a bug in the parser (interpreting the -01th day of the year), or a timezone or daylight savings detail (if the rules changed on midnight in the local timezone.)

NSDateFormatter not recognizing timezone

I have this date:
2013-07-15T06:07:53-04:00
I use NSDateFormatter to convert this to NSDate:
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
This works but it doesn't recognize the timezone. It returns:
2013-07-15 10:07:53 +0000
What am i doing wrong?
Thanks
The log output is correct. NSLogging an NSDate will always show that date/time in UTC (see how your output has +0000 instead of -04:00). NSDate objects represent a specific moment in time regardless of calendar and timezones. You use this "moment in time" in conjunction with a formatter (with a timezone set) in order to format that "moment in time" into a locale-specific time.
If you want to see log the output with your own timezone:
// pick a different timezone if necessary
[formatter setTimeZone:[NSTimeZone localTimeZone]];
NSLog(#"%#", [formatter stringFromDate:momentInTime];
isn't the "-04:00" at the end of the string telling NSDateFormatter that this date is GMT-4 and thus, it's just converting it to GMT ?
If not, please provide the full initialization of your NSDateFormatter.
Try this instead:
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ssZZZ"];
more info here
iPhone NSDateFormatter Timezone Conversion
5 ZZZZZ - heres a category I wrote with some sample of GMT to BST
https://github.com/clearbrian/NSDateFormatter_ISO_8601

Remove time from date

I'm having a problem with NSDate instance.
For the date I'm receiving 2012-08-16 00:00:00 +0000.
But I need to remove from the 00:00:00 +0000.
Is there any way to do that?
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init]autorelease];
[formatter setDateFormat:#"yyyy-MM-dd"];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSDate *eventDate = [formatter dateFromString:currentDate]; // current Tile
NSLog(#"date %#",eventDate);
Use
NSLog(#"date %#",[formatter stringFromDate:eventDate]);
A NSDate is just a single point in time. It does not know how it's value should be formatted, that's what NSDateFormatter is for.
NSLog(#"date %#",eventDate); prints the default string representation of the date.
A date formatter converts strings into dates and dates into strings. An NSDate represents an point in time, regardless how you created it. In your code you seem to be thinking that the NSDate will "remember" that the formatter it came from didn't specify a time of day; it won't. When you call dateFromString: it will simply pick 00:00:00 (midnight) as the time.
If you need to work with calendar dates regardless of the time, you can either:
Use NSDate objects and ignore the time component. You will need to be wary of time zones, since midnight on August 15th in one time zone can be 11pm on August 14th in another.
Use a different data structure to store year, month, and day. NSDateComponents is a good candidate, or you could create your own.

Resources