2016-03-04 108 views
1

我正在尝试使用NSDateComponentsFormatter来生成用户可读的持续时间字符串。虽然它通常工作得很好,有时候结果是奇怪的(或只是简单的错误):NSDateComponentsFormatter忽略了单位。为什么?

// 22d 23h 15m 34.123s 
let timeInterval: NSTimeInterval = 34.123 + 60.0 * (15.0 + 60.0 * (23.0 + 24.0 * 22.0)) 

let formatter = NSDateComponentsFormatter() 
formatter.allowedUnits = [NSCalendarUnit.Year, NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute, NSCalendarUnit.Second] 
formatter.maximumUnitCount = 2 
formatter.unitsStyle = .Abbreviated 
formatter.zeroFormattingBehavior = .Default 

// expected result:  22d 23h 
// actual result:  23d 16m 
let result = formatter.stringFromTimeInterval(timeInterval) 

它不仅省去小时字段在这个例子中,但它也四舍五入了天的分钟。我会假设一旦这些日子四舍五入,它应该在剩下的几分钟内“用完”。从结果来看,用户会认为持续时间绝对超过23天,而事实上并非如此。

回答

2

基于我做的有限测试,NSDateComponentsFormatter在iOS版本< iOS 9和Mac OS < 10.11中有问题。

我得到了一些日期组件的错误值,它不是一个舍入问题。

见我的问题在此链接:

Getting screwy results from NSDateComponentsFormatter

+0

这是不幸的...和我使用OS X 10.11和iOS 9,但我仍然遇到这个问题。 –

+1

有时NSDateComponentsFormatter将显示比maximumUnitCount更多的值。请参阅https://openradar.appspot.com/26354907。仍然发生在iOS 10中。非常令人失望。 – phatmann

4

认为,关于2016年3月27日夏令许多国家的时间变化。

绝对时间间隔可能与基于日历单位的日历计算不同。

只要有可能,避免与文字数字的日期数学。

NSDateComponentsFormatter文件就其calendar财产

格式化使用这个属性没有自己的固有日历格式值的日历。 例如,格式化程序在格式化NSTimeInterval值时使用此日历。

更新:

又见这个例子中,它会创建一个日期2016年3月27日,增加了通过日期组件添加一天,并计算出间隔

let calendar = NSCalendar.currentCalendar() 
let startDate = calendar.dateWithEra(1, year: 2016, month: 3, day: 27, hour: 0, minute: 0, second: 0, nanosecond: 0)! 
let endDate = calendar.dateByAddingUnit(.Day, value: 1, toDate: startDate, options: [])! 

let formatter = NSDateComponentsFormatter() 
formatter.allowedUnits = [.Hour, .Minute, .Second] 
formatter.unitsStyle = .Abbreviated 

let result = formatter.stringFromDate(startDate, toDate: endDate) 
print(result) // 23h 
+0

在实际代码中,timeInterval当然是使用适当的日历日期进行计算的。为了简洁起见,我只是把它留在这里。 *编辑:*并设置正确的日历。 –

+0

查看可能已更新的答案。 – vadian

+0

这仍然可能是正确的选择,@vadian。显然,'NSDateComponentsFormatter'解释了相对于当前日期和时间的时间间隔(据我所知,这是没有记录的)。也没有办法改变它的'锚'日期。因此,在我看来,当您接近夏令时开关时,结果可能会关闭一个小时。 –