【问题标题】:Store time zone independent time-only in NSDate object仅在 NSDate 对象中存储时区独立时间
【发布时间】:2014-01-02 04:00:05
【问题描述】:

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

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

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

提前感谢您的帮助!

【问题讨论】:

  • 为什么不将时间保持为自午夜以来的秒数?使用模算术,您可以在需要时轻松地将其划分为小时/分钟/秒。
  • 这是一种有趣的方法——我没有考虑过。您能否在答案中提供一个示例?我需要在NSDate 对象和(我假设)int 存储秒数之间进行偶尔的转换,因为时间是使用UIDatePicker 选择和修改的。
  • 您不需要使用 UIDatePicker。您可以改用 UIPickerView 或 UIStepper。但是您始终可以使用timeIntervalSinceReferenceDate 与 NSDate 进行转换,将日期设置为 2001 年 1 月 1 日。(请记住,系统会认为这是 GMT 时间,因此您所做的任何格式(以及任何 UIDatePicker)都会有有一个 GMT 时区。)
  • 请记住NSDate 不记录时区。它基本上是NSTimeInterval 的对象包装器,即表示自纪元以来的时间的浮点数。时区仅在您转换为/从您向用户显示的内容转换时才会出现。

标签: ios objective-c nsdate nsdatecomponents


【解决方案1】:

如果您不需要“日期”,我建议您根本不要使用 NSDate,否则您会遇到各种问题。正如 cmets 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(由于时区原因恰好是今天)。例如:

// 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];

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    相关资源
    最近更新 更多