ios - 考虑到时区,如何按日期属性获取记录?

标签 ios swift core-data nsdate

假设我在 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),代表要求我提供相同的日期,但这次看起来像这样:

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

然后...什么都没有获取。为什么?不应该是同一天吗?如何解决?

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

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

最佳答案

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

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

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

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


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

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

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

关于ios - 考虑到时区,如何按日期属性获取记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46123022/

相关文章:

objective-c - 为什么我不能在我的 iOS 项目的类中导入我的协议(protocol)?

ios - 自适应启动屏幕 Storyboard : is there a way to differentiate iPad orientations?

ios - Swift 核心数据 - _NSSingleObjectI(末尾的大写字母 "i")被返回而不是 String

ios - 如何在 Swift 中检查未定义或空变量?

objective-c - UITableViewCell 子类未初始化

ios - 动态类型别名 Swift 3

ios - tableview 上的持久数据(存储在 coredata 中)问题

iphone - 通过 UIManagedDocument 异步打开时如何确保 NSManagedObjectContext

objective-c - NSManagedObjectContext,在哪里声明?

swift - 我应该在 swift 的 getter 方法中返回什么