【问题标题】:Swift - NSDate and last week of yearSwift - NSDate 和一年中的最后一周
【发布时间】:2015-10-08 07:10:25
【问题描述】:

我正在制作一个时间表应用程序,并且我有一个方法可以将当前日期增加 1 周,这按预期工作,但是如果一周从 12 月过渡到 1 月,它会额外增加 1 天。

这是我的代码:

func getWeekDates(var date: NSDate) -> [NSDate] {
    var dates: [NSDate] = [NSDate]()
    for var i = 0; i < 5; i++ {
        date = date.dateAtWeekStart() + 1.day - 1.week
        date += i.day
        dates.append(date)
    }
    return dates
}

还有dateAtWeekStart():

func dateAtWeekStart() -> NSDate {
    let flags : NSCalendarUnit = [NSCalendarUnit.Year,NSCalendarUnit.Month ,
        NSCalendarUnit.WeekOfYear,
        NSCalendarUnit.Weekday]
    let components = NSCalendar.currentCalendar().components(flags, fromDate: self)
    components.weekday = 1 // Sunday
    components.hour = self.hour
    components.minute = self.minute
    components.second = self.second
    return NSCalendar.currentCalendar().dateFromComponents(components)!
}

dateAtWeekStart()是NSDate的扩展函数)

我添加 1 天并删除 1 周的原因是因为 dateAtWeekStart 下周日返回,例如 08-10-2015.dateAtWeekStart() 返回 11-10-2015。

所以这正常工作,但是如果我们以今年为例,29-12-2015.dateAtWeekStart() 返回 04-01-2015 而不是 03-01-2016。

顺便说一句,设备上的地区设置为丹麦。

dateAtWeekStart,来自 malcommac 制作的名为 SwiftDate 的帮助器类:https://github.com/malcommac/SwiftDate

更新编辑: 我仍然无法弄清楚如何解决这个问题,我尝试向组件添加年份,如下所示:components.year = self.year,但在返回组件时出于某种原因将年份设置为 2014..

【问题讨论】:

  • 你试过NSCalendar.autoupdatingCurrentCalendar().dateFromComponents(components)!吗?
  • 不,我没试过。刚试了一下,很遗憾,它不起作用。
  • 我认为您可能需要在组件中考虑年份,因为您的标志包含NSCalendarUnit.Year。我怀疑它实际上是在 2015 年的第一个星期日 - 这是 04-01
  • 当没有提供足够的组件来完全指定绝对时间时,日历会使用其选择的默认值 - Apple Doc,这可能会非常不可预测
  • 听起来好像是这样,我试试,谢谢。

标签: ios swift nsdate


【解决方案1】:

dateAtWeekStart() 方法根本不起作用。 [.YearForWeekOfYear, .WeekOfYear] 足以作为日历单位 唯一地确定(一周的开始)。额外的单位可以使 计算未定。你也不能只设置 components.weekday = 1 因为在某些地区星期一 (2) 是第一个 星期几。

所以实际上要容易一些:

extension NSDate {
    func dateAtWeekStart() -> NSDate {
        let cal = NSCalendar.currentCalendar()
        // cal.firstWeekday = 1 // If you insist on Sunday being the first day of the week.
        let flags : NSCalendarUnit = [.YearForWeekOfYear, .WeekOfYear]
        let components = cal.components(flags, fromDate: self)
        return cal.dateFromComponents(components)!
    }
}

这应该适用于所有情况,并给出给定日期的一周开始(午夜)。还有其他方法 可以使用,例如rangeOfUnit()

如果您希望将星期日视为一周的第一天 而不是使用用户的区域设置 那么你必须设置日历的firstWeekday 属性。

将日期添加几天或几周的代码看起来也很可疑。 SwiftDate 项目中Int 的扩展方法对待 一天为 24*60*60 秒。这是不正确的,因为在具有 夏令时,一天可以有 23 或 25 小时的时钟 被调整。将一周添加到日期的正确方法是 再次使用日历组件:

date = cal.dateByAddingUnit(.WeekOfYear, value: 1, toDate: date, options: [])!

Swift 3 更新:

extension Date {
    func dateAtWeekStart() -> Date {
        var cal = Calendar.current
        // cal.firstWeekday = 1 // If you insist on Sunday being the first day of the week.
        let components = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
        return cal.date(from: components)!
    }
}

【讨论】:

  • 令我感到好奇的是,他的设备设置为丹麦语言环境,但他仍在尝试将星期日作为一周的第一天。这让我认为他可能特别想要星期天,但有一点他似乎不明白为什么他必须向后移动一周并增加一天才能到达星期一。所以我认为关于 iOS 的东西不假设周日——无论它是否具有任意的序数值 1——一定是一周中的第一天,这可能是问题的关键。赞成票等。
  • @Tommy:谢谢!该 dateAtWeekStart() 方法实际上来自 SwiftDate 项目。该项目的作者来自罗马,并且(如果我研究正确的话)意大利周从星期一开始。这让我想知道该功能是否已经过测试:)
  • 这行得通,我对处理日期有点陌生,我想它们有时会很混乱,这就是我使用 swiftdate 的原因。 - 实际上我不想让它在星期天回来,我只是想,那是常态。不过,我觉得有些奇怪,如果我使用断点来查看新 dateAtWeekStart 返回的日期,它实际上返回星期日 22.00,但是当我使用 getWeekDates 将它们转换为星期一到星期五时,它在我的收藏视图中有效。我只是觉得这很奇怪,也许你有一个解释:) 如果你需要我澄清就写吧。
  • @Jonathan:那是因为 1) NSDate 是一个绝对时间点,不知道时区,2) print(someDate) 总是使用 GMT 时区(从尾随“+0000”)。要根据您的本地时区打印日期,您必须使用 NSDateFormatter 并将 NSDate 转换为字符串。 – 比较stackoverflow.com/questions/8466744/…
  • @MartinR :哇,这对我帮助很大,谢谢!,我不知道我使用了多少次称为.toUtc() 的方法,因为它增加了 +2 小时的日期,并且有时会弄乱我的代码。
猜你喜欢
  • 2015-04-27
  • 1970-01-01
  • 2021-08-04
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多