双周工资单频率的开始日期/结束日期 - Swift

Posted

技术标签:

【中文标题】双周工资单频率的开始日期/结束日期 - Swift【英文标题】:Start date/end date for biweekly payroll frequency - Swift 【发布时间】:2020-11-26 01:04:35 【问题描述】:

我必须提供特定工资单频率周期的时间跟踪摘要:每月、每周、每两周一次。我确实找到了一种方法来获取当前一周或当前月份的开始日期和结束日期。

var startOfMonth: Date? 
    let components = Calendar.current.dateComponents([.year, .month], from: startOfDay)
    return Calendar.current.date(from: components)


var endOfMonth: Date? 
    guard let startOfTheMonth = startOfMonth else  return nil 
    var components = DateComponents()
    components.month = 1
    components.second = -1
    return Calendar.current.date(byAdding: components, to: startOfTheMonth)

但是我怎样才能获得当前双周期间的这些日期?

我假设双周期(每年 26 次薪水)是自今年年初以来每两周一次:例如。第一个双周是2020年的1-2周是1.01.20-12.01.20;第 24 个双周是 47-48 周是 16.11.20-29.11.20,最后第 26 个双周是 51-53 周是 14.12.20-31.12.20。

编辑:

根据@Leo Dabus 的回答,我设法获得了 startOfBiweek 和 endOfBiweek。谢谢!

var startOfBiweek: Date? 
    let biweekIntervals = biweekIntervalsInSameYear(using: .iso8601)
    return biweekIntervals.first(where:  $0.contains(self))?.start


var endOfBiweek: Date? 
    let biweekIntervals = biweekIntervalsInSameYear(using: .iso8601)
    return biweekIntervals.first(where:  $0.contains(self))?.end

【问题讨论】:

与您的问题无关,但您不需要 startOfDay 来获取 startOfMonth。关于 endOfMonth,如果您使用日期范围,则无需减去一秒。下个月开始时该月结束 @LeoDabus 1. 你能给我举例说明基于日期范围的月初/月底吗? 2. AFAIK 双周付款频率为一年 26 次付款。我相信每年的第一周和最后一周都会有问题。 您希望您的一周总是从星期一开始吗? 是的。开始 - 星期一,结束 - 星期日 【参考方案1】:

我不知道是否有更简单的方法来完成您想要的,但这就是我想出的。首先,我在同一年得到所有的日子。然后我创建一个包含 26 个子数组的数组,每 2 周分组一次。然后我使用每个子数组的第一个和最后一个日期创建一个日期间隔数组。

extension Calendar 
    static let iso8601 = Calendar(identifier: .iso8601)

extension Date 
    func dayAfter(using calendar: Calendar = .current) -> Date 
        calendar.date(byAdding: .day, value: 1, to: noon(using: calendar))!
    
    func noon(using calendar: Calendar = .current) -> Date  
        calendar.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
    
    func startOfNextDay(using calendar: Calendar = .current) -> Date 
        calendar.startOfDay(for: dayAfter(using: calendar))
    
    func lastSecondOfDay(using calendar: Calendar = .current) -> Date 
        calendar.date(byAdding: DateComponents(second: -1), to: calendar.startOfDay(for: dayAfter(using: calendar)))!
    
    func weekOfYear(using calendar: Calendar = .current) -> Int  calendar.component(.weekOfYear, from: self) 
    func year(using calendar: Calendar = .current) -> Int  calendar.component(.year, from: self) 
    func month(using calendar: Calendar = .current) -> Int  calendar.component(.month, from: self) 
    func allDaysInSameYear(using calendar: Calendar = .current) -> [Date] 
        calendar.range(of: .day, in: .year, for: self)!.map 
            DateComponents(calendar: calendar,year: year(using: calendar), day: $0).date!
        
    
    func biweeksInSameYear(using calendar: Calendar = .current) -> [[Date]] 
        allDaysInSameYear(using: calendar).reduce(into: .init(repeating: [], count: 26)) 
            let weekOfYear = $1.weekOfYear(using: calendar)-1
            let index = weekOfYear > 51 ? 25 : weekOfYear / 2
            $0[index].append($1)
        
    
    func biweekIntervalsInSameYear(using calendar: Calendar = .current) -> [DateInterval] 
        biweeksInSameYear(using: calendar).map 
            DateInterval(start: $0.first!, end: $0.last!.lastSecondOfDay(using: calendar))
        
    


let biweekIntervals = Date().biweekIntervalsInSameYear(using: .iso8601)
for interval in biweekIntervals 
    print(interval.start.description(with: .current), interval.end.description(with: .current), terminator: "\n")
 

这将打印:

2020 年 1 月 1 日星期三 00:00:00 2020 年 1 月 12 日星期日 23:59:59 2020 年 1 月 13 日星期一 00:00:00 2020 年 1 月 26 日星期日 23:59:59 2020 年 1 月 27 日星期一 00:00:00 2020 年 2 月 9 日星期日 23:59:59 2020 年 2 月 10 日星期一 00:00:00 2020 年 2 月 23 日星期日 23:59:59 2020 年 2 月 24 日星期一 00:00:00 2020 年 3 月 8 日星期日 23:59:59 2020 年 3 月 9 日星期一 00:00:00 2020 年 3 月 22 日星期日 23:59:59 2020 年 3 月 23 日星期一 00:00:00 2020 年 4 月 5 日星期日 23:59:59 2020 年 4 月 6 日星期一 00:00:00 2020 年 4 月 19 日星期日 23:59:59 2020 年 4 月 20 日星期一 00:00:00 2020 年 5 月 3 日星期日 23:59:59 2020 年 5 月 4 日星期一 00:00:00 2020 年 5 月 17 日星期日 23:59:59 2020 年 5 月 18 日星期一 00:00:00 2020 年 5 月 31 日星期日 23:59:59 2020 年 6 月 1 日星期一 00:00:00 2020 年 6 月 14 日星期日 23:59:59 2020 年 6 月 15 日星期一 00:00:00 2020 年 6 月 28 日星期日 23:59:59 2020 年 6 月 29 日星期一 00:00:00 2020 年 7 月 12 日星期日 23:59:59 2020 年 7 月 13 日星期一 00:00:00 2020 年 7 月 26 日星期日 23:59:59 2020 年 7 月 27 日星期一 00:00:00 2020 年 8 月 9 日星期日 23:59:59 2020 年 8 月 10 日星期一 00:00:00 2020 年 8 月 23 日星期日 23:59:59 2020 年 8 月 24 日星期一 00:00:00 2020 年 9 月 6 日星期日 23:59:59 2020 年 9 月 7 日星期一 00:00:00 2020 年 9 月 20 日星期日 23:59:59 2020 年 9 月 21 日星期一 00:00:00 2020 年 10 月 4 日星期日 23:59:59 2020 年 10 月 5 日星期一 00:00:00 2020 年 10 月 18 日星期日 23:59:59 2020 年 10 月 19 日星期一 00:00:00 2020 年 11 月 1 日星期日 23:59:59 2020 年 11 月 2 日星期一 00:00:00 2020 年 11 月 15 日星期日 23:59:59 2020 年 11 月 16 日星期一 00:00:00 2020 年 11 月 29 日星期日 23:59:59 2020 年 11 月 30 日星期一 00:00:00 2020 年 12 月 13 日星期日 23:59:59 2020 年 12 月 14 日星期一 00:00:00 2020 年 12 月 31 日星期四 23:59:59



另一种方法,这个方法似乎更短,但我建议进一步测试:

extension Calendar 
    static let iso8601 = Calendar(identifier: .iso8601)

extension Date 
    func startOfYear(using calendar: Calendar = .current) -> Date 
        calendar.dateComponents([.calendar,.year], from: self).date!
    
    func endOfYear(using calendar: Calendar = .current) -> Date 
        startOfYear(using: calendar).adding(.init(year: 1, second: -1))!
    
    func adding(_ components: DateComponents, wrappingComponents: Bool = false, using calendar: Calendar = .current) -> Date? 
        calendar.date(byAdding: components, to: self)
    
    func yearForWeekOfYear(using calendar: Calendar = .current) -> Int  
        calendar.component(.yearForWeekOfYear, from: self)
    
    func biweekIntervalsInSameYear(using calendar: Calendar = .current) -> [DateInterval] 
        let date = DateComponents(calendar: .iso8601, weekOfYear: 1, yearForWeekOfYear: yearForWeekOfYear(using: .iso8601)).date!
        var intervals: [DateInterval] = [.init(start: startOfYear(using: .iso8601), end: date.adding( .init(second: -1, weekOfYear: 2), using: calendar)!)]
        var weekOfYear = 3
        while let start = Calendar.iso8601.nextDate(after: date, matching: DateComponents(weekOfYear: weekOfYear), matchingPolicy: .strict) 
            if intervals.count < 25 
                intervals.append(.init(start: start, end: start.adding( .init(second: -1, weekOfYear: 2), using: calendar)!))  else if intervals.count == 25 
                    intervals.append(.init(start: start, end: start.endOfYear(using: .iso8601)))
            
            weekOfYear += 2
        
        return  intervals
    

【讨论】:

非常感谢您的回答。这是可以解决我的问题的东西。但如果时区是 CET,它似乎对我不起作用。第一个间隔是 2019-12-31 23:00:00 +0000 到 2020-12-31 22:59:59 +0000,其余的都搞砸了。第二个是 2020-01-11 23:00:00 +0000 到 2020-01-25 22:59:59 +0000 @vandermesis 它适用于任何时区。能详细点吗? 您在打印日期吗?它将始终显示 UTC 时区 (+0000) 您使用interval.start.description(with: .current) 打印了该年的所有间隔及其打印正确日期。但是,如果我想获得当前的双周 DateInterval 来获取开始和结束日期,它会给我错误的日期。这就是我想要做的:print(biweekIntervals.first(where: $0.contains(Date()))) 返回2020-11-15 23:00:00 +0000 to 2020-11-29 22:59:59 +0000 这是不正确的。 我很确定它是正确的。 +0000 表示 UTC。日期没有时区,它只是一个时间点。您需要使用DateFormatter 来显示日期的当前时区表示。

以上是关于双周工资单频率的开始日期/结束日期 - Swift的主要内容,如果未能解决你的问题,请参考以下文章

Swift:将开始和结束日期格式化为单个字符串

如何在swift 3中为日期添加天数

评估两个日期之间的工资的功能,按比例应用于部分月份

MS ACCESS 中的 VBA 调度算法

Postgresql 生成日期系列(性能)

结束日期不能小于开始日期啥意思