假设我在区域 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)
答案 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,如果您要切换到字符串,则可以实现自定义迁移来处理此问题。否则,您需要一些方法来尝试检测您是否已经开始使用受影响的数据(因为您不希望在每次启动时重写所有日期,就在修复此问题后的第一次启动时)。