I want to display the following string on my time axis:
"GMT/BST"
Here's the code:
NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init];
[dateformatter setDateFormat:#"zzz"];
timeZoneString = [NSMutableString stringWithFormat:#"%# / %#",[dateformatter stringFromDate:startDate],[dateformatter stringFromDate:endDate]];
But this gives "GMT/GMT+01:00"
What is the NSDateFormatter code to turn "GMT+01:00" into "BST" ? I can't get the right formatters to do this, having tried z|zzz|Z|ZZZ|v|V see... http://waracle.net/iphone-nsdateformatter-date-formatting-table/
Turns out there is a built in array of 48 time zone abbreviations (e.g. 'BST') in iOS.
NSDictionary *tzDict = [NSTimeZone abbreviationDictionary];
There is an array of 419 time zone names in this array (e.g. 'Europe/London'):
NSArray *timeZoneNames = [NSTimeZone knownTimeZoneNames];
tzDict contains the abbreviations for daylight saving time for a subset of time zone names. So the algorithm would be to check if we are in DST, then see if tzDict has an entry, and subsitute that or if not, use
[NSTimeZone abbreviation];
Here are a few other topics on time zones in general.
Daylight saving time and time zone best practices
How can I map tz database names to city and country names?
C# british summer time (BST) timezone abbreviation
http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
GMT timezone conversion in objective c
I spent a day on this and wanted to make sure so others don't get hung up on it.
For a UK region/locale, the 'z' field pattern in DateFormatter returns the proper string for the "America/London" timezone (e.g. "GMT" or "BST"). However, if you use the US region/locale, 'z' will give you "GMT+1".
The gotcha happens when an abbreviation for the given target timezone with a given locale doesn't exist. I was using the 'v' field pattern, and with the US region, "Europe/London" was falling back to "United Kingdom Time", which blew up my text label. 'z' is better, it falls back to "GMT+1" while in DST, but still not the desired "BST".
The abbreviationDictionary doesn't consider daylight savings time. It's meant to map an abbreviation to a timezone. You'll find "BST":"Americal/London", but this only applies while observing daylight savings time as mentioned by #Nick T. During standard time, Brits are used to seeing "GMT".
Unfortunately, without recreating timezone functionality yourself, you're left with compromises. I think iOS can do better here.
Reference
Date Field Symbol Table as part of the Unicode Technical Standard
Related
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.
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.
I'm getting the current date/time using [NSDate date]. The value returned is an hour in the future. I've check my phones location & time settings and they are correct.
I can display the correct date and time as a string using the code below.
[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle]
But I need it to return the correct date/time as a date object as I use it to calculate the estimated time of arrival using -
[date dateByAddingTimeInterval:interval]
I realise my question is similar to this one already asked but none of the answers suit my needs. Thanks in advance!
init] returning date an hour in the past?
Maybe you are confusing the point in time (ie the NSDate object) and the point in time at your location (ie your local time).
If you print a NSDate (like NSLog(#"%#", [NSDate date]); which invokes [date description]) the date representation that is printed is in UTC timezone (+0000) (at least it is on my computer).
So as long as you don't live in an area that uses UTC the date printed by [date description]; is always "wrong". But wrong only means that its representation is not the same representation as the clock in your office. The date (as in point in time) is still correct.
When you use localizedStringFromDate:dateStyle:timeStyle: you are printing the date in your local timezone.
NSDate *date = [NSDate date];
NSLog(#"%#", date);
NSLog(#"%#", [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle]);
at my computer this results in:
2011-02-12 08:32:10.658 x[75647:207] Date: 2011-02-12 07:32:10 +0000
2011-02-12 08:32:10.661 x[75647:207] Date: Saturday, February 12, 2011 8:32:10 AM Central European Time
the printed strings are different, but the NSDate object is still the same. That's why you have to use NSDateFormatters when you show a date to the user. Because the same point in time looks different on different places of the world.
But there are only three places where an UTC formatted date would be one hour in the future, so if you don't live in greenland, cape verde or on the azores I might be totally wrong and there is something wrong with your NSDate objects.
Edit: Out of curiosity I read the documentation about [date description] again. And it says
A string representation of the
receiver in the international format
YYYY-MM-DD HH:MM:SS ±HHMM, where ±HHMM
represents the time zone offset in
hours and minutes from GMT (for
example, “2001-03-24 10:45:32 +0600”).
So I don't know why the date at my computer is printed in GMT timezone. It might be in another timezone at your computer.
But still, it's only the representation, the date is still the same.
I have an NSString like this #"2010-08-30T11:00:00-04:00" . How to convert this to an NSDate ? Which DateFormat should be used with it ? I tried this #"yyyy-MM-dd'T'HH:mm:ss-SSS" . But didn't worked. Please help me.
Edit
I found #"yyyy-MM-dd'T'HH:mm:ss-SSS" was working fine in OS version 3.1 . But its not getting in 4.0 .This question also pointing similar problem. Please give a solution
[yourNSDateFormatterVariable setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]];
Knowing the timezone to be GMT - 4 hours is not enough to determine if daylight saving should be applied or not. Daylight saving is determined based on the geopolitical borders. For instance is daylight saving not applied in the same months above and below equator. Additional countries close to equator do seldom use daylight saving at all.
So, you need to get the named timezone in order to be able to apply daylight saving correctly.
I have an array of NSDates which I build from strings using [NSDate dateFromString]
In the xml I parsed to get the string there was also a timezone string. As far as I can see in the manual NSDate does not in it self deal with timezones. Do I need to always store this timezone value somewhere and pair it with the belonging NSDate each time I need it?
I also need to figure out that if an event starts in London at 10:00, but I am in Denmark having my iPhone set to danish time my "event started in London" should display at 09:00 o'clock.
Again if an event starts in London at 10:00 o'clock and ends in Denmark at 12:00 o'clock, If I were to compare start time and end time using an iPhone with danish settings I would get that the duration of the event was 02:00 event though 10:00 o'clock in UK and 12:00 o'clock in Denmark is only 1 hour apart.
NSdate works really well for these things in the scope of one timezone, but introducing the timezone part just made everything complicated to me. Is there a way to abstract/hide all these calculations, as I see potential for making a lot of mistakes.
I have been through the NSDateformatter and NSDate guides from Apple, but they are really vague and sports a substantial amount of deprecated code :/
Thanks for any help given.
You should take one standard timezone like UTC/GMT format for all calculation.
According to the NSDate reference, dateWithString: takes an offset to GMT as last component; while it is not a time zone, it is sufficient to perform computation or comparison).
Looking at the NSTimeZone reference, you can use the abbreviationForDate: and the timeZoneWithAbbreviation: to get a NSTimeZone object from a NSDate instance. Once you get the time zone, you have everything you need.
I convert the present date and the date I would like to know if is close, to GMT and then returning the difference. So I changed every thing to deal with differences instead of actual times and dates. A bit like a music score transposed to a different key:)
+ (NSInteger) minutesUntilDate:(NSDate*) date withTimezoneOffset:(NSInteger) GMTOffset
{
NSDate *now = [NSDate date];
NSTimeInterval localTimeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
now = [now addTimeInterval:(localTimeZoneOffset * -1)];
date = [date addTimeInterval:(GMTOffset * 60 * 60) * −1];
return ((NSInteger)[now timeIntervalSinceDate:date] / 60 ) * -1;
}
As soon as you have allocated an NSDate, these do not have timezone information any longer. NSDate is "timezone-less" and is always in GMT. You should make sure that NSDate understand your format correctly when allocating it.
Once you have an NSDate you can make normal calculations and ignore the timezones.
You only need to take care of timezones when reading strings into NSDates and when printing them out.