如何在 Core Data 中存储没有时间的日期

Posted

技术标签:

【中文标题】如何在 Core Data 中存储没有时间的日期【英文标题】:How to store dates without times in Core Data 【发布时间】:2009-08-05 09:45:47 【问题描述】:

我一直在尝试找到一种在 iPhone 上使用 Core Data 存储日常数据的合理方法。

我的应用接收 csv 格式的数据,有日期但没有时间:

date, cycles
2009-08-01, 123
2009-08-02, 234
2009-08-03, 345
2009-08-04, 456

存储此数据时,每天应该只有一条记录。我认为最好的办法是创建一个 NSDate 进行存储,但去掉时间和时区数据。

我可以使用 NSDateComponents 或 NSDateFormatter 轻松创建一个 NSDate,而无需小时、分钟或秒。但是,即使我将时区明确设置为 UTC 或距 GMT 零秒,使用 NSLog() always 输出创建的日期也会有我的本地时区,例如:

2009-07-29 00:00:00 +0100

有没有人知道制作没有时间组件的 NSDates 的更好方法?或者也许是存储日期的更好方法?

【问题讨论】:

【参考方案1】:

一个好的编程经验法则是始终以 UTC 格式存储日期。是否使用 Core Data 并不重要;你仍然需要做一些工作,因为 Apple 的日期类非常糟糕。

日期在内部表示为自参考日期以来的秒数,我相信它是 2001 年 1 月 1 日 00:00:00(尽管实际的参考日期不是很重要)。重点是,NSDate 对象始终以 UTC 为原生。如果您在 CSV 文件中获取的日期是本地日期,则需要执行以下操作来获取 UTC 时间:

NSDate *UTCDate = [localDate addTimeInterval:-[[NSTimeZone localTimeZone] secondsFromGMT]];

然后,我将时间设置为 00:00:00。现在,您正在以 UTC 格式在午夜保存日期。出于演示目的,您将使用配置了您选择的时区的NSDateFormatter(如果您未指定系统时区,则为默认时区)来显示这些日期。

不过,当您只处理日期时,时区并不重要。只要您确保将 NSDateFormatter 上的时区设置为 UTC,无论用户在其设备上选择了哪个时区,您都将始终显示相同的日期。

如果您不喜欢此解决方案,您可以随时以其他格式存储您的日期。您可以使用doubleint 以某种自定义格式存储日期(例如,自某个参考日期以来的天数),或者您甚至可以滚动您自己的类以完全按照您想要的方式对日期进行建模并存储它作为NSData 对象。只要类实现了NSCoding,就可以将其序列化为Core Data中的NSData对象。您只需将 Core Data 中的属性类型设置为“Transformable”即可。

您有很多选择,其中没有一个涉及编写您自己的 SQLite 查询和数据库的工作。

【讨论】:

非常感谢。我现在已经整理好了。您的回答使转换更有意义,下面 Peter Hosey 解释了 NSLog 输出。【参考方案2】:

NSDate 没有时区。 NSLog 使用您当地的时区;它说 +0100,因为这就是你所在的位置。

【讨论】:

谢谢。我不知道它是使用本地时区的 NSLog。在您指出这一点之后,我又使用了系统日期和时间首选项,现在它更有意义了。 我不明白 +0100。它究竟代表什么? srikanth rongali:时区偏移。提问者比格林威治标准时间早一小时:格林威治标准时间+0100。 (后一对数字是分钟,因此比格林威治标准时间提前五个半小时的时区为 +0530。)【参考方案3】:

NSDate 对象将始终包含时间日期 - 引用它“表示[s] 单个时间点”的文档,并通过存储自其参考日期以来的时间值(格林威治标准时间 2001 年 1 月 1 日开始,再次根据文档)。因此,您不能有一个不知道一天中时间的 NSDate。

与其尝试以您自己的方式存储日期,我仍然会在您的模型中使用 NSDate 并考虑向您的实体类添加一对方法,其中一个将执行您上面描述的操作,将 NSDate 设置为 00:00 :00 在给定的一天。另一个可以以您喜欢的格式仅返回来自 NSDate 的日期。然后这些将使用 Core Data 生成的 getter 和 setter 来访问 NSDate 属性。

通过仍然使用 NSDate,您使用的是 Core Data 可以原生使用的类,这意味着您仍然可以轻松地使用谓词进行过滤,或者按日期对获取的结果进行排序,而无需考虑太多。

【讨论】:

感谢您的回复。这仍然存在时区问题。例如:我将数据保存在 7 月的伦敦 (GMT+0100),而其他人将其保存在库比蒂诺 (GMT-0700)。现在存储的日期有 8 小时的差异。我认为回到原始 SQLite 可能更有效。 我不太明白这个问题:NSDate 中的日期存储为绝对日期,自 2001 年 1 月 1 日 GMT 00:00:00 起的秒数。因此,如果不同时区的两个人在完全相同的时刻存储“当前”日期,那么他们的 NSDate 是相同的。时区仅在检索/显示时使用,除非您告诉 NSDate 否则它将与系统区域设置时区一起使用。也就是说,如果你的两组数据同时存储在伦敦和库比蒂诺,那么存储的日期是相同的,没有区别。

以上是关于如何在 Core Data 中存储没有时间的日期的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Core Data 中存储星期几?

Swift Core Data Fetch 按日期和时间存储为字符串并排序

在 Core Data 中存储指针

如何使用 Core Data 和 iOS 5 存储指南?

事后修改 Core Data 中现有的对象属性

Xcode Entity Core Data - NSDate 错误的年份? [复制]