My country is located in GMT+0. We are +1 hour now, because we are in daylight saving.
When I do
[NSDate date];
it was supposed to return the current date and time, but when I do that, I receive the GMT time not considering the daylight saving.
This is what the docs say about the date command
Creates and returns a new date set to the current date and time.
Why Apple does that to us? Why everything is so complex? Is this a bug? Is there a way to get the current real time the device is on? the same time that is displayed on the device's clock?
My app depends on dates and times and having a wrong date for an user located in a different timezone around the world that is on summertime or wintertime will be a disaster.
Thanks.
EDIT
After several answers, I have tried this code:
NSDate *wrongToday = [NSDate date];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *currentTime = [dateFormatter wrongToday];
NSDate *today = [dateFormatter dateFromString:currentTime];
guess what, today = wrongToday...
in other words, no change, I continue to have the wrong date without daylight saving.
what is more amazing is that currentTime shows in NSString the date with daylight saving...
any clues? thanks again.
albertamg, MRAB and Joe Osborn are all correct. They're all trying to explain to you that NSDate is a "number", "an absolute moment in time".
This value is INDEPENDENT of whether you're in London, in Los Angeles or in Singapore. It's independent of whether your county respects daylight savings time.
To INTERPRET NSDate in terms of something recognizable (like "Th July 28, 4:28pm"), you need an NSDateFormatter. You also need to make sure your locale is defined correctly: including timezone, whether daylight savings is honored, and various time/date formatting conventions.
'Hope that helps ..
Hard coding:
BOOL isDayLightSavingTime = [sysTimezone isDaylightSavingTimeForDate:currentDate];
if (isDayLightSavingTime) {
NSTimeInterval timeInterval = [sysTimezone daylightSavingTimeOffsetForDate:currentDate];
currentDate = [currentDate dateByAddingTimeInterval:timeInterval];
}
the current date is now daylight saving time.
Hope help.
My suggestion!
NSString *dateToTest = #"16-10-2016"; // <-- daylight saving
NSDateFormatter *dateformatter = [[NSDateFormatter alloc] init];
[dateformatter setDateFormat:#"dd-MM-yyyy"];
NSDate *data = [dateformatter dateFromString:dateToTest];
NSLog(#"data before --> %#:", data);
if (data == nil && [[NSTimeZone systemTimeZone] isDaylightSavingTimeForDate:data]) {
NSTimeZone *timeZone = [[NSTimeZone alloc] initWithName:[NSTimeZone localTimeZone].name];
[dateformatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:[timeZone secondsFromGMT]]];
data = [dateformatter dateFromString:dateToTest];
NSLog(#"data after --> %#:", data);
}
There are a couple of good answers on the site already here and here and here. An NSDate is an interval since the (UTC) reference date, but you can use NSTimeZone as detailed in those answers.
Related
I have an app that displays a timetable of certain ferry trips.
If I travel to a different timezone - say 4 hours behind, a 10am ferry trip now shows up as 6am?
I know this has got to do with how dates are treated based on their timezones, but I can't work out how to change that behaviour.
At the moment here's how I am getting the date and displaying it on a UILabel:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm"];
[self.departureTime setText:[dateFormatter stringFromDate:[self.route objectForKey:#"departureTime"]]];
[self.arrivalTime setText:[dateFormatter stringFromDate:[self.route objectForKey:#"arrivalTime"]]];
[dateFormatter release];
Thanks in advance for your help.
You'll need to store the timezone that the ferry ride is taking place in and format it for that timezone.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm"];
NSDate *now = [NSDate date];
NSLog(#"now:%#", [dateFormatter stringFromDate:now]);
NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:(-8 * 3600)];
[dateFormatter setTimeZone:timeZone];
NSLog(#"adjusted for timezone: %#", [dateFormatter stringFromDate:now]);
Outputs:
2011-10-10 20:42:23.781 Craplet[2926:707] now:20:42
2011-10-10 20:42:23.782 Craplet[2926:707] adjusted for timezone: 16:42
You have seen NSDateFormatter's setTimeZone method, yes?
http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDateFormatter/setTimeZone:
(b.t.w., I'd be amazed if there was a ferry that involved crossing four time zones; sounds like a cruise ship itinerary to me)
You can also use the NSDateComponents class as described by apple's reference:
If you need to create a date that is independent of timezone, you can store the date as an NSDateComponents object—as long as you store some reference to the corresponding calendar.
In iOS, NSDateComponents objects can contain a calendar, a timezone, and a date object. You can therefore store the calendar along with the components. If you use the date method of the NSDateComponents class to access the date, make sure that the associated timezone is up-to-date.
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtTimeZones.html#//apple_ref/doc/uid/20000185-SW1
Don't confuse an NSDate value with a formatted output like NSLog. NSDate is GMT, Apple's docs:
The sole primitive method of NSDate, timeIntervalSinceReferenceDate,
provides the basis for all the other methods in the NSDate interface.
This method returns a time value relative to an absolute reference
date—the first instant of 1 January 2001, GMT.
NSTimeInterval referenceInterval = [[dateFormatter dateFromString:#"1 January 2001 GMT"] timeIntervalSinceReferenceDate];
NSLog(#"referenceInterval: %f", referenceInterval);
NSTimeInterval estInterval = [[dateFormatter dateFromString:#"1 January 2001 EST"] timeIntervalSinceReferenceDate];
NSLog(#"estInterval: %f", estInterval);
Output:
referenceInterval: 0.000000
estInterval: 18000.000000
NSDate *currentDateTime = datePicker.date;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEE,MM-dd-yyyy HH:mm:ss"];
NSString *dateInStringFormated = [dateFormatter stringFromDate:currentDateTime];
NSLog(#"%#", dateInStringFormated);
Why would this code be giving me GMT? (I am in US Mountain Time)
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
[dateFormatter setTimeStyle:NSDateFormatterLongStyle];
[dateFormatter setLocale:[NSLocale currentLocale]];
NSDate *now = [NSDate date];
NSString *storeTime = [dateFormatter stringFromDate:now];
An NSDate represents a concrete point in time, regardless of the timezone. Put another way, an NSDate does not have a timezone. Timezones are only relevant when you want to display the date to the user. So 9:30pm in Mountain Time is 3:30am (+1 day) in GMT (assuming a 6 hour time difference).
NSDate, since it does not have a timezone, must pick one when producing a human-readable version to return as its -description. To make things simple, it always returns a date formatted in the GMT time zone. If you would like the date formatted to be in a different timezone, you can set the -timezone property of an NSDateFormatter, and then convert the date into a string using the -stringFromDate: method.
Yes, turns out this was a bug in Apple's Numbers on the Mac. Numbers was not interpreting the date string, or rather it was adding the time offset. The NSDate string, after formatting, was correct all along.
Sometimes my code is returning an a.m. or p.m. but not always. Most of the time it just returns what I expect, which is something like: 20110815170852164
But other times it's returning: 20100412010241 a.m.450
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"yyyyMMddHHmmssSSS"];
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
What could be causing this? Specific date/time country settings on users iPhones? I have this out to thousands of people, and most aren't returning the a.m. (which is expected) but others are. WHY?
The problem you are describing is a known bug. Check out some discussion on the problem on stackoverflow, and you can find some possible work-arounds there.
Here's an excerpt of huyz's explaination of the bug:
The problem comes from NSDateFormatter somehow “getting stuck” in the 12 or 24-hour time mode that the user has manually selected. So if a French user manually selects 12-hour mode, and the application requested NSDateFormatter to output time with the 24-hour format “HHmm”, it would actually receive time in a 12-hour format, e.g. “01:00 PM”, as if the application had instead requested “hhmm aa”. The reverse would happen if a US user manually selected 24-hour mode: outputting time with the 12-hour format “hhmm aa” would actually get you time in the 24-hour format instead, e.g. “17:00″.
Right. The solution is to explicitly set the locale of the date formatter, ideally to en_US_POSIX. See the final answer to this question.
I was working on a data-share function of a project which was highly depending on the values/results entered in advance when I bumped into the same problem. I implemented a nasty little workaround for saving the right datetime in 24h format to the database.
The solution is very simple
First, I get the local date from the device:
NSDate* now = [NSDate date];
Second step is to create a NSDateFormatter with US locale regardless of system's locale to make sure that "PM" is going to be "PM":
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
Then, I get the date (year, month, day) into a string:
[formatter setDateFormat:#"yyyy-MM-dd"];
NSString *date = [formatter stringFromDate:now];
For the next part, I get the hours, minutes and seconds:
[formatter setDateFormat:#"hh"];
NSString *hours = [formatter stringFromDate:now];
[formatter setDateFormat:#"mm"];
NSString *minutes = [formatter stringFromDate:now];
[formatter setDateFormat:#"ss"];
NSString *seconds = [formatter stringFromDate:now];
Next, I get the part of the day:
[formatter setDateFormat:#"a"];
NSString *partOfDay = [formatter stringFromDate:now];
Then comes the logic: if the part of the day is PM but the hours are less then 12, we just have to correct that. In code:
if([partOfDay isEqualToString:#"PM"] && [hours intValue] < 12) {
hours = [[NSString alloc] initWithFormat:#"%i", ([hours intValue] + 12)];
}
After this modification, we are ready to put the string together in order to have a datetime ready to be saved into SQL:
NSString *sqlDateTime = [[NSString alloc] initWithFormat:#"%# %#:%#:%#", date, hours, minutes, seconds];
That's all there is to it. And from now we can only hope that Apple is going to fix this bug to make it work as it should be.
I hope this helps.
I want current date and time in PST. I used this code
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss zzz"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"PST"]];
NSString *timeStamp = [dateFormatter stringFromDate:[NSDate date]];
NSLog(#"String:%#",timeStamp);
It returns correct date and time in PST in string form but I want NSDate in PST. So when I change NSString to NSDate like this:
NSDate *currentPST = [dateFormatter dateFromString:timeStamp];
NSLog(#"currentPST Date:%#",currentPST);
It returns date in GMT. I have done R&D but all in vain.Output is:
String:2011-05-18 22:28:54 PDT
currentPST Date:2011-05-19 05:28:54 +0000
Can anyone suggest a solution please.
Thanks in advance
In Cocoa, NSDate is an abstract representation of a date with no time zone information applied.
Whenever you print a NSDate object, it will print the date value corresponds to the default timezone(your device timezone). Your device timezone is GMT thats why you get the value like that. If you look into that deeply, both the time where same, but the timezone varies.
I'm having a problem. I get incoming time strings in 12-hour format, and I'm turning them into NSDate objects. When the iPhone is in 12 hour format, no problem. But when it's in 24 Hour format, things go wrong. Here's some sample code to demonstrate:
NSString *theTime = #"3:19 PM";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"h:mm a"]; // "3:19 PM"
NSDate *date = [formatter dateFromString:theTime];
NSString *theString = [formatter stringFromDate:date];
In 24 hour mode, date is 1970-01-01 03:19:00, and theString is "3:19" - WRONG
In 12 hour mode, date is 1970-01-01 15:19:00, and theString is "3:19 PM" - RIGHT
So... question 1: why is the device's 24 hour setting overriding my date formatter setting?
and more importantly, question 2: How do I get a proper conversion from 12 hour time to 24 hour time?
I already have code to detect if the phone is in 24 hour mode, but other than digging around in the string and swapping the 3 with a 15, there doesn't seem to be a clean way to do this.
Not sure if you still need it, but I've had a similar problem which got solved by setting the locale for the date formatter. That is, if you want to force it to 12-hour mode, regardless of the user's 24/12 hour mode setting, you should set the locale to en_US_POSIX.
The reason for this behaviour is Locale, set the correct Locale
NSString *strAgendaDate = #"01/17/2012 12:00 AM";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"] autorelease];
[dateFormatter setDateFormat:AgendaDateFormatForMeeting];
NSDate *meetingDate = [dateFormatter dateFromString:aStrDate];
[dateFormatter setDateFormat:AgendaDateRepresentation];
strAgendaDate = [dateFormatter stringFromDate:meetingDate];
It works for both 24-hour and 12 hour format
I believe the #"h:mm a" should be #"HH:mm a".
If you use the pre-build dateformatter in cocoa, everything will be taken care of for you.
NSDateFormatter *timeFormatter = [[[NSDateFormatter alloc] init] autorelease];
[timeFormatter setTimeStyle:NSDateFormatterShortStyle];
[timeFormatter setDateStyle:NSDateFormatterNoStyle];
NSDateFormatterShortStyle and NSDateFormatterNoStyle comes in different varieties.
Using those will make sure you respect the settings the user has selected for dates and times.
The 12-14 hour clock conversion is taken care of by the SDK, if you have a model or some value object for storing your dates try to keep them as NSDate. This way you can format them only when you need to display them. Saving dates as strings could open a world of trouble when you maybe parse them from xml where the GMT is specified separately or try to add and subtract NSTimeIntervals.
I changed from #"hh:mm:ss" to #"HH:mm:ss" and time style was changed from "1:03 PM" to "13:03".
Hope this will help you.
Okay, I left a comment, but it squished all the code together, so I'll have to "answer" my question with a comment:
Thanks. I gave it a whirl with this code:
NSString *theTime = #"3:19 PM";
NSDateFormatter *timeFormatter = [[[NSDateFormatter alloc] init] autorelease];
[timeFormatter setTimeStyle:NSDateFormatterShortStyle];
[timeFormatter setDateStyle:NSDateFormatterNoStyle];
NSDate *date = [timeFormatter dateFromString:theTime];
NSString *theString = [timeFormatter stringFromDate:date];
And date comes up nil. I ran into this earlier when I tried this route, and it's not working. Very frustrating.