Crash while using Datecomponents having larger dif

2019-02-26 20:15发布

Crashing for large interval between dates while trying to use date components in swift (for example dates used is 16 August 1979 to 11 may 2053) The code for date components is

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

Using breakpoints i found out the thread_exc happens in an assembly line code

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   

I think this is an issue with integer format because anything greater than 68 years is causing this crash in Datecomponents for seconds I've used Playground to identify the issue the code used in playground is

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: [])

Anything for date2 greater than year 2047 will result this error

1条回答
Bombasti
2楼-- · 2019-02-26 20:52

The problem seems to happen when the dateComponents of Calendar is used to get the number of seconds between two dates and the resulting number of seconds is too large to fit in a signed 32-bit integer (2^31).

An alternate solution is to use Date timeIntervalSince to get the number of seconds between two dates.

Your updated code becomes:

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

This gives 2177636500 for seconds and 36293941 for minutes.

查看更多
登录 后发表回答