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?
Related
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);
I have integrate RSS feed parser into iOS application. One of the field in the received data is published date. I'm able to parse that date if the iPhone locale is English-United States. But when I change the language of iPhone to Spanish, its not able to convert the string to NSDate object.
Here's the code that I wrote:
NSString* dt = #"Fri, 26 Jun 2015 00:00:00";
NSDateFormatter* dtFormatter = [[NSDateFormatter alloc] init];
//set the locale to spanish
[dtFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"es"]];
[dtFormatter setDateFormat:#"EEE, dd MMM yyyy hh:mm:ss"];
NSDate* conDt = [dtFormatter dateFromString:dt ];
NSLog(#"%#", conDt); //This value is always (null)
Even after setting the locale to "es" (which is spanish), its still not able to parse it properly. How can I convert the string to date in iOS?
When you set the locale, you don't want to use the locale of the device, but rather the locale used when the string was created (because you're taking an English string and want to convert it to NSDate regardless of the locale of the device). In fact, it's advised to use en_US_POSIX:
[dtFormatter setLocale:[NSLocale localeWithLocaleIdentifier:#"en_US_POSIX"]];
See Technical Q&A #1480. This focuses on the Gregorian calendar issue with RFC 3999/ISO 8601 date strings, but it is applicable to language settings, too.
By the way, I notice that you're not setting the timezone. Often when dates do not bear any timezone information, they've been converted to GMT/UTC/Zulu. So you may want to set the timezone for your formatter, too:
[dtFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
Given that the time component of your string is "00:00:00", perhaps this isn't significant, but if dealing with datetime strings, you often want to make sure you correctly capture the timezone used within the string, as well.
So there is a section on web application that users can enter events into and the web service sends those events to the mobile app in the following format:
"yyyy-MM-dd'T'HH:mm:ssZZZZZ"
I'm having issues trying to convert the string into a date so I can get just the time from the event (formatted in the correct timezone as well), So for example here's one that comes over "2015-03-20T20:00:00-07:00", which when I pull the time should be 1PM Pacific Time. But instead I either get 8PM or 3AM (depending on whether I add UTC abbreviation to the date formatter).
Here's what I have so far, I know I'm missing something here & maybe there's another date formatter that needs to be used but so far I can't figure out where I'm going wrong.
NSString *datePattern = #"yyyy-MM-dd'T'HH:mm:ssZZZZZ";
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:datePattern];
NSString *sString = [valueDict valueForKey:#"start_date"];
NSDate *startDate = [dateFormatter dateFromString:sString];
NSDateFormatter *timeFormatter = [NSDateFormatter new];
[timeFormatter setDateFormat:#"hh:mm a"];
[timeFormatter setLocale:[NSLocale systemLocale]];
NSString *timeString = [timeFormatter stringFromDate:startDate];
2015-03-20T20:00:00-07:00 is 8pm Pacific Daylight Time.
If you're representing 1pm PDT, that's either
2015-03-20T13:00:00-07:00
or represent that in "Zulu" (i.e. GMT/UTC)
2015-03-20T20:00:00Z
When working with a web service, the latter is the common convention for ISO 8601 dates. Then, when you present it to the user, you present it to them in their local timezone (using a NSDateFormatter with its default timeZone setting.
Note, when using NSDateFormatter to prepare ISO 8601 dates, you will want to ensure that you specify a locale of en_US_POSIX as outlined in Technical Q&A QA1480. When designing app for US audience this isn't critical, but it's best practice in case the user is not using a gregorian calendar on their device.
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.
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.