NSDate and different timezones? - iphone

Alright. Our application sends an NSString made out of the current user's username and todays date formatted in yyyyMMddHH. Our server, that is located in sweden, makes the exact same String and compares the two when it gets the call.
Now. We have realized, that if one of our users goes abroad, the timezone will change, resulting in complications.
if the iPhone user were to be in lets say, Seoul, South-korea. His NSString that is sent would be something like:
2011061718
Meanwhile, when our server gets the call, it will recreate its own datestring in this format because it's located in sweden.
2011061711
And therefore deny the user access to the functions on the server side.
To summarize:
How do i programmatically set a default static timezone in my application?
Atm we do this:
NSDate *aDate = [aDateFormatter stringFromDate:[NSDate date]];
And somehow we need the timezone and compare the difference between the user's actual timezone and change it to a swedish-timezone.
Any ideas?
EDIT: Ok. This application is only meant to be released in sweden. And we are using a combination of the user's username and the current date in the format of yyyyMMddHH to make a secure key, the key is meant to update itself whenever a new hour starts. The server, which is located in sweden in the timezone of GMT+1 makes a verification that the user is on an actual device using the application and not someone who has made a client of his own making soap-calls to our service.
Therefore, if one of our users goes outside the timezone, it will reject the user since the strings wont match.
This is why we want to set the default timezone for that function GMT+1 at all times. And this is what we're really looking for.
Thanks. Again.

If you need to make the client format the date, this is how to do it:
NSDate *now = [NSDate date];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"Europe/Stockholm"]; // Sets the right time.
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]; // Forces the date formatter to accept any format string.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setCalendar:gregorianCalendar];
[formatter setTimeZone:timeZone];
[formatter setDateFormat:#"yyyyMMddHH"];
[formatter setLocale:locale];
NSString *dateString = [formatter stringFromDate:now];
NSLog(#"Date: %#", dateString);
[locale release];
[gregorianCalendar release];
[formatter release];
The date formatter will do all the work for you, you just need to configure it.
By setting the gregorian calendar, you're using the same calendar as in Sweden.
By setting the timezone, you'll get the time as it would be in Sweden.
By setting the locale to "en_US_POSIX" you make the formatter use the exact format you specify, and not append any AM/PM stuff.

Don't mess about with that. Send complete date time as a string and let the server figure out the times.
NSString *dtString = [[NSDate date] description];
This will create a string with the format
YYYY-MM-DD HH:MM:SS ±HHMM

Use -[NSDateFormatter setTimeZone:]. NSDate has nothing to do with it as it does not care about time zones.
Btw, your code will also fail if the user uses a different calendar.

Also a heads up, if you turn the AM/PM function on the dateformatter will pring out 'AM/PM' even if you dont place it in the format string.
To fix this also add an NSLocale to the DateFormatter.

Related

Keep Date format to be fix IPhone SDK

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.

Confusion regarding [NSDate date]

[NSDate date] returns GMT on simulator... what time does it return on the device... ? And also how can I get the simulator time programmatically?
It returns the current date and time. NSDate is timezone-independent. The -description of NSDate may be in GMT, but it's not guarenteed.
The representation is not guaranteed to remain constant across different releases of the operating system. To format a date, you should use a date formatter object instead.
If you want to display or parse a date in a different timezone, use NSDateFormatter (and modify its timezone/locale property) or use -descriptionWithLocale:.
NSLocale* currentLocale = [NSLocale currentLocale]
NSLog(#"current locale = %#", [currentLocale localeIdentifier]);
NSLog(#"date = %#", [[NSDate date] descriptionWithLocale:currentLocale];
NSDate is timezone-independent. When you get the description with description it displays a timezone but that's entirely "informational", and, to my knowledge there's no way to set or access that timezone info (other than description). The value stored in the NSDate object is (supposed to be) GMT/UTC (though of course it can't tell if you're feeding it the wrong time).
To get the simulator's understanding of the current time and date use [NSDate date]. Format it (if need be) with NSDateFormatter.

Struggling with NSDate, formats and timezones

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.

Does NSTimeZone in iPhone adjust automatically for DST

I have a fairly simple question. I have a set of dates in UTC. I want to represent these to the user in the correct local time adjusted (or not, if DST is not currently in effect) for DST.
So, if I do something such as the following, will timeStamp be set correctly to the local time in New York taking DST into account when in effect
NSDate *date = initialise with a UTC time
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
[formatter setTimeZone:timeZone];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *timeStamp = [formatter stringFromDate:date];
Or so I need to do something else? Do I check NSTimeZone.isDaylightSavingTime/NSTimeZone.daylightSavingTimeOffset and adjust my date accordingly or anything like that?
Thanks in advance?
Twibbles.
Yes, NSDateFormatter will automatically adjust for DST if you create the timeZone with [NSTimeZone timeZoneWithName]. NSTimeZone knows the DST rules for each time zone and can look into the future and the past and will do the right thing for the NSDate passed to stringForDate. However, if you create the NSTimeZone with [NSTimeZone timeZoneForSecondsFromGMT] DST adjustments are not made. It should also be noted that DST rules are subject to change, which means NSTimeZone is not guaranteed to always do the right thing for all time zones.
You do not need to use NSTimeZone.isDaylightSavingTime or NSTimeZone.daylightSavingTimeOffset to format an NSDate as DST correct local time. Both of those methods operate on the current time. If you want to know if an NSDate falls within DST in a timezone you can use the NSTimeZone.isDaylightSavingTimeForDate method and if you want to know what the DST offset is for an NSDate you can use the NSTimeZone.daylightSavingTimeOffsetForDate method.

In Cocoa, how do I use NSTimeZone to get the system time zone offset as a string?

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)