简体   繁体   English

如何在Swift 5中获得所选周的第一天

[英]How to get the first day of a selected Week in Swift 5

I have an UIPickerView with 53 weeks and I try to get the first day (Monday) of a selected week. 我有一个53周的UIPickerView ,我尝试获取所选星期的第一天(星期一)。 But every time when I select a week I get the wrong year. 但是每次我选择一个星期时,我都会得到错误的年份。 For example if I select a week lower than the current week (which is week 31 at this time), then I will get the year 2020 instead of 2019. If I select a Week greater than the current Week (for example week 32 of 2019) then I will get 4 August 2019 23:00 instead of 5 August 2019. 例如,如果我选择一个比当前周低的周(此时为第31周),那么我将获得2020年而不是2019年。如果我选​​择的周大于当前周(例如2019年的第32周) ),那么我将获得2019年8月4日23:00而不是2019年8月5日。

Here is the list with the correct week numbers of 2019: https://www.epochconverter.com/weeks/2019 这是具有正确的2019周号的列表: https : //www.epochconverter.com/weeks/2019

Here is my small demo: 这是我的小演示:

https://github.com/tygruletz/FirstDayOfSelectedWeek https://github.com/tygruletz/FirstDayOfSelectedWeek

Here is my code: 这是我的代码:

class ViewController: UIViewController {

    // Interface Links
    @IBOutlet weak var pickerView: UIPickerView!
    @IBOutlet weak var firstMondayLabel: UILabel!

    // Properties
    var weeksArray = [String]()

    //-- Get the number of weeks for current year.
    var numberOfWeeksInYear: Int {
        var calendar = Calendar(identifier: .iso8601)
        calendar.firstWeekday = 2
        let weekRange = calendar.range(of: .weekOfYear,
                                       in: .year,
                                       for: Date())
        return weekRange!.count
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        weeksArray = (1...numberOfWeeksInYear).map { "\($0)" }

        print("Number of weeks in current year: \(numberOfWeeksInYear)")
    }
}

// Functionality for Next Trailer Inspection Cell
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource{

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return weeksArray.count
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return weeksArray[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

        let mondayOfSelectedWeek = Date().dateCorrespondingTo(weekNumber: Int(weeksArray[row]) ?? 0)

        print("1st monday of week \(Int(weeksArray[row]) ?? 0) is: \(mondayOfSelectedWeek ?? Date())")

        firstMondayLabel.text = "\(mondayOfSelectedWeek!)"
    }
}

extension Date {

    func dateCorrespondingTo(weekNumber: Int) -> Date? {
        let thisCalendar = Calendar(identifier: .iso8601)
        return thisCalendar.date(bySetting: .weekOfYear, value: weekNumber, of: self)
    }
}

In your dateCorrespondingTo(weekNumber:) function, you are calleing date(bySetting:...) which is implementation dependent, and currently, when you call it, you set the date to now, and when you select week of year that is in the past, it won't go in the past but will calculate date in the future. dateCorrespondingTo(weekNumber:)函数中,您正在调用date(bySetting:...) ,它依赖于实现,并且当前,当您调用它时,您将日期设置为现在,并且选择了一年中的星期几过去,它不会过去,但会计算将来的日期。

The fact that you are getting August 4, 23:00 is because the date is calculated in the universal time zone, so since your local date is one hour ahead, it recalculates the UTC time, back to your time zone. 之所以得到8月4日23:00的事实是因为日期是在世界时区中计算的,所以由于您的本地日期比世界时区早一小时,因此它会重新计算UTC时间,回到您的时区。 You really got August 5 00:00:00 but in UTC. 您确实是8月5日00:00:00,但使用的是UTC。

Here's a piece of code that will calculate the Monday of the week of the year (notice that iso8601 calendar has the first day of the week set to Sunday so you should use number 2 for the weekday parameter in DateComponents) 这是一段代码,它将计算一年中的一周的星期一(请注意,iso8601日历将一周的第一天设置为星期日,因此您应该在DateComponents中将数字2用作工作日参数)

here's the example based on your code: 这是基于您的代码的示例:

extension Date {

    func dateCorrespondingTo(weekNumber: Int) -> Date? {
        let thisCalendar = Calendar(identifier: .iso8601)

        let year = thisCalendar.component(.year, from: self)

        let dateComponents = DateComponents(calendar: thisCalendar, timeZone: TimeZone(abbreviation: "UTC"), hour: 0, minute: 0, second: 0, nanosecond: 0, weekday: 2, weekOfYear: weekNumber, yearForWeekOfYear: year)
        return thisCalendar.date(from: dateComponents)
    }
}

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

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