I have a UIDatePicker and a button. When I press the button I want to display in the log the message "Setting a reminder for x" where x is the time displayed by the date picker.
Everytime I press the button, the time logged is precisely 3 hours behind the time displayed by the picker (the time displayed by the picker is my current time). I suspect it has something to do with the time zone. I live in GMT +2 time zone (I guess it's +3 since we are in daylight saving time).
Do you have any idea how I could make the time logged to be the same as the time displayed?
Below is the method that gets executed when I press the button. Thanks.
- (IBAction)addReminder:(id)sender {
[self.datePicker setTimeZone:[NSTimeZone systemTimeZone]];
NSLog(#"Setting a reminder for %#", self.datePicker.date);
}
NSDate is simple representation of some moment in time, it knows nothing about your local time. When you log it (actually, when description) message is sent, it uses GMT to display itself.
UIDatePicker uses your timezone by default (see https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDatePicker_Class/#//apple_ref/occ/instp/UIDatePicker/timeZone).
So, here is how it works:
You choose some time in DatePicker, but time is meaningless unless you specify timezone.
DatePicker uses your local (GMT+2) timezone and creates NSDate for it.
You display NSDate and since it knows nothing about timezone, it simply displays itself as GMT.
To display your date, your should use NSDateFormatter. It has Timezone property: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/#//apple_ref/occ/instp/NSDateFormatter/timeZone
You can also use NSCalendar and its components.
You should read this guide: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DatesAndTimes/DatesAndTimes.html since dates, formatters and calendars are not very clear in Cocoa unless you understand its concepts.
Try this...
NSDate *now = [[NSDate alloc] init];
[self.datePicker setDate:now];
[self.picker setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:2*60*60]]; // GMT+2 Your timeZone
NSLog(#"Setting a reminder for %#", self.datePicker.date);
Related
This question already has answers here:
Getting date from [NSDate date] off by a few hours
(3 answers)
Closed 6 years ago.
I am using a MacBook developing my iOS app & run it on a real iPhone. Both my MacBook & my iPhone show me current time is 2016-08-11 13:18
But at the same time, the following code shows me the current time that is 3 hours earlier than now:
NSLog(#"NOW = %#",[NSDate date]); // it prints out 2016-08-11 10:18:17 +0000
But NSDate documentation tells me the +date function returns current date and time. Why I get a date time three hours earlier then?
When you log an NSDate using NSLog it is always shown in UTC. It sounds like you are in the UTC+3 time zone, so a time shown in UTC will be 3 hours earlier.
If you want to display a date in your local time zone create a date formatter and use it to display the date instead. (By default date for matters use the user's local time zone.)
An NSDate does not have an inherent time zone. An NSDate records an instant in time. You have to use a time zone in order to look at it.
Your date is correct. You are just displaying it in a way that's confusing.
I am new to IOS development. I am receiving a date string from an API and would like to set the time to the user's current time zone. The dateformatter looks like:
[dateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'"];
I know I can set the timezone like so
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
But is there a way to set it depending on the user's current time zone?
My apps are time-zone agnostic: I want the dates and times saved and displayed in a manner that ignores changes in the user's time zone. Once I've recorded the local date/time of some user action in my app (typically by saving timeIntervalSince1970 in an sqlite DB), I want to show the same date/time string regardless if the user's time zone has changed or not, and regardless of the user's various time zone settings in his device.
For example, if a user's action occurs at 1:15 pm local time in San Francisco, and then he opens my app a few days later in New York, I want that prior action to still appear as 1:15 pm (not 4:15 pm), and even if he's manually set some other time zone in his device (e.g., Chicago). A second action in New York at 9:00 pm there, should forevermore display as 9:00 pm, even when back in California.
I could achieve my goal by saving every date/time as a string (based on the user's local time zone), and then never use the date methods again -- but then I couldn't do date/time arithmetic (e.g., sorting).
How can I be time-zone agnostic when saving and retrieving dates/times?
(Apple's Calendar app seems to behave this way when Time Zone Override is on, but only if I manually set the event time.)
Here's the working solution (#Hot Licks deserves the credit, but he didn't post an answer):
Subclass NSDate and add a gmtDate method that does the conversion from local TZ to GMT. gmtDate uses #"yyyy-MM-dd HH:mm" as the format string, which also drops seconds from the value. Like this:
+(NSDate *)gmtDate
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"yyyy-MM-dd HH:mm"; // drops the seconds
dateFormatter.timeZone = [NSTimeZone systemTimeZone]; // the local TZ
NSString *localTimeStamp = [dateFormatter stringFromDate:[NSDate date]];
// localTimeStamp is the current clock time in the current TZ
// adjust date so it'll be the same clock time in GMT
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSDate *gmtDate = [dateFormatter dateFromString:localTimeStamp];
return gmtDate;
}
In didFinishLaunchingWithOptions: add [NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"GMT"]] so all date formatters make date strings in GMT by default (but never include the timezone in the format string).
When the date/time of a user action needs to be saved, get the date via [NSDate gmtDate] and save that value in your database.
Record the time zone along with the timestamp. Use that time zone when formatting the timestamp later. You'll need to add another column to your database table.
Either save the time zone, as Rob suggested, or save the time as both an NSDate and a string. Use the string for the UI and the NSDate for calculations.
Or hey, do all three, if you need them.
I know that NSDate doesn't have timezone information.
However, I'm trying to understand how to manipulate them properly.
At the moment I'm passing a date into an object. That date is the user selected date at time 00:00:00.
i.e. if the user hits October 21st then the NSDate passed in should be. 21/10/2013 00:00:00.
However, it isn't it's 20/10/2013 23:00:00. (One hour before).
Now, this is nothing about formatting them or displaying them. I'm just using the NSDates.
I'm creating the date using NSDateComponents and NSCalendar.
I guess my question is...
How can I tell what date an NSDate is actually referring to in my local time zone?
I need to send a UNIX time stamp for 00:00:00 and 23:59:59 for a given date. However, at the moment when I set the hour, minute and second to 0, 0 and 0 then I'm not getting midnight in the current time zone I'm getting midnight in GMT.
This isn't what I want.
Fixed?
OK, I've fixed it... I think. At least, it's doing what I want it to do.
The trick is...
NSTimeZone *timeZone = [NSTimeZone localTimeZone];
[dateComponents setSecond:timeZone.secondsFromGMT];
I've been confused by this many times. When you NSLog an NSDate, you'll always get the output in GMT. So the 20/10/2013 23:00:00 (GMT) you're seeing is the same as your expected 21/10/2013 00:00:00 (BST). The UNIX timestamp for both of these dates would be the same because it doesn't take into account timezone - it's always UTC.
If you want to output in a user-readable format, an NSDateFormatter will format the date using your current timezone and locale.
When I am printing the date
//getting the current date and time
self.date = [NSDate date];
NSLog(#"%#",date);
The date which I am getting is correct, but there is a delay in time by 6 hrs. My system time is correct.
try this
NSLocale* currentLoc = [NSLocale currentLocale];
NSLog(#"%#",[[NSDate date] descriptionWithLocale:currentLoc]);
Make use of NSDateFormatter
NSDate *today = [NSDate date];
//Create the dateformatter object
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//Set the required date format
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
//Get the string date
NSString *dateString = [dateFormatter stringFromDate:today];
//Display on the console
NSLog(dateString);
Logging an NSDate in the debugger is somewhat misleading as it gives you a calendar day and time for a particular time zone - UTC / GMT. However, NSDate has no inherent time zone or any inherent relationship to how humans perceive and think about dates at all. Instead, it is a timestamp. Classes like NSDateComponents, NSTimeZone, NSDateFormatter, and so on all exist to provide human context and formatting.
So what you see is the timestamp formatted to that particular format and UTC time zone, which is how NSDate will always appear when printed in the debugger or the console. If you were to calculate the time zone offset between UTC and your own time zone, you'd find that the date represents the time stamp you gave it, and not one however many hours off.
you can set current time zone for customizing your date format.
This link can help:
https://stackoverflow.com/a/7213629/456471
The default date string representation is probably formatting the date as UTC, rather than your local time zone (the exact format that it will use is not defined, and may change from release to release, so you shouldn't rely on it). You should use the NSDateFormatter class if you need to format a date in a particular format (or with a particular time zone, including the local time zone); see the Data Formatting Guide and the NSDateFormatter Class Reference for more information.