如何根据时区按日期属性获取记录?

时间:2017-09-08 19:00:09

标签: 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 ),代表要求我提供相同的date,但这次看起来像这样:

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

并且......没有任何东西被抓取。为什么?不应该是同一天?如何解决?

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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

或者,您可以继续将其存储为NSDate,但在使用Calendar转换为日期组件时,请务必指定UTC时区。

如果你需要修复一个正在制作的应用程序,那么这里最好的解决方案可能就是采用一种“#round;""以UTC格式解释的每个日期到最近的午夜值。这应该有效地恢复用于创建日期的时区。唯一的困难是在距离UTC 12小时或更长时间的时区(实际上是UTC + 14:00时区),但我相信这些时区大多只是无人居住的岛屿,所以你可能不会有这些时区创建的日期。

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

由于这是CoreData,如果您要切换到字符串,则可以实现自定义迁移来处理此问题。否则,您需要一些方法来尝试检测您是否已经开始使用受影响的数据(因为您不希望在每次启动时重写所有日期,就在修复此问题后的第一次启动时)。