I noticed a nifty setting in the xcode simulator while running that I can change the current location and hence simulate location based tests
However, when I try to get the date using NSDateFormatter, the local date is still in PST. I am in the Pacific Time Zone
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle]; // Jan 1, 2010
[dateFormatter setTimeStyle:NSDateFormatterShortStyle]; // 1:43 PM
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:usLocale];
[usLocale release];
NSDate *testDate = [NSDate date];
NSLog(#"Local date: %#", [dateFormatter stringFromDate:testDate]);
According to the docs, stringFromDate should use the receivers current setting, which should use the timeZone of the Tokyo, Japan.
Is this expected?
Chech the - timezone-attribute of the NSDateFormatter - I think this is controlled by the device itself (or your computer in this case), not the location. There is a setting in the settings-app however that lets you set the time by location, I'm not sure if that would change anything, but try activating that.
And a general tips: always test it on a device as well - I think the "Simulate Location"-setting works on the phone as well.
Edit: Just saw an answer that could be relevant, try calling [NSTimeZone resetTimeZone]; after setting a new location. That should trigger a reset and hopefully display the correct timezone. Ref: https://stackoverflow.com/a/5987409/267892
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.
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.
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.
I'm having a bit of a problem with NSDateFormatter failing on one user's device (returning nil when parsing a string) and working perfectly when I run it locally (either in the simulator or on my device).
I'm trying to rule out what could be causing a difference in this behaviour. My first thought was the locale but I've tried setting it explicitly to ensure the same locale is always used but it makes no difference.
Here is the code:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ssZ"];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_GB"];
[dateFormatter setLocale:locale];
[locale release];
NSDate *theDate = [dateFormatter dateFromString:dateString];
NSLog(#"PARSING DATE %# AS %#", dateString, theDate);
On the failing device, I get:
PARSING DATE 2010-11-28T20:30:49-0000 AS (null)
But locally I get:
PARSING DATE 2010-11-28T20:30:49-0000 AS 2010-11-28 20:30:49 +0000
This is driving me crazy, am I missing something else?
I am running 4.2 locally (simulator) and on my device (an iPhone 4). The failing device is a 3GS running 4.2.1.
Any ideas would be much appreciated!
I'm pleased to say that I eventually got to the bottom of this issue and I must pass on my thanks to #bendodson on Twitter for helping me out with this. aBitObvious also hit on the issue in his comment above; I'd have up-voted him if I could.
There was one difference between the user's device and mine, and that was that his device was set to use the 12 hour clock and mine was not. This single thing meant that the NSDateFormatter was unable to parse the time in the above examples and returned nil.
By far the biggest issue for me with this problem was being unable to reproduce the problem locally!
So, to be clear, to solve this issue; that is, if you are parsing date/time strings that are in a known, fixed format (often coming from some API as this was in my case), you should set the correct locale for the date formatter, which will often be en_US_POSIX.
...
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[dateFormatter setLocale:locale];
[locale release];
For more information on this, read Apple QA1480.
I am having a NSString object which I am converting to NSDate with help of NSDateFormatter. Now code works fine here with all the OS but it is creating different Output at client's add (USA region).
Here is the code that I am using.
NSDateFormatter *formate = [[[NSDateFormatter alloc] init] autorelease];
[formate setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSString *strConcat = #"2010-09-24 17:30:00";
NSDate *date = [formate dateFromString:strConcat];
NSLog(#"Output :%#",date);
Output at my end -------2010-09-24 17:30:00 - 0700
Output at Client end ----2010-09-25 00:30:00 GMT
Can anyone please suggest where's the problem?
Thanks
Pratik Goswami
The only output difference I notice is the time is different. If you do not explicitly set the timeZone property of the formatter it will use the system's local timezone. If you expect the times to the be the exact same from you and your client:
[formate setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
That would insure the output is always GMT.
You need to manually set the locale for the NSDateFormatter, so that all your users see the same formatted string. Otherwise, the formatter will use whatever locale is set for the device.
Actually, it's working correctly. The two dates are equivalent, just that one is in the US/Mountain time zone and the other is in the Greenwich time zone. (5:30pm + 7 hours = 12:30 am)
What's the problem here?
In iOS2.x and 3.x the description/datefromstring function returns:
2010-09-24 17:30:00 - 0700
in iOS 4.x it returns this:
2010-09-25 00:30:00 GMT
You could submit a bug to apple.