iOS NSDateFormatter Timezone - objective-c

I have some code that takes a string, turns it into a date, reformats it then spits it out as another string:
[formatter setDateFormat:#"YYYY'-'MM'-'DD','HH:mm:ss','ZZZ"];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"America/New_York"]];
NSDate *date = [formatter dateFromString:combinedString];
[formatter setDateStyle:NSDateFormatterLongStyle];
NSString *finishedString = [formatter stringFromDate:date];
Basically, it works fine except for the timezones. All of the input strings are in timezone -0400, and I want the reformatted string to be in that timezone also, but the reformatted string keeps being converted forward 4 hours, even after I added the setTimeZone: line. Basically, I don't want to change the time at all, I just want to reformat it, and I can't understand what I am doing wrong?

It depends on format specified on the source of your dates. Most of the times I deal with dates in Unix/POSIX format. Then I use the following two lines of code:
[formatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
[formatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"] autorelease]];
Anyway, I recommend you to check the following Q&A from Apple Developers site:
http://developer.apple.com/library/ios/#qa/qa1480/_index.html

In Swift:
// Formatter configuration
let formatter: NSDateFormatter = NSDateFormatter()
let posix: NSLocale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.locale = posix
formatter.dateFormat = "d.M.y"
formatter.timeZone = NSTimeZone(name: "UTC")!
// String to date
let dateString: String = "1.1.2013"
let defaultDate: NSDate = formatter.dateFromString(dateString)!
println("defaultDate: \(defaultDate)")
self.dateOfBirthUIDatePicker.date = defaultDate

Related

Date with month name date, year in objective-c

I have a date string formatted as "September 10, 2013". How can I convert this representation into a format such as "yyyy/mm/dd".
NSString *strDate = #"September 10, 2013";
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df dateFromString:strDate];
NSDate *date = [df dateFromString:strDate];
[df setDateFormat:#"yyyy/mm/dd"];
NSString* temp = [[NSString alloc] init];
temp = [df stringFromDate:date];
NSLog(#"date i required %#", temp);
temp object is null here.
Thanks in advance.
Let's rework your original code, and discuss it as well:
NSString *strDate = #"September 10, 2013";
NSDateFormatter *df = [[NSDateFormatter alloc] init];
For the input you're attempting to parse, you've got to provide a format string for your date formatter. If you don't, the date formatter is going to use defaults that are determined by the settings in your Date & Time control panel. Not only do these settings vary from locale to locale, they're subject to whatever changes the user may have effected. Another way of putting it is that they might not match the format of the date string you're attempting to convert.
You also don't want to rely on predefined styles such as NSDateFormatterShortStyle, NSDateFormatterMediumStyle or NSDateFormatterLongStyle. They're meant for date display (if you're willing to accept the Date & Time control panel settings), not for parsing.
There's a document you should consult, which is Unicode Technical Standard #35. Look in the table labeled "Date Field Symbol Table." Based on the information presented there (and your input), you'd set up your date converter to parse with a format string like this one:
[df setDateFormat:#"MMMM dd, yyyy"];
Now you can use your date formatter to parse your date string, and it'll work:
NSDate *date = [df dateFromString:strDate];
From this point onward, you're looking pretty good (though I've removed a superfluous line or two throughout all of this):
[df setDateFormat:#"yyyy/MM/dd"];
NSString *temp = [df stringFromDate:date];
NSLog(#"date i required %#", temp);
Best wishes to you in your endeavors.
You can use the NSDateFormatterclass -- look at the stringFromDate and dateFromString methods.
UPDATE: you have a couple of problems -- first, you need to tell the formatter what the initial format should be. Second, you have a format problem with the second format string -- 'm' is minutes, 'M' is months. You should review the documentation here. Here is an example:
NSString *strDate = #"September 10, 2013";
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateStyle:NSDateFormatterLongStyle];
[df dateFromString:strDate];
NSDate *dat = [df dateFromString:strDate];
[df setDateFormat:#"yyyy/MM/dd"];
NSString* t = [df stringFromDate:dat];
NSLog(#"date i required %#", t);

Convert ISO 8601 to NSDate

I have a timestamp coming from server that looks like this:
2013-04-18T08:49:58.157+0000
I've tried removing the colons, I've tried all of these:
Converting an ISO 8601 timestamp into an NSDate: How does one deal with the UTC time offset?
Why NSDateFormatter can not parse date from ISO 8601 format
Here is where I am at:
+ (NSDate *)dateUsingStringFromAPI:(NSString *)dateString {
NSDateFormatter *dateFormatter;
dateFormatter = [[NSDateFormatter alloc] init];
//#"yyyy-MM-dd'T'HH:mm:ss'Z'" - doesn't work
//#"yyyy-MM-dd'T'HH:mm:ssZZZ" - doesn't work
//#"yyyy-MM-dd'T'HH:mm:sss" - doesn't work
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
// NSDateFormatter does not like ISO 8601 so strip the milliseconds and timezone
dateString = [dateString substringWithRange:NSMakeRange(0, [dateString length]-5)];
return [dateFormatter dateFromString:dateString];
}
One of my biggest questions is, is the date format I have above really ISO 8601? All the examples I have seen from people the formats of each are slightly different. Some have ...157-0000, others don't have anything at the end.
This works for me:
NSString *dateString = #"2013-04-18T08:49:58.157+0000";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
// Always use this locale when parsing fixed format date strings
NSLocale *posix = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[formatter setLocale:posix];
NSDate *date = [formatter dateFromString:dateString];
NSLog(#"date = %#", date);
There is New API from Apple! NSISO8601DateFormatter
NSString *dateSTR = #"2005-06-27T21:00:00Z";
NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];
NSDate *date = [formatter dateFromString:dateSTR];
NSLog(#"%#", date);
I also have the native API, which is way cleaner... This is the implementation I got in my DateTimeManager class:
+ (NSDate *)getDateFromISO8601:(NSString *)strDate{
NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];
NSDate *date = [formatter dateFromString: strDate];
return date;
}
Just copy and paste the method, it would do the trick. Enjoy it!
The perfect and best solution that worked for me is:
let isoFormatter = ISO8601DateFormatter();
isoFormatter.formatOptions = [ISO8601DateFormatter.Options.withColonSeparatorInTime,
ISO8601DateFormatter.Options.withFractionalSeconds,
ISO8601DateFormatter.Options.withFullDate,
ISO8601DateFormatter.Options.withFullTime,
ISO8601DateFormatter.Options.withTimeZone]
let date = isoFormatter.date(from: dateStr);
For further more detail, you can refer to apple's official documentation: https://developer.apple.com/documentation/foundation/nsiso8601dateformatter

NSDateFormatter: Converting "5/13/2012 6:05am" (US, EDT) to "13/05/2012 12:05" (IT, GMT+1)

I am retrieving a time value from a server. The format is:
"5/13/2012 6:05am"
It is not specified in the string but I know it is "EDT".
I need to:
1) Get rid of the am/pm thing.
2) Convert it from EDT (or other timezone) to the local GMT+/-x time.
For my timeZone (Italy, GMT+1) it should become:
"13/05/2012 12:05"
How can I do this with NSDateFormatter?
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale: [NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
[dateFormatter setDateFormat:#"dd-MM-yyyy HH:mm"];
...?
Thanks
Nicola
First of all, you set your NSDateFormatters dateFormat to the source format. In your case:
[dateFormatter setDateFormat:#"M/d/yyyy h:mma"];
NSDate *myDate = [dateFormatter dateFromString:#"5/13/2012 6:05am"];
This creates a new instance of NSDate. Now you set the formatters dateFormat to your target format:
[dateFormatter setDateFormat:#"dd/MM/yyyy hh:mm"];
NSString *myString = [dateFormatter stringFromDate:myDate];
You could also use two date formatters, one for converting you'r string into NSDate instance and one to convert it back to the corrected NSString.
For further informations and the complete list of the current format specs refer to the unicode reference and the Apple Docs

How do I convert from NSString to NSDate using NSDateFormater

I have this string: 2012-01-12T21:01:00 and this code:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd hh:mm:ss a"];
NSDate* arrivalTime=[df dateFromString:field_arrival_time];
But it returns nil. What date format should I use to parse this string?
Your string 2012-01-12T21:01:00 contains the literal T (At least I believe it's a literal, it doesn't appear to signify a timezone). You must include this in your date format.
[df setDateFormat:#"yyyy-MM-dd'T'hh:mm:ss"];
Note the lack of the a in the date format, using it will require your input string to use AM or PM preceded by a white space. For more information on special characters with NSDateFormatter take a look at the Date Formatting Guide paying extra attention to the Fixed Formats.
Edit: Your input string does not specify a timezone, it will probably be interpreted as UTC and be localized to the timezone of your machine when you output it through NSLog().
I have tried a lot on your string but never get result. only nil shows on console. but when i remove character "T" from your string it gives perfect result.
[f setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [f dateFromString:#"2012-01-12 21:01:00"];
NSLog(#"date %#", date);
NSDateFormatter *f2 = [[NSDateFormatter alloc] init];
[f2 setDateFormat:#"dd-MM-yyyy"];
NSString *s = [f2 stringFromDate:date];
NSLog(#"S %#", s);
/// OutPut : S 12-01-2012

NSDateFormatter with 24 hour times

I have a countdown timer which countsdown from the current date/time to a specific future date/time. It is working great except for one problem. I input the future date using NSDateFormatter and dateFromString. It doesn't seem to be able to accept any time (hour) over 12 though indicating it is not support 24 hour clock. Is there a way to enable 24 hour clock support or a workaround? Here is some of my code:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSDate *myDate = [df dateFromString:#"2010-03-14 15:00:00"];
NSDateFormatter follows the Unicode standard for date and time patterns. Use 'H' for the hour on a 24-hour clock:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *myDate = [df dateFromString:#"2010-03-14 15:00:00"];
I had the same problem and using HH worked only on some devices, like Roger also verified. In the end this was the solution that worked for me, I hope it works for others. Finding this answer was difficult, there are no forums with it, it was literally trial and error following the apple documentation.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[dateFormatter setLocale:enUSPOSIXLocale];
NSString *dateFormat = #"dd/MM/yyyy HH:mm"; //MM for month, mm for minutes
[dateFormatter setDateFormat:dateFormat];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
date = [dateFormatter dateFromString:string];
My solution on Swift:
let formatter = NSDateFormatter()
var defIdentifer = formatter.locale.localeIdentifier
if !defIdentifer.hasSuffix("_POSIX") {
defIdentifer = defIdentifer+"_POSIX"
let locale = NSLocale(localeIdentifier: defIdentifer)
formatter.locale = locale
}
formatter.dateFormat = "HH:mm"
I had a similar problem recently, instead of HH, NSDateFormatter ignored hh, a(AM/PM Symbol) and G (cyclic era name) in my app.
And I was surprised to find that if I go to localization setting of my device and make some random choice, all the freaks are gone and the error cannot be produced again. Very weird.
Then I tested on simulator to do some study on it. There is my solution:
After you created the NSDateFormatter, explicitly set the locale property even you are using current locale, more importantly, DON'T use [NSLocale currentLocale], this one is bugged and can be somehow "overriden" by user setting, use systemLocale or explicitly create an NSLocale instance using a locale identifer.
Taken from the Apple Technical Q&A on NSDateFormatters
Q: I'm using NSDateFormatter to parse an Internet-style date, but this fails for some users in some regions. I've set a specific date format string; shouldn't that force NSDateFormatter to work independently of the user's region settings?
A: No. While setting a date format string will appear to work for most users, it's not the right solution to this problem. There are many places where format strings behave in unexpected ways.
This is how I have done mine in Swift:
private let dateFormatter: NSDateFormatter = {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.timeZone = NSTimeZone.init(forSecondsFromGMT: 0)
return dateFormatter
}()
Objective C version of getting NSDate from 24-hour string when user has set 12 hour format on their iPhone without changing locale and setting timezone:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSString *localeId = dateFormatter.locale.localeIdentifier;
if (! [localeId hasSuffix:#"_POSIX"]) {
localeId = [localeId stringByAppendingString:#"_POSIX"];
dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:localeId];
}
dateFormatter.dateFormat = #"yyyy-MM-dd'T'HH.mm.ss";
NSDate *date = [dateFormatter dateFromString:dateText];