I have this problem with displaying a date for the user based on the user's locale. But I want the date to be composed of digits only. For example: 2011/12/04 19:20:11. The problem is that I've tried to use NSDateFormatter and depending on the locale it can display an only numerical date or one with words like this: Jan 1 2011, 19:20:11. I want the locale to only affect the order of the month, day and year. Can this be done?
To be honest I thought this was a poor question until I read the last line. "I want the locale to only affect the order of the month, day and year. Can this be done?"
A fixed date format such as [formatter setDateFormat:#"HH:mm"] will not be affected by locale changes. The best thing to do is to use a 'NSDateFormatterStyle' to do the heavy lifting for you.
Part of your problem was that you did not set the correct date formatter style. NSDateFormatterShortStyle already outputs the date format you want.
As far as the time format goes, if the user has their system set to 24hour clock then NSTimeZoneNameStyleShortGeneric should work right out of the box. But if not that can be fixed. The beauty of it is you don't have to check.
// Example Date Now
NSDate *now = [NSDate date];
// Formatter set to proper locale by default
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// Set formatter to short styles
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSTimeZoneNameStyleShortGeneric];
At this point your formatter will have already setup it's own format string "M/d/yy h:mm:ss a", this would be for the US. So at this point all we have to do is change the format slightly.
// Remove the AM/PM from the format string
formatter.dateFormat = [formatter.dateFormat stringByReplacingOccurrencesOfString:#"a" withString:#""];
// Change 12h clock to 24h clock
formatter.dateFormat = [formatter.dateFormat stringByReplacingOccurrencesOfString:#"h" withString:#"H"];
Now your date format should be "M/d/yy H:mm:ss". Which is the version you would want for the US. You can confirm with a log statement.
NSLog(#"%#",[formatter stringFromDate:now]);
Note that when you change the 'h' in the format to 'H' you don't care where it is. So if in some locale they were to have a reversed time format it would be changed, but left in it's original position.
Related
+(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"];
How do I keep the date format fix getting from UIDatePickerView, It should not affected from country(Region Format). Presently In my application if I set the region format as "China" it is displaying UIDatePickerView in local china format. I want to as it is but I want to access the date from this in my fixed standard format. It should not be affect by country whether it is Australia or China or UK. Please Suggest with example.
I do not want to change the date format in Picker View just want to change date format access from it. Here is the code that I am using:
NSDateFormatter *datef = [[NSDateFormatter alloc]init];
NSCalendar *usersCalendar =
[[NSLocale currentLocale] objectForKey:NSLocaleCalendar];
[datef setLocale:[NSLocale currentLocale]];
[datef setTimeZone:[NSTimeZone localTimeZone]];
[datef setCalendar:usersCalendar];
tempFDate = [datef dateFromString:[NSString stringWithFormat:#"%# %#",txtDate.text,txtTime.text]];
NSLog(#"%#",tempFDate);
I am continuously getting null in console. I need such a date format that can work for all the region formats. Please Suggest its urgent for me.
NSDateformatter is the best option.
See, the timezone if not specified it will use the timezone of which device is set and display the content accordingly
there are options to get the device setted timezone also to work with it
+ localTimeZone
+ defaultTimeZone
+ setDefaultTimeZone:
+ resetSystemTimeZone
+ systemTimeZone
check this class
Here you need the reponse to a certain timezone for eg GMT 0000
then
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
will do the job for you
using NSDateFormatter.
you can use NSDateFormatter to convert any date format like dd/MM/yyyy etc.
I have a strange query...
If the date/time is set automatically in my iPhone than the time is correctly displayed as seen below...
And if the date/time is set manually with a different time zone than I am actually in (I am in India and set it to London. Works fine if set to India),it shows wrong results only for two dates calculated by using the method [self.surveyModel.creationDate dateByAddingTimeInterval:60*60*24*30] and similarly for 20 days .. see image below..
I am not setting the default time zone or local time zone for the application, and I am suing the following method to show the result...
- (NSString *)stringWithFormat:(NSString *)format {
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setTimeZone:[NSTimeZone systemTimeZone]];
[outputFormatter setDateFormat:format];
NSString *timestamp_str = [outputFormatter stringFromDate:self];
[outputFormatter release];
return timestamp_str;
}
what am I doing wrong here...?
NOTE: This answer is in reply to the Comment on the Question
It seem the error is caused by regions with Daylight Savings, in this case London, England.
When the date/time is calculated automatically, the iOS DateTime library takes the DayLight Saving into account.
When dealing with the DateTime manually, which you are doing through this code [self.surveyModel.creationDate dateByAddingTimeInterval:60*60*24*30]
You are setting the DateTime without listing the DayLight option enabled. So when you take the NSTimeZone look for the DayLight savings options.
The deal is I want a NSDate representation of the date 18th of June 1978.
I have tried to init NSDate like
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
self.dateFormatter.timeStyle = NSDateFormatterNoStyle;
self.startDate = [dateFormatter dateFromString:#"19/06/78"];
NSLog(#"%#", self.startDate);
This produces the right date when the iPhone is set to Danish in the International settings.
It does not work with a iPhone set to i.e. english/american settings.
Notice the extra day (19) because denmark is in GMT +1 and i think the NSDate defaults to time 23:00:00. That indicates that something i not working as intended.
I want the above date (18/06/1978) represented a an NSDate object regardless of the timezone, locale and International settings on the device.
How to achieve that?
Edit:
So Ole Begemann's answer seemed to resolve my issue. His solution did create the correct date both on a device in USA International settings and en European international settings.
But when Apple should review the app the date created was 17th of June 1978. This makes sence since I'm setting timezone to GMT +0000. And Cupertino is like GMT -0007 or so.
So this would give a day earlier.
So to correct my question: I want the 18-06-1978 no matter what locale, timezone the device is physically or settings wise in.
What I'm trying to do is setting a start date 18. june 1978 and later in my app render the date as a string formatted like "780618" (yyMMdd) regardless of the timezone or place of the device. It allways has to be "780618" as this is a key start date for my app.
So I might be attending the problem wrong. Instead of trying to force same date everywhere I maybe should accept the timezone stuff and try to configure the NSDateFormatter to output the right date.
So basically: What I want is THE NSDate instance that formats to "780618" everywhere - in any timezone with any international device settings.
How to achieve this?
I want the above date (18/06/1978) represented a an NSDate object regardless of the timezone, locale and International settings on the device.
This makes no sense to NSDate. An NSDate always represents a single point in time, so by definition it includes a time and the time zone this time is in (or to be more exact, it stores the time in GMT; the time is only converted to another time zone for display purposes). If you just want the date, you have to make your own definition regarding the time, e.g. to store these dates with a time of midnight GMT.
When setting a date programmatically, you must always set a time zone and, if you use a date formatter, set the formatter's locale and calendar. This ensures that your code is independent of the user's/device's locale settings.
I would do it like this:
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[dateComponents setYear:1978];
[dateComponents setMonth:6];
[dateComponents setDay:18];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [calendar dateFromComponents:dateComponents];
NSLog(#"%#", date);
You can do like this:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// Set the locale to en_US_POSIX. This makes the date formatter respect
// the format string regardless of the user's locale.
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[formatter setLocale:locale];
[locale release];
// We want the date in the user's current time zone.
[formatter setTimeZone:[NSTimeZone localTimeZone]];
[formatter setDateFormat:#"dd/MM/yy"];
NSDate *date = [formatter dateFromString:#"18/06/78"];
[formatter release];
NSLog(#"%#", date);
That the date is shown like this 1978-06-17 23:00:00 +0000 is because NSDate's description returns the date in GMT. 17th of June 1978 at 23:00 is 18th of June 1978 00:00 in GMT+1.
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)