在NSDate对象中仅存储与时区无关的时区

时间:2014-01-02 04:00:05

标签: ios objective-c nsdate nsdatecomponents

我正在创建一个包含时间表功能的应用,允许用户指定特定日期的时段(例如,时段1从9:00到10:00;时段2从10:00到11:00,等等)。由于应用程序由Core Data支持,因此将句点存储为具有两个NSDate属性的核心数据管理对象似乎是明智的:startTimeendTime

假设句点不能跨越多天,NSDate个对象中的日期无关紧要 - 我只对时间感兴趣。虽然一种方法是简单地使用NSDateComponents来提取时间(并忽略日期),如果我正在对NSDate个对象进行比较,或者根据这些对象进行排序,那么如果日期不同那么会影响比较或排序。我认为解决此问题的一种方法是手动将startTimeendTime属性设置为具有相同(任意)选择的日期。这是围绕这个问题的最好方法吗?

此外,时间(即NSDate个对象)需要与时区无关。如果用户从说澳大利亚旅行到美国,那么我不希望所有时间现在都显示他们在半夜上课!补偿时区变化与此应用程序无关,因此无论时区如何,我都希望时间保持静止。我也很感激这方面的建议。

提前感谢您的任何帮助!

1 个答案:

答案 0 :(得分:2)

如果您不需要“日期”,我建议您根本不使用NSDate,否则您将遇到各种问题。正如评论中所述,NSDate不是时区感知,这意味着您将进行大量不必要的转换,以确保您的应用程序适用于所有时区。

我也可以使用这种方法来保存午夜以来的秒数,或者从午夜开始有两个小时和分钟的字段。这基本上是当地时间,总是如此。

要从UIDatePicker获取此信息,您必须将NSDate转换为NSDateComponents

- (IBAction)datePickerChanged:(UIDatePicker *)sender {
    NSDate *date = sender.date;
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    calendar.timeZone = sender.timeZone;

    NSDateComponents *components = [calendar components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:date];

    NSInteger hours = components.hour;
    NSInteger minutes = components.minute;
    NSLog(@"%02ld:%02ld", (long)hours, (long)minutes);

    NSInteger secondsSinceMidnight = hours * (60*60) + minutes * 60;
    // save to core data
}

如果你想在datePicker中显示你的时间,你必须采取相反的方式,你必须从保存的组件创建一个NSDate(由于时区原因恰好是今天)。 e.g:

// get from core data
NSInteger secondsSinceMidnight = 8 * (60*60) + 30 * 60;

NSInteger minutes = (secondsSinceMidnight / 60) % 60;
NSInteger hours = (secondsSinceMidnight / 3600);
NSLog(@"%02ld:%02ld", (long)hours, (long)minutes);

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
calendar.timeZone = datePicker.timeZone;

// use today as day, to avoid timezone issues
NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
components.hour = hours;
components.minute = minutes;

datePicker.date = [calendar dateFromComponents:components];