Error with formatting time in objective-c - objective-c

I am trying to format the date of a blog post pulled from an RSS feed to be displayed in a table cell. I set the string "dateString" equal to the date received from the XML parser and log the results. Then, I convert the date to a new format, log it to the console, and I receive "null." Which in return gives me a time interval of 0, and displays "seconds ago" in my cell. I think there could be an error in my date format, but I checked many sources.
NSString *dateString = nil;
dateString = [datearray objectAtIndex:indexPath.row];
NSLog(#"Date Posted: %#", dateString);//Log date posted
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EEE, dd MMM yyyy HH:mm:ss ZZZ"];
NSDate *date = [dateFormat dateFromString:dateString];
NSLog(#"New Date: %#", date);//Log date posted
NSTimeInterval timeInterval = [date timeIntervalSinceNow];
NSLog(#"Time interval %f", timeInterval);
NSString *newTime = [timeIntervalFormatter stringForTimeInterval:timeInterval];
NSLog(#"New Time %#", newTime);
cell.dateLabel.text = [NSString stringWithFormat:#"%#", newTime];
Console Log:
2014-06-13 15:43:41.555 Cazenovia High School[13489:60b] Date Posted: Thu, 22 Aug 2013 13:33:44 +0000
2014-06-13 15:43:41.556 Cazenovia High School[13489:60b] New Date: (null)
2014-06-13 15:43:41.557 Cazenovia High School[13489:60b] Time interval 0.000000
2014-06-13 15:43:41.558 Cazenovia High School[13489:60b] New Time seconds ago
Edits:
Added the following lines, but still no change...
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[dateFormat setLocale:locale];

that was quite clear after running the project, because it seems there is an extra new-line character at tail of the dateString.
technically, which string you are working with is "Thu, 22 Aug 2013 13:33:44 +0000\0x0a", that is why the parser cannot work with it using that formatter.
I've modified the formatter to EEE, dd MMM yyyy HH:mm:ss ZZZ\n and it works properly now, that is how my console looks:

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.

NSDate and NSDate stringFromDate are inconsistent

I am trying to convert a mysql datetime field to another timezone. The conversion seems correct when I print the date object, however when I print the date as a string the time is incorrect. Source code and output are below.
Source:
edited - print original interval in seconds and string, add timezones
interval = [NSNumber numberWithDouble: seconds];
NSLog(#"interval in ms: %#",interval);
self.dateStamp = [[NSDate alloc] initWithTimeIntervalSince1970:seconds/1000];
if(![currentZone.name isEqualToString: timezone]){ //need to convert
NSDateFormatter *fromTZ = [[NSDateFormatter alloc]init];
[fromTZ setTimeZone:currentZone];
[fromTZ setDateFormat:#"hh:mm yyyy-MM-dd"];
NSLog(#"original date: %#",[fromTZ stringFromDate:self.dateStamp]);
NSDateFormatter *toTZ = [[NSDateFormatter alloc]init];
[toTZ setTimeZone:spotZone];
[toTZ setDateFormat:#"hh:mm yyyy-MM-dd"];
NSString *tempdate = [fromTZ stringFromDate:self.dateStamp];
NSDate *toDate = [toTZ dateFromString:tempdate];
NSLog(#"Date: %#",toDate);
NSLog(#"Date String: %#", [toTZ stringFromDate:toDate]);
}
Output:
interval in ms: 1384193573000
original date: 01:12 2013-11-11 //date in current timezone: America/Phoenix
Date: 2013-11-11 08:12:00 +0000 //date in new timezone: America/New York
Date String: 01:12 2013-11-11
NSDate has no concept of time zone, it is simply an object representing the number of seconds since January 1, 2001 GMT and represented in UTC. No matter what you try and set it to, when you straight log an NSDate its going to give you the same result. The only way to circumvent this is to use the NSDateFormatter which you've already done. Everything you've posted is the expected behavior.
Your server sends the time 1384193573000 (in milliseconds) since 1.1.1970, but not with respect to GMT as it is usually done, but with respect to a different time zone, "America/Phoenix" in your example.
Therefore you have to add a correction first, which is the difference between "America/Phoenix" and GMT:
NSTimeInterval serverTime = 1384193573000/1000.;
NSTimeZone *fromZone = [NSTimeZone timeZoneWithName:#"America/Phoenix"];
NSTimeInterval diff = [fromZone secondsFromGMTForDate:[NSDate dateWithTimeIntervalSince1970:0]];
NSDate *dateStamp = [NSDate dateWithTimeIntervalSince1970:(serverTime - diff)];
This was the crucial step. dateStamp is now a "proper" NSDate object representing
the time sent from the server.
What remains is to display the date. That is done as in the above comments and the other
answer. For example:
NSTimeZone *toZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
NSDateFormatter *toTZ = [[NSDateFormatter alloc]init];
[toTZ setTimeZone:toZone];
[toTZ setDateFormat:#"HH:mm yyyy-MM-dd"];
NSString *result = [toTZ stringFromDate:dateStamp];
// result = 20:12 2013-11-11

NSDateFormatter dateFromString with date

i have a problem with method dateFromString, here is my code
NSString* res = [NSString stringWithFormat:#"%#/%#/%#",dateInput.text,monthInput.text,yearInput.text];
NSDateFormatter* formatter = [[NSDateFormatter alloc]init];
[formatter setTimeZone:[NSTimeZone localTimeZone]];
[formatter setDateFormat:#"dd/MM/yy"];
NSDate* inpTime = [formatter dateFromString:res];
[dateResult setText:[NSString stringWithFormat:#"%#",inpTime]];
when I run, the date in "inpTime" always is "dateInput" - 1.
for example: if "dateInput" is 5, the date in "inpTime" will be 4
You need to adjust the timezone.
Change
[formatter setTimeZone:[NSTimeZone localTimeZone]];
to
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"UTC"]];
This is because you're not setting the time, so it's set by default the midnight UTC.
But when you are displaying the date with a timezone other than UTC the time is shifted accordingly.
As an example if you live in New York the 12/29/2012 00:00:00 UTC is actually the 12/28/2012 18:00:00 for you.
You Code is perfect, no error what so ever.
Try nslogging dateInput.text, monthInput.text and yearInput.text...might be from here you are getting invalid data.

NSDateFormatter return incorrect date from string

I have a method,
+ (NSDate *) convertToDateFrom:(NSString *) dateString
{
if (dateString == nil || [dateString isEqual:#""]) return nil; //return nil if dateString is empty
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"EEEE, dd MMMM yyyy HH:mm"];
NSDate *date = [df dateFromString:dateString];
return date;
}
When I pass,
#"Monday, 21 November 2011 17:01" //Passed string
It returns a wrong date,
2011-11-21 23:14:00 +0000 // Output
I am not sure whether I am using those flags correctly or NSDateFormatter isn't properly converting my string to date.
Am I doing something wrong?
Thanks
The +0000 at the end of the date indicates GMT. All dates are stored relative to GMT; when you convert a date to a string or vice versa using a date formatter, the offset to your time zone is included. You can use NSDateFormatter's -setTimeZone: method to set the time zone used.
In short, you're not doing anything wrong in your code. Use [df stringFromDate:date]; to see that the date is correct. (You can also use NSDate's -descriptionWithCalendarFormat:timeZone:locale:.)
try using
df stringFromDate:date
Following worked on mine,
NSLog(#"Date for locale %#: %#",
[[dateFormatter locale] localeIdentifier], [df stringFromDate:date]);
gave me output as :
Date for locale en_US: Wednesday, 26 June 2013 15:50
Try setting the time zone and locale.
[df setLocale:[NSLocale currentLocale]];
[df setTimeZone:[NSTimeZone systemTimeZone]];

NSDateFormatter will not parse string with timezone that includes colon

I'm trying to transform #"Fri, 26 Aug 2011 10:51:00 +02:00" into an NSDate:
[dateFormatter setDateFormat:#"EEE, dd MMM yyyy HH:mm:ss Z"];
NSDate *date = [dateFormatter dateFromString:dateString];
I get nil as a result; what am I doing wrong?
You can use the getObjectValue:forString:range:error: method to parse dates that have the colon in the timezone:
// test date formatting
NSString *dateString = #"2012-04-11T18:34:19+00:00";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"yyyy-MM-dd'T'HH:mm:ssZ";
NSDate *date;
NSError *error;
[formatter getObjectValue:&date forString:dateString range:nil error:&error];
The colon in the timezone (+02:00) is the issue. According to the Unicode Standard #35, 1..3 capital Z pattern denotes a RFC 822 time zone. RFC 822 time zones represent the offset from GMT (or UTC) and have the following format:
zone = "UT" / "GMT" ; Universal Time
...
...
/ ( ("+" / "-") 4DIGIT ) ; Local differential
; hours+min. (HHMM)
As you can see, there is no colon between hours and minutes of the time zone. Therefore, the time zone should be +0200.
The most proper solution would be to generate a unicode compliant date string in the first place, but if you are stuck with this format, you may need to preprocess the date string before you pass it to NSDateFormatter.
For example, a quick fix would be using stringByReplacingOccurrencesOfString to get rid of the colon in the time zone:
// dateString --> Fri, 26 Aug 2011 10:51:00 +02:00
dateString = [dateString stringByReplacingOccurrencesOfString:#":"
withString:#""
options:0
range:NSMakeRange(25, [dateString length] - 25)];
// dateString --> Fri, 26 Aug 2011 10:51:00 +0200
[dateFormatter setDateFormat:#"EEE, dd MMM yyyy HH:mm:ss Z"];
NSDate *date = [dateFormatter dateFromString:dateString];
// date --> 2011-08-26 08:51:00 +0000
No string manipulation required. Change your format string to:
[dateFormatter setDateFormat:#"EEE, dd MMM yyyy HH:mm:ss Z:00"];
I tested it and it parses the date you give just fine. When I print the date using [NSDate description], I get 2011-08-26 08:51:00 +0000, which is equivalent to the date given in the string.
Yeah, this is a common problem. A number of servers produce the date with the colon in the timezone, and NSDateFormatter can't (to my knowledge) be convinced to accept it. The solution is to cut out the colon somehow, as suggested.