gpt4 book ai didi

swift - 使用 DateComponent 构造 NSDate 会给出不一致的结果

转载 作者:行者123 更新时间:2023-11-28 07:06:14 24 4
gpt4 key购买 nike

我为 NSDate 创建了一个扩展,它删除了时间组件,以允许仅基于日期对 NSDate 进行相等性检查。我通过获取原始 NSDate 对象,使用 DateComponent 类获取日、月和年,然后使用获取的信息构造一个新的 NSDate 来实现这一点。虽然获得的 NSDate 对象在打印到控制台时看起来是正确的(即时间戳是 00:00:00)并且在两个相同的日期上使用 NSDate.compare 函数返回 NSComparisonResult.OrderedSame,如果您再次使用 DateComponent 解构它们,其中一些将小时设置为 1。这似乎是一个随机事件,大约有 55% 的时间出现此错误。在构造新的 NSDate 之前强制 DateComponent 的小时、分钟和秒属性为零而不是假设它们将默认为这些值并不能纠正这种情况。确保设置时区会有所帮助,但同样无法解决问题。

我猜某处可能存在舍入错误(可能在我的测试代码中),我弄乱了转换或者存在 Swift 错误,但希望收到评论。以下单元测试的代码和输出。

代码如下:

extension NSDate {

// creates a NSDate object with time set to 00:00:00 which allows equality checks on dates alone
var asDateOnly: NSDate {
get {
let userCalendar = NSCalendar.currentCalendar()
let dayMonthYearUnits: NSCalendarUnit = .CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear
var dateComponents = userCalendar.components(dayMonthYearUnits, fromDate: self)
dateComponents.timeZone = NSTimeZone(name: "GMT")
// dateComponents.hour = 0
// dateComponents.minute = 0
// dateComponents.second = 0
let result = userCalendar.dateFromComponents(dateComponents)!
return result
}
}

测试函数:

func testRemovingTimeComponentFromRandomNSDateObjectsAlwaysResultsInNSDateSetToMidnight() {
var dates = [NSDate]()
let dateRange = NSDate.timeIntervalSinceReferenceDate()
for var i = 0; i < 30; i++ {
let randomTimeInterval = Double(arc4random_uniform(UInt32(dateRange)))
let date = NSDate(timeIntervalSinceReferenceDate: randomTimeInterval).asDateOnly
let dateStrippedOfTime = date.asDateOnly

// get the hour, minute and second components from the stripped date
let userCalendar = NSCalendar.currentCalendar()
var hourMinuteSecondUnits: NSCalendarUnit = .CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitSecond
var dateComponents = userCalendar.components(hourMinuteSecondUnits, fromDate: dateStrippedOfTime)
dateComponents.timeZone = NSTimeZone(name: "GMT")
XCTAssertTrue((dateComponents.hour == 0) && (dateComponents.minute == 0) && (dateComponents.second == 0), "Time components were not set to zero - \nNSDate: \(date) \nIndex: \(i) H: \(dateComponents.hour) M: \(dateComponents.minute) S: \(dateComponents.second)")
}
}

输出:

testRemovingTimeComponentFromRandomNSDateObjectsAlwaysResultsInNSDateSetToMidnight] : XCTAssertTrue failed - Time components were not set to zero - 
NSDate: 2009-06-19 00:00:00 +0000
Index: 29 H: 1 M: 0 S: 0

最佳答案

我确信您随机创建的测试日期将包含 DST(夏令时)日期,因此会有 1 小时的偏移量——实际上时钟会显示 0:00。


您的代码无论如何都过于复杂,并且在您覆盖它时无法识别时区。

准备:创建到同一天相隔5小时的日期。

var d1 = NSDate()
let cal = NSCalendar.currentCalendar()
d1 = cal.dateBySettingUnit(NSCalendarUnit.CalendarUnitHour, value: 12, ofDate: d1, options: nil)!
d1 = cal.dateBySettingUnit(NSCalendarUnit.CalendarUnitMinute, value: 0, ofDate: d1, options: nil)!

d1 今天中午在用户位置。

let comps = NSDateComponents()
comps.hour = 5;

var d2 = cal.dateByAddingComponents(comps, toDate: d1, options: nil)!

d2 五小时后

比较:此比较将产生相等,因为日期在同一天

let b = cal.compareDate(d1, toDate: d2, toUnitGranularity: NSCalendarUnit.CalendarUnitDay)
if b == .OrderedSame {
println("equal")
} else {
println("not equal")
}

以下将产生不相等,因为日期不在同一小时内

let b = cal.compareDate(d1, toDate: d2, toUnitGranularity: NSCalendarUnit.CalendarUnitHour)
if b == .OrderedSame {
println("equal")
} else {
println("not equal")
}

使用日期格式化程序显示日期,因为它将考虑 DST 和时区。

关于swift - 使用 DateComponent 构造 NSDate 会给出不一致的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30517887/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com