NSDateComponentsFormatter的stringFromDate(_,toDate :)返回nil

时间:2015-02-20 16:37:21

标签: swift nsdate nsdateformatter nsdatecomponents nsdatecomponentsformatter

问题

为什么string为零?

let formatter = NSDateComponentsFormatter()
let referenceDate = NSDate(timeIntervalSinceReferenceDate: 0)
let intervalDate = NSDate(timeInterval: 3628810, sinceDate: referenceDate)
let string = formatter.stringFromDate(referenceDate, toDate: intervalDate)

我期待像" 6w 10s"被退回。

(6周是3,628,800秒。)


尝试排除故障

要进行问题排查,我尝试设置allowedUnits

formatter.allowedUnits = .YearCalendarUnit | .MonthCalendarUnit | .WeekCalendarUnit | .DayCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit

导致此错误:

  

" NSInvalidArgumentException","指定带间隙的位置单位是不明确的,因此不受支持"

我不知道"位置单位"是(在足球之外),我不认为我指的是任何差距。


注释

我使用stringFromTimeInterval() ,因为根据系统的当前日期,它会返回不同的结果。 (即,二月只有一个月的28/29天。)我想从NSDate参考日期计算时间间隔

我正在使用Xcode 6.1.1(6A2008a)。如果有帮助的话,这是Playground屏幕截图:

enter image description here

4 个答案:

答案 0 :(得分:6)

来自headerdoc:

/* Bitmask of units to include. Set to 0 to get the default behavior.
   Note that, especially if the maximum number of units is low, unit
   collapsing is on, or zero dropping is on, not all allowed units may
   actually be used for a given NSDateComponents. Default value is the
   components of the passed-in NSDateComponents object, or years | 
   months | weeks | days | hours | minutes | seconds if passed an
   NSTimeInterval or pair of NSDates.

   Allowed units are:

    NSCalendarUnitYear
    NSCalendarUnitMonth
    NSCalendarUnitWeekOfMonth (used to mean "quantity of weeks")
    NSCalendarUnitDay
    NSCalendarUnitHour
    NSCalendarUnitMinute
    NSCalendarUnitSecond

   Specifying any other NSCalendarUnits will result in an exception.
 */
var allowedUnits: NSCalendarUnit

所以:

let formatter = NSDateComponentsFormatter()
formatter.calendar = NSCalendar.currentCalendar()
formatter.allowedUnits = nil
formatter.allowedUnits |= .CalendarUnitYear
formatter.allowedUnits |= .CalendarUnitMonth
formatter.allowedUnits |= .CalendarUnitWeekOfMonth
formatter.allowedUnits |= .CalendarUnitDay
formatter.allowedUnits |= .CalendarUnitHour
formatter.allowedUnits |= .CalendarUnitMinute
formatter.allowedUnits |= .CalendarUnitSecond

let referenceDate = NSDate(timeIntervalSinceReferenceDate: 0)
let intervalDate = NSDate(timeInterval: 214458810, sinceDate: referenceDate)
let string = formatter.stringFromDate(referenceDate, toDate: intervalDate)
// -> "6y 9m 2w 4d 3:53:30"

当我们在中间省略其中一个时:

formatter.allowedUnits = nil
formatter.allowedUnits |= .CalendarUnitYear
formatter.allowedUnits |= .CalendarUnitMonth
formatter.allowedUnits |= .CalendarUnitWeekOfMonth
formatter.allowedUnits |= .CalendarUnitDay
// formatter.allowedUnits |= .CalendarUnitHour
formatter.allowedUnits |= .CalendarUnitMinute
formatter.allowedUnits |= .CalendarUnitSecond

'Specifying positional units with gaps is ambiguous, and therefore unsupported'错误:)我认为这就是“差距”的意思。

答案 1 :(得分:4)

这对我来说可以摆脱"差距":

formatter.allowedUnits = .DayCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit

答案 2 :(得分:1)

Swift 3.0版本解决此问题。

 let dateFormatted = DateComponentsFormatter()

 dateFormatted.allowedUnits = [NSCalendar.Unit.year, NSCalendar.Unit.month, NSCalendar.Unit.weekOfMonth ,NSCalendar.Unit.day, NSCalendar.Unit.hour, NSCalendar.Unit.minute, NSCalendar.Unit.second]

 let autoFormattedDifference = dateFormatted.string(from: currentDate, to: dateFromTimestamp)

 print("The difference between dates is: \(autoFormattedDifference!)")

现在,区别在于从升序或降序给出allowUnits的所有值。

答案 3 :(得分:1)

未指定单位样式将在Swift 4中引发此错误。

let componentsFormatter = DateComponentsFormatter()
componentsFormatter.unitsStyle = .full // or .spellOut, .short, .brief, .abbreviated, .positional