I am getting a time/duration from a .NET web service in this format: PT12H30M
How can this be handled?
When you define the format string for parsing a date you use the UTS #35 Date Format Patterns to define what the incoming data looks like. PT looks like a legitimate timezone abbreviation. You will want to fiddle with this depending on whether the minutes and hours are zero-padded or not.
NSString *dateString = #"PT12H30M";
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"ZZhh'H'mm'M'"];
NSDate date = [dateFormatter stringFromDate:dateString];
Take a look at NSDateFormatter, which can parse dates with a user-specified format using particular syntax. Parse result is a standard NSDate.
Create an instance of NSDateFormatter configured with a format string the describes the time format, and then use the -dateFromString: method to translate the time you get from the web service into a NSDate object.
Related
I have a simple question but it is driving me nuts. I am using an API, and I get a JSon object back, and one of the fields is a date. The date is formatted like this: 2013-05-17T02:00:00.000Z. I cannot seem to get the NSDateformatter correct for this date. Would anyone be willing to give me a hand?
If it is not clear, I am using objective c for an iPhone app. My goal is to get a NSDate object at the end of this. Thanks again for your help.
That's one of the ISO 8601 formats. Parsing it with NSDateFormatter can be tricky at best, which is why I wrote an NSFormatter subclass specifically for parsing and unparsing any ISO 8601 format.
You'll want to get the correct format for that string.
Then you should be able to do something like:
NSString * dateString = jsonDict[#"dateKey"];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"]
NSDate *date = [df dateFromString:dateString];
The T is in there to separate date from time and the Z specifies Zulu time. (https://stackoverflow.com/a/8405125/1074558)
+(NSDate *)DateServerFormatFromString:(NSString *)date
{
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init] ;
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_GB"];
[dateFormatter setLocale:locale];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss"];
NSDate* returnDate = [dateFormatter dateFromString:date];
return returnDate;
}
The function returns date in format "2013-05-09 08:06:04 AM +0000". But i want it in 24 hour format. The date being passed to this function is in the exact same format as given in setDateFormat method.
The device's region format is set to "United Kingdom" and time format is set to "12 hour format". This should not be changed. When time format is set to 24 hour format in the device, the function works perfectly. What is wrong with the code. I am using iPad 1 with OS 5.1.1. Setting locale identifer or even timezone didnt make a difference. Thanks in advance.
This is not necessarily an answer, just an explanation, found in the Apple docs (here):
Although in principle a format string specifies a fixed format, by
default NSDateFormatter still takes the user’s preferences (including
the locale setting) into account. You must consider the following
points when using format strings:
NSDateFormatter treats the numbers in a string you parse as if they
were in the user’s chosen calendar. For example, if the user selects
the Buddhist calendar, parsing the year 2010 yields an NSDate object
in 1467 in the Gregorian calendar. (For more about different
calendrical systems and how to use them, see Date and Time Programming
Guide.)
In iOS, the user can override the default AM/PM versus 24-hour
time setting. This may cause NSDateFormatter to rewrite the format
string you set.
The problem here is how you're getting the string. You say you got it
by printing the description of returnDate
However, according to the documentation, the -description method says this:
The representation is useful for debugging only.
There are a number of options to aquire a formated string for a date including: date formatters (see NSDateFormatter and Data Formatting Guide), and the NSDate methods descriptionWithLocale:, dateWithCalendarFormat:timeZone:, and descriptionWithCalendarFormat:timeZone:locale:
What this means is that the value returned by -description does not respect any 12- or 24-hour time settings. It's just a debug version.
If you want to express a date as a human-readable string, you must use an NSDateFormatter.
Again and again:
Did you NSLog() the date? Logging a date is always been done in a normalized standard format. If you want to log a date formatted, log the result of a formatter, not the date directly.
You want 24h format for what? Format is used to convert NSDate to NSString with correct string format. Just make reverse converting when you need it
12 hour format
[dateFormatter setDateFormat:#"dd/MM/yyyy hh:mm:ss"];
24 hour format
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss"];
According to this site:
http://iosdevelopertips.com/cocoa/date-formatter-examples.html
there is a class that handles formatting, which takes in a set of constants/enums (e.g. NSDateFormatterShortStyle) to the "setDateStyle" property/method.
Somehow the NSDateFormatter knows to retrieve the proper locale-specific date format. What I want is to be able to retrieve the default formats based on the user's choice of region format. I have a feeling it is stored in NSLocale, but that does not seem to expose anything that will retrieve the format strings.
Is there a way to extract the formats? It has to be in memory somewhere; I'm hoping the retrieval mechanism is exposed somewhere.
I've looked in several places, but the only answers I get are a lesson on how to create an NSDate from a custom format.
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateStyle:NSDateFormatterShortStyle];
NSString *dateFormat = [df dateFormat];
NSLog(#"Date format: %#", dateFormat);
[df release];
Just tested on OS X but this should also work in iOS.
I store my NSDates to a file in the international format you get when you call description on a NSDate.
However, I don't know how to go back from the string-format to an NSDate object. NSDateFormatter seems to be limited to a couple of formats not including the international one.
How should I go back from the string-format?
Jeff is right, NSCoding is probably the preferred way to serialize NSDate objects. Anyways, if your really want/need to save the date as a plain date string this might help you:
Actually, NSDateFormatter isn't limited to the predefined formats at all. You can set an arbitrary custom format via the dateFormat property. The following code should be able to parse date strings in the "international format", ie. the format NSDate's -description uses:
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ss ZZZ";
NSDate* date = [dateFormatter dateFromString:#"2001-03-24 10:45:32 +0600"];
For a full reference on the format string syntax, have a look at the Unicode standard.
However, be careful with -description - the output of these methods is usually targeted to human readers (eg. log messages) and it is not guaranteed that it won't change its output format in a new SDK version! You should rather use the same date formatter to serialize your date object:
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm:ss ZZZ";
NSString* dateString = [dateFormatter stringFromDate:[NSDate date]];
Instead of saving the description to a file, why not save the object itself? NSDate conforms to the NSCoding protocol; saving the object means you don't have to worry about translating it. See the NSCoding protocol reference for more information.
I would try to set up an NSDateFormatter to successfully parse the string by the following method:
- (NSDate *)dateFromString:(NSString *)string
Note that it could take you a while to get the NSDateFormatter set up just right to successfully parse your string.
If you're going to store program-facing data like this I would also recommend storing it in an easier-to-access format, e.g., CFAbsoluteTime. Once you have it in your program you can format it into the international format or something else human-readable.
Convert it to a format NSDate accepts and then perform the conversion back.
Alternatively, depending on which NSDate you're referring to (!) initWithString should cover international standard dates.
For PDT, I would want "-0700".
I'm getting a date in the past to determine how long ago something happened.
NSDate *then = [NSDate dateWithString:#"1976-04-01 12:34:56 -0700"]; // Note the hard-coded time zone at the end
I'll be constructing the date string elsewhere but I don't know how to access the local time zone.
I read the Apple Dates and Times Programming Topics for Cocoa as well as the NSTimeZone and NSDate Class References but it's just too hard for me to put the information together. I could really use a few lines of code just to show how it's used.
Update: While struggling with this, I was writing code using a Command Line template so I could try things quickly. I just tried my previous code on iPhone and I'm getting NSDate may not respond to '+dateWithString:' Sorry if that added to the confusion, who knew Apple would change up such a basic class.
Use NSDateFormatter to build NSDate from a string:
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
[inputFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss Z"];
NSDate *formatterDate;
formatterDate = [inputFormatter dateFromString:#"1976-04-01 12:34:56 -0700"];
NSString *dateString = [inputFormatter stringFromDate:formatterDate];
NSLog(#"date:%#", dateString);
This way you get the local time from string, for example the date specified by the string:
"1976-04-01 12:34:56 -0700"
is in time zone -0700, (I'm in time zone GMT +1000) so I get:
2009-11-17 22:13:46.480
cmdline[10593:903] date:1976-04-02
05:34:56 +1000
The time zone offset is dependent on the date in much of the world—those parts of it that use Daylight-Saving Time/Summer Time.
The only correct way is to generate the entire string from date and time-zone together. Use NSDateFormatter for this.
The best way is to probably use a simple calendar formatter
NSCalendarDate * date = [NSCalendarDate calendarDate];
[date setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"PDT"]];
NSLog([date descriptionWithCalendarFormat:#"%z"]);
which will output '-0700'
or leave out the second line if you want the current time zone of the system (not sure which you were asking for)