处理两个时区
Dealing with two timezones
从昨天开始我就一直在为这个问题苦苦挣扎,但我还是输了。日期相关的东西真的是我编程的祸根。
让我解释一下情况。我来自斯里兰卡 (GMT +5:30) and I'm working with a client in Sweden (GMT +1)。我正在从那里托管的 API 检索 JSON 响应。这是它的存根。响应中的每个字典数组称为 Handover.
[
{
"Tim" : 8,
"Pat" : {
"Id" : 5104
},
"Sta" : "Ej utfört",
"SB" : 1066,
"CB" : 0,
"Date" : "2015-02-19T00:00:00+01:00",
"DD" : null,
"HTI" : 1
},
{
"Tim" : 8,
"Pat" : {
"Id" : 5029
},
"Sta" : "",
"SB" : null,
"CB" : 0,
"Date" : "2015-02-19T00:00:00+01:00",
"DD" : null,
"HTI" : 1
}
]
这里的麻烦制造者是 Date
字段。如您所见,日期字符串以 ISO 8601 格式发送。我在应用程序方面所做的是从中创建对象并将其存储在核心数据中。所以为了保存这个日期值,首先我使用这个名为 ISO8601DateFormatter 的库将日期字符串转换为 NSDate
。下面是我为此编写的辅助方法。
public class func getDateFromISO8601DateString(dateString: String?) -> NSDate? {
if let dateString = dateString {
let formatter = ISO8601DateFormatter()
formatter.defaultTimeZone = NSTimeZone.localTimeZone()
formatter.includeTime = true
let convertedDate = formatter.dateFromString(dateString)
return convertedDate
} else {
return nil
}
}
现在,当我转换日期字符串 2015-02-19T00:00:00+01:00 时,我得到这个 NSDate
值,2015-02-18 23:00:00 +0000.
稍后在应用程序中,我需要检索一组当前日期的交接。下面是我为此编写的代码。
let fetchRequest = NSFetchRequest()
let entityDescription = NSEntityDescription.entityForName("Handover", inManagedObjectContext: NSManagedObjectContext.MR_defaultContext())
let datePredicate = NSPredicate(format: "date > %@ AND date < %@", NSDate().beginningOfDay(), NSDate().endOfDay())
fetchRequest.entity = entityDescription
fetchRequest.predicate = datePredicate
var error: NSError?
let handovers = NSManagedObjectContext.MR_defaultContext().executeFetchRequest(fetchRequest, error: &error) as? [Handover]
return handovers
这是另一个使用日期的地方。要根据日期值过滤记录,我需要获取日期的开始时间和结束时间。所以我有以下这些方法来 return 这些值。这些方法取自 this 库。
func beginningOfDay() -> NSDate {
let calendar = NSCalendar.currentCalendar()
calendar.timeZone = NSTimeZone.localTimeZone()
let components = calendar.components(.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit, fromDate: self)
return calendar.dateFromComponents(components)!
}
func endOfDay() -> NSDate {
let calendar = NSCalendar.currentCalendar()
calendar.timeZone = NSTimeZone.localTimeZone()
let components = NSDateComponents()
components.day = 1
return calendar.dateByAddingComponents(components, toDate: self.beginningOfDay(), options: .allZeros)!.dateByAddingTimeInterval(-1)
}
这是我从这些方法中得到的值。
beginningOfDay()
- 2015-02-18 18:30:00 +0000
endOfDay()
- 2015-02-19 18:29:59 +0000
这是疯狂的部分。当我 运行 我居住的地方的应用程序时,所有这些代码都有效。但是当我的客户 运行 发送它时,切换获取方法 return 的结果为零!
我已经追踪到这个问题,发现日期和时间有问题。但我就是想不出纠正它的方法。在完成日期操作的任何地方,我都将时区设置为 localTimeZone()
。在 AppDelegate 的 didFinishLaunchingWithOptions
方法中,我还重置了时区 NSTimeZone.resetSystemTimeZone()
。似乎没有任何效果。
有人有ideas/suggestions吗?如果您能在这方面帮助我,我将不胜感激。
谢谢。
日期“2015-02-19T00:00:00+01:00”正好是一天的开始
GMT+01 时区,因此与谓词
不匹配
NSPredicate(format: "date > %@ AND date < %@", NSDate().beginningOfDay(), NSDate().endOfDay())
将第一个 >
替换为 >=
应该可以解决问题:
NSPredicate(format: "date >= %@ AND date < %@", NSDate().beginningOfDay(), NSDate().endOfDay())
你的endOfDay()
方法也不需要减去一秒,
因为您已经将第二个日期与 <
.
进行了比较
从昨天开始我就一直在为这个问题苦苦挣扎,但我还是输了。日期相关的东西真的是我编程的祸根。
让我解释一下情况。我来自斯里兰卡 (GMT +5:30) and I'm working with a client in Sweden (GMT +1)。我正在从那里托管的 API 检索 JSON 响应。这是它的存根。响应中的每个字典数组称为 Handover.
[
{
"Tim" : 8,
"Pat" : {
"Id" : 5104
},
"Sta" : "Ej utfört",
"SB" : 1066,
"CB" : 0,
"Date" : "2015-02-19T00:00:00+01:00",
"DD" : null,
"HTI" : 1
},
{
"Tim" : 8,
"Pat" : {
"Id" : 5029
},
"Sta" : "",
"SB" : null,
"CB" : 0,
"Date" : "2015-02-19T00:00:00+01:00",
"DD" : null,
"HTI" : 1
}
]
这里的麻烦制造者是 Date
字段。如您所见,日期字符串以 ISO 8601 格式发送。我在应用程序方面所做的是从中创建对象并将其存储在核心数据中。所以为了保存这个日期值,首先我使用这个名为 ISO8601DateFormatter 的库将日期字符串转换为 NSDate
。下面是我为此编写的辅助方法。
public class func getDateFromISO8601DateString(dateString: String?) -> NSDate? {
if let dateString = dateString {
let formatter = ISO8601DateFormatter()
formatter.defaultTimeZone = NSTimeZone.localTimeZone()
formatter.includeTime = true
let convertedDate = formatter.dateFromString(dateString)
return convertedDate
} else {
return nil
}
}
现在,当我转换日期字符串 2015-02-19T00:00:00+01:00 时,我得到这个 NSDate
值,2015-02-18 23:00:00 +0000.
稍后在应用程序中,我需要检索一组当前日期的交接。下面是我为此编写的代码。
let fetchRequest = NSFetchRequest()
let entityDescription = NSEntityDescription.entityForName("Handover", inManagedObjectContext: NSManagedObjectContext.MR_defaultContext())
let datePredicate = NSPredicate(format: "date > %@ AND date < %@", NSDate().beginningOfDay(), NSDate().endOfDay())
fetchRequest.entity = entityDescription
fetchRequest.predicate = datePredicate
var error: NSError?
let handovers = NSManagedObjectContext.MR_defaultContext().executeFetchRequest(fetchRequest, error: &error) as? [Handover]
return handovers
这是另一个使用日期的地方。要根据日期值过滤记录,我需要获取日期的开始时间和结束时间。所以我有以下这些方法来 return 这些值。这些方法取自 this 库。
func beginningOfDay() -> NSDate {
let calendar = NSCalendar.currentCalendar()
calendar.timeZone = NSTimeZone.localTimeZone()
let components = calendar.components(.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit, fromDate: self)
return calendar.dateFromComponents(components)!
}
func endOfDay() -> NSDate {
let calendar = NSCalendar.currentCalendar()
calendar.timeZone = NSTimeZone.localTimeZone()
let components = NSDateComponents()
components.day = 1
return calendar.dateByAddingComponents(components, toDate: self.beginningOfDay(), options: .allZeros)!.dateByAddingTimeInterval(-1)
}
这是我从这些方法中得到的值。
beginningOfDay()
- 2015-02-18 18:30:00 +0000
endOfDay()
- 2015-02-19 18:29:59 +0000
这是疯狂的部分。当我 运行 我居住的地方的应用程序时,所有这些代码都有效。但是当我的客户 运行 发送它时,切换获取方法 return 的结果为零!
我已经追踪到这个问题,发现日期和时间有问题。但我就是想不出纠正它的方法。在完成日期操作的任何地方,我都将时区设置为 localTimeZone()
。在 AppDelegate 的 didFinishLaunchingWithOptions
方法中,我还重置了时区 NSTimeZone.resetSystemTimeZone()
。似乎没有任何效果。
有人有ideas/suggestions吗?如果您能在这方面帮助我,我将不胜感激。
谢谢。
日期“2015-02-19T00:00:00+01:00”正好是一天的开始 GMT+01 时区,因此与谓词
不匹配NSPredicate(format: "date > %@ AND date < %@", NSDate().beginningOfDay(), NSDate().endOfDay())
将第一个 >
替换为 >=
应该可以解决问题:
NSPredicate(format: "date >= %@ AND date < %@", NSDate().beginningOfDay(), NSDate().endOfDay())
你的endOfDay()
方法也不需要减去一秒,
因为您已经将第二个日期与 <
.