NSDateComponentsFormatter 的方法 stringFromDate:ToDate: 每秒返回一个不同的值

NSDateComponentsFormatter's method stringFromDate:ToDate: is returning a different value every second

我正在尝试获取今天日期和未来日期之间的天数。 我每秒调用一次:

NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:2025];
[components setMonth:1];
[components setDay:1];

NSDate *currentDate = [NSDate date];
NSDate *futureDate = [[NSCalendar currentCalendar] dateFromComponents:components];

NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorNone;
formatter.allowedUnits = NSCalendarUnitDay;
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleAbbreviated;
NSString *remainingDaysAsString = [formatter stringFromDate:currentDate toDate:futureDate];

我每秒打印一次变量 remainingDaysAsString,它总是相差一天。

3,551d
3,551d
3,550d
3,550d
3,551d
3,550d
3,551d

有没有人经历过类似的事情?这看起来像 class 的错误吗?

我不知道你描述的问题,只是想让你知道另一种方法。

NSDate * date1; 
NSDate * date2;
//assuming both vars contain a date
NSTimeInterval duration = [date2 timeIntervalSince1970] - [date1 timeIntervalSince1970];
NSLog("@days between %@ and %@: %f", date1, date2, duration / (24 * 60 * 60));

这很奇怪,看起来像一个错误。 NSDateComponentsFormatter 的结果是正确的(在我的测试中)如果你指定 所有单位精确到秒:

formatter.allowedUnits = NSCalendarUnitDay + NSCalendarUnitHour + NSCalendarUnitMinute  + NSCalendarUnitSecond;

获取两个日期之间的天数的更简单可靠的方法是

NSDateComponents *comp = [[NSCalendar currentCalendar] components:NSCalendarUnitDay
                                                      fromDate:currentDate
                                                        toDate:futureDate
                                                       options:0];
NSInteger days = comp.day;

我遇到了同样的问题:

let fmt1 = NSDateComponentsFormatter()

fmt1.allowedUnits = .CalendarUnitYear |
    .CalendarUnitMonth |
    .CalendarUnitDay

let dc1 = NSDateComponents()
dc1.month = 1
dc1.day = 15

// This occasionally outputs "1 month, 14 days" instead of
// "1 month, 15 days" when the formatter is constrained to
// years, months and days. If formatter is allowed to use
// all units, the output is "1 month, 14 days, 23 hours,
// 59 minutes, 59 seconds".
fmt1.stringFromDateComponents(dc1)

这可以通过指定一个正的秒数并将其与 限制允许的单位 and/or 将格式化程序参数 maximumUnitCount 设置为固定值:

let fmt2 = NSDateComponentsFormatter()

fmt2.allowedUnits = .CalendarUnitYear |
    .CalendarUnitMonth |
    .CalendarUnitDay

fmt2.maximumUnitCount = 2
fmt2.collapsesLargestUnit = true

let dc2 = NSDateComponents()
dc2.month = 1
dc2.day = 15
dc2.second = 10

// This always outputs "1 month, 15 days"
fmt2.stringFromDateComponents(dc2)

因此,在您的情况下,只需将正数的秒数分配给 NSDateComponents:

[components setYear:2025];
[components setMonth:1];
[components setDay:1];
[components setSecond:10];

这将防止舍入错误。