【问题标题】:Creating a date with DateComponents使用 DateComponents 创建日期
【发布时间】:2019-07-23 03:00:19
【问题描述】:

我想得到一周的第一天和最后一天。但我的结果与苹果的文档不符: https://developer.apple.com/documentation/foundation/nsdatecomponents/1410442-weekday

这是我的功能:

func startAndEndDateOfWeek(weekOfYearWithYear: (week: Int,year: Int)) -> (start: Date, end: Date) {
    var output = (start: Date.init(), end: Date.init())

    let calendar = Calendar(identifier: .gregorian)
    var firstDayComponents = DateComponents()
    firstDayComponents.weekOfYear = weekOfYearWithYear.week
    firstDayComponents.yearForWeekOfYear = weekOfYearWithYear.year
    firstDayComponents.weekday = 1

    let firstDay = calendar.date(from: firstDayComponents)

    var lastDayComponents = DateComponents()
    lastDayComponents.weekOfYear = weekOfYearWithYear.week
    lastDayComponents.yearForWeekOfYear = weekOfYearWithYear.year
    lastDayComponents.weekday = 2

    let lastDay = calendar.date(from: lastDayComponents)
    output = (start: firstDay!, end: lastDay!)
    return output
}

.weekday = 2 -> 指向星期日而不是 0。

我也想要一整天而不是 16:00。

【问题讨论】:

  • Date 始终以 UTC 格式打印 - 请参阅 stackoverflow.com/questions/39937019/…。您可能处于 GMT+8 时区。
  • 好吧有道理,但你知道为什么用 dayComponents 创建日期不起作用吗?

标签: swift calendar nsdatecomponents


【解决方案1】:

几个观察:

  1. 在公历中,weekday = 1 表示星期日; weekday = 2 表示星期一;等等。您可以查看calendar.maximumRange(of: .weekday) 以获取有效值的范围,您可以查看calendar.weekdaySymbols 以了解这些weekDay 值的含义(例如“Sun”、“Mon”、“Tue”、“Wed” ”、“周四”、“周五”和“周六”)。

  2. 你说:

    我也想要一整天而不是 16:00。

    Date 对象引用了某个时刻。所以它不能代表“一整天”。但它可以代表午夜(您所在时区的午夜可能是 GMT/UTC/Zulu 下午 4 点)。

    您也可以返回一个DateInterval,它确实代表一个时间范围。

    func interval(ofWeek week: Int, in year: Int) -> DateInterval {
        let calendar = Calendar.current
    
        let date = DateComponents(calendar: calendar, weekOfYear: week, yearForWeekOfYear: year).date!
        return calendar.dateInterval(of: .weekOfYear, for: date)!
    }
    

    然后

    let formatter = DateIntervalFormatter()
    formatter.dateStyle = .short
    formatter.timeStyle = .short
    
    let year = Calendar.current.component(.year, from: Date())
    let dateInterval = interval(ofWeek: 2, in: year)
    print(formatter.string(from: dateInterval))
    

    在美国地区,时间间隔从 1 月 6 日开始:

    19 年 1 月 6 日上午 12:00  –  19 年 1 月 13 日上午 12:00

    而在德国语言环境中,间隔从 7 日开始:

    07.01.19, 00:00 – 14.01.19, 00:00

  3. 如果你想要一周的第一天和一周的最后一天的开始,你可以这样做:

    func startAndEndDate(ofWeek week: Int, in year: Int) -> (Date, Date) {
        let date = DateComponents(calendar: calendar, weekOfYear: week, yearForWeekOfYear: year).date!
        let lastDate = calendar.date(byAdding: .day, value: 6, to: date)!
    
        return (date, lastDate)
    }
    

    然后

    let formatter = DateFormatter()
    formatter.dateStyle = .short
    
    let year = Calendar.current.component(.year, from: Date())
    let (start, end) = startAndEndDate(ofWeek: 2, in: year)
    print(formatter.string(from: start), "-", formatter.string(from: end))
    

【讨论】:

  • 设置weekday = weekDayRange?.first (== 1) 没有考虑到在某些地区(如德国),一周从星期一开始。最好将该组件设置为第一个日期,然后通过添加一周减去一天来计算第二个日期。
  • 如果我使用像 Calendar.current 这样的用户当前日历,它不会处理用户区域,对吗?所以基本上我必须处理用户可能使用的所有各种日历?或者更通用的解决方案是什么?
  • @MartinR - 你是对的。我已经相应地更新了我的答案
  • @PaFi - 不,我绝对建议始终使用Calendar.current。如果你不这样做,使用非公历的人会看到非常不寻常的结果。绝对使用非公历和不同的语言环境测试您的代码。
  • 德国用户将看到“07.01.19, 00:00 – 14.01.19, 00:00”。 CalendarDateIntervalFormatter 有一个locale 属性,默认值(可能)是可以在系统首选项中修改的当前语言环境。
猜你喜欢
  • 2018-06-22
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多