【问题标题】:How to fetch records by date property considering time zone?考虑到时区,如何按日期属性获取记录?
【发布时间】:2017-09-08 19:00:08
【问题描述】:

假设我在 UTC +0200 区域,我想用 date 保存记录:2017-10-04。我是这样做的:

service!.date = Calendar.current.date(from: DateComponents(year: date.year, month: date.month, day: date.day))!

日期是这样保存的:

2017-10-04 22:00:00 +0000

现在我需要显示每天的服务。代表要求我为date 提供服务,例如:

2017-10-04 22:00:00 +0000

一切都很好,记录被提取并且没问题。

但假设我要去另一个国家 (UTC +0100),那里的代表要求我提供相同的 date,但这次看起来像这样:

2017-10-04 23:00:00 +0000

并且...没有任何内容被获取。为什么?不应该是同一天吗?如何解决?

我如何获取记录的谓词如下所示:

NSPredicate(format: "date = %@", date as NSDate)

【问题讨论】:

  • 我认为你需要以相同格式的 UTC 保存和获取
  • 什么意思?该应用程序正在生产中......所有内容都保存到持久存储中。现在我需要解决这个问题...
  • 始终与 UTC 合作必须解决您的问题,您需要转换为 UTC 保存并在转换为 UTC 后获取它,我不知道您是否理解我,对不起我的英语

标签: ios swift core-data nsdate


【解决方案1】:

如果我理解这一点,您只关心日期而不是时间,但您使用NSDate 存储它,对吗?问题是NSDate 不知道时区。它实际上只是自某个纪元以来的秒数,将其转换为日期的唯一方法是知道您要转换的时区。

这里最好的答案可能是将其存储为String,格式类似于2017-10-04。否则,正如您所发现的,时区会导致同一天被表示为不同的Dates。

如果您使用的是 iOS 10+,则可以使用 NSISO8601DateFormatter 来处理此问题,否则您可以使用适当的格式配置 DateFormatter

或者,您可以继续将其存储为 NSDates,但在使用 Calendar 转换为/从日期组件时要特别注意始终指定 UTC 时区。


如果您需要修复生产中的应用程序,最好的解决方案可能是采用启发式算法,将每个日期(以 UTC 解释)“四舍五入”到最接近的午夜值。这应该有效地恢复用于创建日期的时区。唯一的困难是在距离 UTC 12 小时或更长时间的时区(实际上有一个 UTC+14:00 时区),但我相信这些时区大多只是无人居住的岛屿,所以你可能没有任何从这些时区创建的日期。

无论如何,您都需要检查所有数据,使用 UTC 将其转换为日期组件,然后检查小时。弄清楚您是否需要向上或向下舍入才能到达最近的午夜,并相应地调整实际日期。然后,您可以获取更正后的日期组件并将其写回(通过使用 UTC 将其转换回 NSDate 或将其转换为字符串,具体取决于您是否正在修改数据格式)。

由于这是 CoreData,如果您要切换到字符串,您可以实现自定义迁移来处理这个问题。否则,您将需要一些方法来尝试检测您是否从一开始就有受影响的数据(因为您不想在每次发布时都重写所有日期,只是在解决此问题后的第一次发布时重写)。

【讨论】:

  • 那么有没有办法以某种方式处理这个问题?该应用程序正在生产中......需要解决这个问题。
  • 不考虑字符串解决方案...因为它已经作为 NSDate 存在。
  • @BartłomiejSemańczyk 我已经用建议更新了我的答案。
  • NSISO8601DateFormatter 是干什么用的?我可以用它来解决我的问题吗?
  • 它只是一个专门处理 ISO8601 日期的日期格式化程序,我推荐它是因为它可以很容易地生成 2017-10-04 格式。如果您不打算将模型切换为将日期存储为String,那么它是无关紧要的。只需使用在创建 NSDate 对象以用于您的数据时始终使用 UTC 的方法。
猜你喜欢
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多