将具有给定时间的 NSDate 对象转换为具有相同时间和当前日期的对象的最有效方法

Posted

技术标签:

【中文标题】将具有给定时间的 NSDate 对象转换为具有相同时间和当前日期的对象的最有效方法【英文标题】:Most efficient way to convert a NSDate object with a given time to one with the same time and the current date 【发布时间】:2011-02-27 23:24:28 【问题描述】:

我目前正在创建一个处理学校日程安排的日程安排应用程序。每个计划都有一个包含开始时间和结束时间的期间对象数组。目前我将这些时间存储为 NSDate 对象,其中只有时间是真正相关的,并且每个 NSDate 对象都有一些与之关联的任意日期,这对我的应用程序来说基本上是微不足道的(它是 UIDatePicker 分配给它的任何日期,但我只使用 TimePickerMode )。我用这些日期做了很多事情。首先,我使用 NSDateFormatter 在 UITableView 中输出每个时间段的时间字符串表示形式。然后,我还尝试通过将 [NSDate date] 获取的当前时间与开始和结束时间进行比较来找到当天的当前时段。但我无法决定最好的方法。

目前,我使用 NSDateFormatter 将开始时间和结束时间转换为字符串,然后返回到现在日期与今天日期相同的日期。然后,我可以使用 - (NSComparisonResult)compare: 将开始日期和结束日期与当前日期进行比较来进行日期比较。但是,我可以认为这是非常低效的。

其他可能的方法是将每个 NSDate 转换为 NSDateComponents,然后使用 NSCalendar 将其转换回具有当前日期和相同原始时间的 NSDate。

或者,我可以采取不同的方法,完全放弃 NSDate 存储技术。相反,我可以将每个开始和结束时间存储为 NSDateComponents,然后为 UITableView 输出时间的格式化版本就足够简单了,然后我可以将 [NSDate date] 获得的日期转换为 NSDateComponents 用于逻辑比较以获得当前期间。

我看到了三到四种不同的方式来解决这个问题,实际上经过讨论后,我非常有信心我讨论的最后一种方式将是最有效的,因为它需要在不同类型的日期对象。我只是在寻找其他人的意见。

【问题讨论】:

【参考方案1】:

使用 NSDate 存储时间的问题在于它的值取决于时区。如果您的应用程序在前台或后台运行时时区或 DST 发生变化,那么您的所有时间都会突然出错。如果您实际上将 NSDate 值保存到磁盘,则同上。 (一种选择是将您的应用的默认时区设置为 UTC,但您的应用的“现在”概念对用户来说是不正确的)。

我会单独存储时间并实现与 NSDate 相互转换的方法。您可以使用 NSDateComponents 存储时间,或者您可以将其存储为单个整数(例如,午夜过后的分钟数),这样比较两次变得微不足道。

在与 NSDate 之间转换分钟时,您使用 NSDateComponents,并且您需要确保您的 UIDatePickers、NSCalendars 和 NSDateFormatters 使用相同的时区,默认情况下是本地时区。

【讨论】:

【参考方案2】:

您似乎担心 NSDateFormatter 当前对您的程序征收的开销以同步您的经期日期和当前日期。但实际上,您根本不在乎日期,您只需要从一天开始的时间。

为什么不去掉中间人?将开始和结束时间存储为 NSTimeIntervals,实际上只是双倍。将开始和结束时间修改为 86,400,即一天中的秒数,以便将时间简化为新一天开始后的秒数。你并不关心它代表什么日子,除了那一天被表示为第二个 0。

然后,每当您拉出当前 NSDate 时,将其 NSTimeInterval 修改 86,400 以获得以秒为单位的时间,并将其与存储的周期值进行比较。整个过程中唯一涉及的对象转换将使用原始 timeIntervalSinceReferenceDate。其余的是简单的 mod 和比较运算符,您可以将周期数存储为简单的 NSTimeIntervals。

【讨论】:

这似乎仍然涉及一个经常被忽视的转换——将修改后的 timeIntervalSinceReferenceDate 转换为反映当前时区的一个。由于 timeIntervalSinceReferenceDate 返回自格林威治标准时间 2001 年 1 月 1 日午夜以来的秒数,因此只需修改时间间隔即可得到一个数字,即自午夜以来的实际时间间隔 18000 或 5 小时。因此,我觉得这可能涉及每次我希望获得自午夜以来的秒数时创建一个 NSCalendar 对象。 自午夜以来的几秒钟内您都不需要它。但是,例如上午 9:30 并不总是自午夜以来的相同秒数。您需要一个 NSCalendar 才能在当天上午 9:30 获得。

以上是关于将具有给定时间的 NSDate 对象转换为具有相同时间和当前日期的对象的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章

Swift 和 ObjectMapper:具有最小值的 NSDate

为啥核心数据托管对象中的 NSDate 转换为 NSTimeInterval?

如何使 NSDate 与关联对象一起工作?

创建具有特定时区的 NSDate 对象

如何将具有 Decimal 的 spark DataFrame 转换为具有相同精度的 BigDecimal 的 Dataset?

将具有相同索引的熊猫系列列表转换为字典