使用具有较大差异的Datecomponents时崩溃

时间:2017-05-09 17:51:37

标签: ios swift nsdatecomponents

在swift中尝试使用日期组件时,日期之间的间隔很大(例如使用的日期是1979年8月16日到2053年5月11日) 日期组件的代码是

ComponentsforDetail = (Calendar.current as NSCalendar).components([.second], from: FromDateValue!, to: ToValueDate!, options: [])

使用断点我发现thread_exc发生在装配线代码

libswiftFoundation.dylib`static Foundation.DateComponents._unconditionallyBridgeFromObjectiveC (Swift.Optional<__ObjC.NSDateComponents>) -> Foundation.DateComponents:
    0x16cf280 <+0>:  push   {r4, r5, r7, lr}
    0x16cf284 <+4>:  add    r7, sp, #8
    0x16cf288 <+8>:  sub    sp, sp, #4
    0x16cf28c <+12>: mov    r4, r0
    0x16cf290 <+16>: mov    r0, #0
    0x16cf294 <+20>: str    r0, [sp]
    0x16cf298 <+24>: cmp    r4, #0
    0x16cf29c <+28>: beq    0x16cf2dc                 ; <+92>
    0x16cf2a0 <+32>: mov    r0, r4
    0x16cf2a4 <+36>: bl     0x17a42e8                 ; symbol stub for: objc_retain
    0x16cf2a8 <+40>: mov    r1, sp
    0x16cf2ac <+44>: mov    r0, r4
    0x16cf2b0 <+48>: bl     0x174ed80                 ; function signature specialization <Arg[0] = Owned To Guaranteed, Arg[2] = Dead> of static Foundation.DateComponents._conditionallyBridgeFromObjectiveC (__ObjC.NSDateComponents, result : inout Swift.Optional<Foundation.DateComponents>) -> Swift.Bool
    0x16cf2b4 <+52>: mov    r0, r4
    0x16cf2b8 <+56>: bl     0x17a42d8                 ; symbol stub for: objc_release
    0x16cf2bc <+60>: ldr    r5, [sp]
    0x16cf2c0 <+64>: cmp    r5, #0
    0x16cf2c4 <+68>: beq    0x16cf2e0                 ; <+96>
    0x16cf2c8 <+72>: mov    r0, r4
    0x16cf2cc <+76>: bl     0x17a42d8                 ; symbol stub for: objc_release
    0x16cf2d0 <+80>: mov    r0, r5
    0x16cf2d4 <+84>: sub    sp, r7, #8
    0x16cf2d8 <+88>: pop    {r4, r5, r7, pc}
->  0x16cf2dc <+92>: trap   (Here is the breakpoint exception Happening)
    0x16cf2e0 <+96>: trap   

我认为这是整数格式的问题,因为大于68年的任何事情都会导致Datecomponents中的这种崩溃持续数秒 我已经使用Playground来识别游乐场中使用的代码的问题

import UIKit

var str = "Hello, playground"
let dateString1 = "1979-11-28 07:57:20 +0000"
let dateString2 = "2048-11-29 10:59:00 +0000"

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let date1 = formatter.date(from: dateString1)!
let date2 = formatter.date(from: dateString2)!

let calendar = NSCalendar.current
let components1 = (Calendar.current as NSCalendar).components([NSCalendar.Unit.minute], from: date1, to: date2, options: NSCalendar.Options.init(rawValue: 0))
let components2 = (Calendar.current as NSCalendar).components([.second], from: date1, to: date2, options: [])

日期2大于2047年的任何内容都将导致此错误

1 个答案:

答案 0 :(得分:1)

当使用dateComponents Calendar来获取两个日期之间的秒数并且得到的秒数太大而无法符合带符号的32位整数时,似乎会出现问题(2 ^ 31)。

另一种解决方案是使用Date timeIntervalSince来获取两个日期之间的秒数。

您的更新代码变为:

let dateString1 = "1979-11-28 07:57:20 +0000"
let dateString2 = "2048-11-29 10:59:00 +0000"

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let date1 = formatter.date(from: dateString1)!
let date2 = formatter.date(from: dateString2)!

let seconds = date2.timeIntervalSince(date1)
let components1 = Calendar.current.dateComponents([ .minute ], from: date1, to: date2)
let minutes = components1.minute

这会使2177636500为秒,36293941为分钟。