NSDate timeIntervalSinceNow and local timezone? - objective-c

I'm doing a calculation to find the NSTimeInterval between a known futureDate (which is in GMT/UTC) and the current time (and timezone) where the device currently resides.
NSTimeInterval approachInterval = [futureDate timeIntervalSinceNow];
I know that NSDate does not store any timeZone specific data, this rather being something that is calculated when the date needs displaying on the device.
My question is that from my initial tests (I'm currently in GMT+0001) it seems that the NSTimeInterval returned does not account for my local timezone. Do I have to manually calculate the timezone offset and remove that from my interval, and what would be the best way of doing that given that I can't supply an NSDate with a correct timezone (using timeIntervalSinceDate: for example)

NSDate represents a single point in time. It does not have (and does not need!!) a time zone. So "a known futureDate (which is in GMT/UTC)" or "I can't supply an NSDate with a correct timezone" does not make sense.
[futureDate timeIntervalSinceNow] returns the time interval between futureDate and the
current date and time and is completely independent of any time zones.
If you do not get the expected result, then perhaps your calculation of futureDate was wrong.

Related

How to show nsdate without converting to local time zone?

I want to present a date to the user in the dates own timezone. So without it being converted to the users timezone.
Basically what happens: I retrieve a string '2015-04-01T15:35:00-04:00' from the backend, and I convert it to a NSDate. Later on I want to show the user the time: 15:35.
But NSDateFormatter converts the date to my system time zone (+02:00) which results in showing 21:35.
I've searched all over the internet to find out I can skip this convert, but I can't find anything.
What do I miss?
Help is really appreciated.
You will have to save the original timezone in addition to the NSDate representation and use it when you want to present the time in the original timezone.
NSDate keeps the date/time relative to GMT (UTC).

'Normalized' NSDateFormatter

I have to parse strings like 2012-06-06T18:00:00 or 2012-06-06 without any timezone information. When I parse this the date formatter uses the local timezone and takes DST into account.
But what the date actually means is that this event occurs on 2012-06-06 not depending on the timezone, but on 2012-06-06T00:00:00 in every timezone.
Should I store the year/month/day values separately?
The same time in different time zones will correspond to different absolute times (which are represented by NSDate). So one NSDate object cannot represent what you are trying to represent. You will need one NSDate per time zone you are interested in.
You can create an NSDateComponent instance with your string. Then use NSCalender with the locale (time zone) you want to transform those date components into an NSDate (a point in time).

Most efficient way to convert a NSDate object with a given time to one with the same time and the current date

I'm currently creating a scheduling application that deals with schools schedules. Each schedule has an array of period objects that contains both a start and an end time. Currently I have these times stored as NSDate objects, where only the time is really relevant and each NSDate object has some arbitrary date associated with it that is largely insignificant to my application (it's whatever the UIDatePicker assigns to it, but I only use the TimePickerMode). I do a number of things with these dates. First, I use an NSDateFormatter to output a string representation of the time for each period in a UITableView. I then also attempt to find the current period in the day by comparing the current time, fetched by [NSDate date], to the start and end time. But I am having trouble deciding the best way to do this.
Currently, I use an NSDateFormatter to convert the start and end times to strings, and then back to dates that now have a date the same as today's date. Then after that I can do my date comparisons using - (NSComparisonResult)compare: comparing the start and end dates to the current date. However, I could see this as being very inefficient.
Other possible ways could be to convert each NSDate to NSDateComponents, then use NSCalendar to convert that back into an NSDate with the current date and the same original time.
Or, I could take a different approach and ditch the NSDate storage technique altogether. Instead I could store each start and end time as NSDateComponents, then it would be simple enough to output a formatted version of the time for the UITableView, and then I could convert the date obtained by [NSDate date] to NSDateComponents to be used for logical comparisons to obtain the current period.
I see three or four different ways of going about this, and actually after talking it out I I'm pretty confident the final way I discussed would be the most efficient as it requires the least amount of runtime conversions between different types of date objects. I'm just looking for other people's inputs.
The problem with using NSDate to store a time-of-day is that its value is dependent on the time zone. If the time zone or DST changes while your app is running in the foreground or background, then all of your times will suddenly be wrong. Ditto if you actually save NSDate values to disk. (One option is to set your app's default time zone to UTC, but then your app's idea of "now" will be incorrect to the user).
I would store the time separately and implement methods to convert to and from NSDate. You could store the time using NSDateComponents, or you could just store it as a single integer (say, minutes past midnight) which makes it trivial to compare two times.
When converting minutes to and from NSDate you use NSDateComponents, and you need to make sure that your UIDatePickers, NSCalendars, and NSDateFormatters are using the same time zone, which by default is the local time zone.
It seems like you're worried about the overhead that NSDateFormatter currently levies on your program to synchronize the day of your periods and the current date. But really, you don't care about the date at all, you just want the time since the beginning of the day.
Why not cut out the middleman? Store the start and end times as NSTimeIntervals, which are really just doubles. Mod the start and end times by 86,400, the seconds in a day, in order to distill the time down to simply the time in seconds after the start of a new day. You don't really care what day it represents, except that that day is represented as second 0.
Then whenever you pull the current NSDate, mod its NSTimeInterval by 86,400 to obtain the time in seconds and compare it against the stored period values. The only object conversion involved in the whole process would be using the primitive timeIntervalSinceReferenceDate. The rest are simple mod and comparison operators, and you get to store your period numbers as simple NSTimeIntervals.

Do NSDate's in CoreData encapsulate time zone?

I keep dates and times in my CoreData store and need to accurately present to users the time as originally entered. The problem is that if they entered 4:00 on the East Coast, then later look at the recorded time on the West Coast, it appears as 1:00, since the iPhone translates universal times to local times. I need it to show 4:00 -- probably 4:00 (+3h00).
Before I go and restructure my Core Data model, I want to be sure there's no way to derive the NSTimeZone that was active at creation-time from a stored NSDate object. Is there? If not, any recommendation how best to capture NSTimeZone at creation time myself? An NSNumber representing the creation-time NSTimeZone time difference from GMT?
Thanks.
As you've discovered, NSDate represents a universal point in time and does not include specific time zone information.
I'd suggest instead of storing the offset, store the NSTimeZone's name property. Then you can use +[NSTimeZone timeZoneWithName:] to get the time zone and thence convert it to local time. This gives you maximum flexibility in how you display the information to the user.

Covert NSString to NSDate in a different timezone

I am trying to convert a string to date in a separate time zone from the current system time zone. I have set the time zone of the dateformatter to this timezone. But the NSDate I get is always in my current time zone.
For instance, my current time zone is PDT. I have set the DateFormatter's time zone to CST. I have a string with the time in CST. But when I use date formatter to convert this string to date, I get the date in PDT, whereas I want it in CST.
Can someone please help.
Thanks.
NSDate stores only the seconds since 00:00:00 01 Jan. 2001. The description of NSDate will use your current time zone (if try to debug with NSLog for example).
You must get the default time zone with
[NSTimeZone defaultTimeZone]
and then calculate the offset by using
-(NSTimeInterval)secondsFromGMT