简体   繁体   English

Swift 中具有正确时区的日期范围

[英]Date range with correct TimeZone in Swift

I know there is a lot of questions about time zones and dates but I really having hard time to figure this out.我知道有很多关于时区和日期的问题,但我真的很难弄清楚。

My time zone is GMT+3 (That's what my physical device says)我的时区是 GMT+3(这就是我的物理设备所说的)

I'm trying to get the range of the next week starting from Sunday.我试图从周日开始获得下周的范围。 So it need to be Sep 27 ... Oct 3所以它需要是 9 月 27 日 ... 10 月 3 日

Every night at 09:PM the results that I'm getting is from Sep 28 ... Oct 4. It's stays that way until 03:AM每天晚上 09:PM 我得到的结果是从 9 月 28 日到 10 月 4 日。一直到 03:AM

The current time that I'm writing this question is 2:AM and it's shows me this range from Sep 28.我写这个问题的当前时间是 2:AM,它显示了从 9 月 28 日开始的这个范围。

I made an extension for Date and added this variables (I'm using SwiftDate also).我为Date做了一个扩展并添加了这个变量(我也在使用 SwiftDate)。

var closedRange: ClosedRange<Date> {
        let d = Date() //.timeInterval - Fix the problem until 03:AM
        let calendar = Calendar.autoupdatingCurrent
        let min = calendar.date(byAdding: .day, value: 0, to: d.nextWeekday(.sunday))!
        let max = calendar.date(byAdding: .day, value: 6, to: d.nextWeekday(.sunday))!
        return min...max
    }

If I adding this var to d the date is correct.如果我将此 var 添加到d日期是正确的。 but after 3:AM it's messed up again.但在 3:AM 之后又搞砸了。

var timeInterval: Date{
        var date = self
        date.addTimeInterval(TimeInterval(TimeZone.current.secondsFromGMT(for: self)))
        return date
    }

Later in view:后期来看:

let range = Date().closedRange
    
DatePicker(LocalizedStringKey("Choose day:"), selection: $shift.date, in: range, displayedComponents: .date)

The problem also happens when I get the next week as String or Int.当我将下周作为 String 或 Int 获取时,问题也会发生。 It starts from Sep 28 instead Sep 27 (again depends on my location time)它从 9 月 28 日而不是 9 月 27 日开始(再次取决于我的位置时间)

var nextWeek: [String]{
        
        let d = Date()
        var daysArr = [String]()
        let dateFormat = DateFormatter()
        let calendar = Calendar.autoupdatingCurrent
        let dayOfWeek = calendar.component(.weekday, from: d.nextWeekday(.sunday))
        let weekdays = calendar.range(of: .weekday, in: .weekOfYear, for: d.nextWeekday(.sunday))!
        let days = (weekdays.lowerBound ..< weekdays.upperBound).compactMap { calendar.date(byAdding: .day, value: $0 - dayOfWeek, to: d.nextWeekday(.sunday)) }
        
        dateFormat.dateFormat = DateFormats.format11.rawValue
        
        for d in days{
            daysArr.append(dateFormat.string(from: d))
        }
        
        return daysArr
        
    }

The same problem happens with this array of dates.这个日期数组也会出现同样的问题。

var nextWeekAsDates: [Date]{
        
        let d = Date()
        var daysArr = [Date]()
        let calendar = Calendar.autoupdatingCurrent
        let dayOfWeek = calendar.component(.weekday, from: d.nextWeekday(.sunday))
        let weekdays = calendar.range(of: .weekday, in: .weekOfYear, for: d.nextWeekday(.sunday))!
        let days = (weekdays.lowerBound ..< weekdays.upperBound).compactMap { calendar.date(byAdding: .day, value: $0 - dayOfWeek, to: d.nextWeekday(.sunday)) }
                
        for d in days{
            daysArr.append(d)
        }
        
        return daysArr
        
    }

You can simply get todays component weekOfYear advanced by 1, the yearForWeekOfYear and get the date from those components.您可以简单地将今天的组件 weekOfYear 提前 1,即 yearForWeekOfYear,并从这些组件中获取日期。 That will be the start of the next week.那将是下周的开始。 If you need the end of it you can get the start of the following week which marks the end of it:如果你需要它的结束,你可以得到下一周的开始,这标志着它的结束:

extension Calendar {
    static let gregorian: Calendar = .init(identifier: .gregorian)
}

extension Date {
    func nextWeekOfYear(using calendar: Calendar = .gregorian) -> Int {
        calendar.component(.weekOfYear, from: self) + 1
    }
    func yearForWeekOfYear(using calendar: Calendar = .gregorian) -> Int {
        calendar.component(.yearForWeekOfYear, from: self)
    }
    func startOfNextWeek(using calendar: Calendar = .gregorian) -> Date {
        DateComponents(calendar: calendar, weekOfYear: nextWeekOfYear(using: calendar), yearForWeekOfYear: yearForWeekOfYear(using: calendar)).date!
    }
}

Date().startOfNextWeek()  // "Sep 27, 2020 at 12:00 AM"

If you need a range:如果您需要一个范围:

var range: Range<Date> {
    let min = Date().startOfNextWeek()
    return min..<min.startOfNextWeek()
}

print(range) //  "2020-09-27 03:00:00 +0000..<2020-10-04 03:00:00 +0000\n"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM