Search code examples
objective-cnsdatensdateformatternscalendarnsdatecomponents

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.


Solution

  • 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.