【问题标题】:iOS Calendar.ordinality(of:in:for:) wrong results for month in eraiOS Calendar.ordinality(of:in:for:) 时代月份的错误结果
【发布时间】:2020-09-14 21:44:19
【问题描述】:

我不确定我是否没有掌握这里的某些东西,或者这是一个 iOS SDK 问题:

问题:我需要获取当前月份的月差(例如:上个月的 -1)。除任何选定月份的第一天和第二天外,任何一天都可以进行线下工作。

我最初认为可能是某种我没有考虑的时区或日历方面,但简化了问题(例如,仅使用 UTC),在当前时代为 2 个不同的日期获取月份顺序,一个在 1 日(或 2 日) ) 从 2020 年 9 月到 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 相同的原因,我怀疑它也是由于此问题中显示的日历对齐的一些影响:https://stackoverflow.com/a/41864214/691977

【问题讨论】:

  • 尝试使用年份而不是时代。顺便说一句,不需要弄乱时区
  • 你只需要得到两个日期之间的月差吗?从这两个日期获取每月的第一天并获得它们之间的差异会容易得多。
  • 谢谢,是的,我考虑过使用年份,但它会使非常复杂的代码库上的计算更加复杂,(我们需要跨越数月的范围和日期操作),如果可能的话,我想避免。此外,这个时代已经几乎无处不在,如果有需要考虑的问题,很高兴知道

标签: ios swift calendar


【解决方案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 个Dates 之间的月差,有一个更简单的解决方案:您只需要使用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

【讨论】:

  • DateComponents(calendar: .current, year: 2020, month: 9, day: 1).date!
  • 谢谢大卫,很遗憾,请参阅我在问题中的评论,因为这不是我需要的答案(很抱歉,语言环境是剩余的,正在清理)
  • @jalone 检查我编辑的答案,第二个解决方案应该是您更新问题的正确答案。
  • @jalone 这绝对是您处理问题的方式。忘记使用时代。正如我所提到的,我只会得到当月的第一天,然后得到日期之间的月差。如果您特别偏执,请使用中午。 Calendar.current.dateComponents([.month], from: DateComponents(calendar: .current, year: 2020, month: 9, day: 3, hour: 12).date!, to: DateComponents(calendar: .current, year: 2021, month: 8, day: 3, hour: 12).date!).month! // 11省略一天就可以使用当月的第一天
  • 谢谢。我会等待关于时代的全面答案,我会接受你的答案
猜你喜欢
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多