【问题标题】:NSDateComponentsFormatter's stringFromDate(_, toDate:) returns nilNSDateComponentsFormatter 的 stringFromDate(_, toDate:) 返回 nil
【发布时间】:2015-04-22 10:04:03
【问题描述】:

问题

为什么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(),因为这将根据系统的当前日期返回不同的结果。 (即,2 月一个月只有 28/29 天。)我想计算时间间隔NSDate 参考日期

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

【问题讨论】:

    标签: swift nsdate nsdateformatter nsdatecomponents nsdatecomponentsformatter


    【解决方案1】:

    来自标题文档:

    /* 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' 错误:) 我认为这就是“差距”的意思。

    【讨论】:

    • 啊,所以是.WeekOfMonth,而不是.Week——这可以解释“差距”错误。
    • 是的,我们不能使用.WeekCalendarUnit,因此被忽略了。这就是我认为的“差距”。
    • 还有一个错误,因为它显然没有这样做:“默认值是......年|月|周|天|小时|分钟|秒如果传递一个NSTimeInterval或一对NSDates。”
    • 在 iOS 12 上跳过 .weekOfMonth 会导致此崩溃。这有效:formatter.allowedUnits = [.year, .month, .weekOfMonth, .day, .hour, .minute, .second]
    【解决方案2】:

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

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

    【讨论】:

    • 那不返回nil(它返回“42d 0:00:10”),但为什么我不能得到周/月/年?
    • stringFromTimeInterval() 使用当前日期作为开始日期返回周/月/年没有问题。
    • 我认为这是一个 API 错误 - 文档讨论了一组默认的允许单位,因此它不应该只是从未配置的调用中返回 nil
    【解决方案3】:

    Swift 45 中未指定单位样式会导致此问题。

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

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

    【讨论】:

      【解决方案4】:

      解决这个问题的 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的所有值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-12
        相关资源
        最近更新 更多