iOS Calendar.ordinality(of:in:for:) 时代月份的错误结果

iOS Calendar.ordinality(of:in:for:) wrong results for month in era

我不确定我是不是没有领会这里的东西还是 iOS SDK 问题:

问题: 我需要获得与当前月份的月份差值(例如:上个月为 -1)。任何选定月份的第一天和第二天除外的任何一天的下线工作。

我认为最初可能是我没有考虑的某种时区或日历方面,但简化了问题(例如,仅使用 UTC),获取当前时代的月份序号,用于 2 个不同的日期,一个在 1 日(或 2020 年 9 月的第 2 次)以及第 3 次,我得到了不同的结果。

    var calendar = Calendar.current
    let timezone = TimeZone(secondsFromGMT: 0)!
    calendar.timeZone = timezone
    
    
    let dateMonthFirst = calendar.date(from: DateComponents(calendar: calendar, timeZone: timezone, year: 2020, month: 9, day: 1))!
    // let dateMonthFirst = Date(timeIntervalSince1970: 1598918400) // same using directly timestamp for sept 1st
    let ordinalityFirst = calendar.ordinality(of: .month, in: .era, for: dateMonthFirst)!
    
    
    let dateMonthThird = calendar.date(from: DateComponents(calendar: calendar, timeZone: timezone, year: 2020, month: 9, day: 3))!
    // let dateMonthThird = Date(timeIntervalSince1970: 1599091200) // same using directly timestamp for sept 3rd
    let ordinalityThird = calendar.ordinality(of: .month, in: .era, for: dateMonthThird)!
    
    
    print("1st of month ordinality: \(ordinalityFirst)")
    print("3rd of month ordinality: \(ordinalityThird)")
    print("MONTHS AGO: \(ordinalityThird - ordinalityFirst)")

结果总是

1st of month ordinality: 24236
3rd of month ordinality: 24237
MONTHS AGO: 1

两者的预期结果都应该是 24237

我是不是漏掉了什么?

注意 (1):使用该月的第二天可以获得相同的“错误”结果,因此我将排除时区问题。

注(2):出于与1相同的原因,我怀疑它也是由于这个问题中显示的日历对齐的一些影响:

问题是因为您使用 era 而不是 year。一旦将 in 的输入更改为 .year,您就会得到预期的结果。也不需要设置 TimeZone,尤其是不需要设置 calendar.locale = Locale.current,因为无论如何这是 Calendar.current.locale 的默认值。

let calendar = Calendar.current    

let dateMonthFirst = calendar.date(from: DateComponents(calendar: calendar, year: 2020, month: 9, day: 1))!
// let dateMonthFirst = Date(timeIntervalSince1970: 1598918400) // same using directly timestamp for sept 1st
let ordinalityFirst = calendar.ordinality(of: .month, in: .year, for: dateMonthFirst)!


let dateMonthThird = calendar.date(from: DateComponents(calendar: calendar, year: 2020, month: 9, day: 3))!
// let dateMonthThird = Date(timeIntervalSince1970: 1599091200) // same using directly timestamp for sept 3rd
let ordinalityThird = calendar.ordinality(of: .month, in: .year, for: dateMonthThird)!


print("1st of month ordinality: \(ordinalityFirst)")
print("3rd of month ordinality: \(ordinalityThird)")
print("MONTHS AGO: \(ordinalityThird - ordinalityFirst)")

但是,如果您只需要 2 Date 之间的月差,则有一个更简单的解决方案:您只需使用 calendar.dateComponents(_:from:to:).

calendar.dateComponents([.month], from: dateMonthFirst, to: dateMonthThird).month! // 0

即使你们的日期在不同的年份,这也会给你正确的答案。

let thisSept = calendar.date(from: DateComponents(calendar: calendar, year: 2020, month: 9, day: 3))!
let nextAug = calendar.date(from: DateComponents(calendar: calendar, year: 2021, month: 8, day: 3))!
calendar.dateComponents([.month], from: thisSept, to: nextAug).month! // 11