NSDateComponents Formatter string From Date(to, toDate:) returns 无

NSDateComponentsFormatter's stringFromDate(_, toDate:) returns nil

问题

为什么 string 为零?

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

我希望 returned 像“6w 10s”这样的字符串。

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


已尝试解决问题

为了排除故障,我尝试设置 allowedUnits:

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

导致此错误的结果:

"NSInvalidArgumentException", "Specifying positional units with gaps is ambiguous, and therefore unsupported"

我不知道 "positional unit" 是什么(足球之外),而且我不认为我在指定任何差距。


注释

使用stringFromTimeInterval(),因为根据系统的当前日期,return会产生不同的结果。 (即,2 月一个月只有 28/29 天。)我想从 NSDate 参考日期 .

计算时间间隔

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

这对我有用,可以摆脱 "gaps":

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

来自标题文档:

/* 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'错误:) 那就是"gap"的意思,我想。

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 的所有值。

不指定单位样式将导致 Swift 45.

let componentsFormatter = DateComponentsFormatter()
componentsFormatter.unitsStyle = .full

其他单位样式:.spellOut.short.brief.abbreviated.positional