Swift 使用NSDate获取复活节的日期

Swift 使用NSDate获取复活节的日期,swift,nsdate,Swift,Nsdate,我正在开发一个应用程序,需要使用获取国家假日的日期 在下面,我可以得到阵亡将士纪念日: //设置阵亡将士纪念日(5月最后一个星期一)的组件 让memorialDayComps=NSDateComponents() memorialDayComps.weekday=2 纪念日公司月份=5 memorialDayComps.year=当前年份 var mondaysOfMay=[NSDate]() 对于var i=1;我我在GitHub上找到了一个解决方案,该解决方案精确地计算并返回复活节的NSDa

我正在开发一个应用程序,需要使用获取国家假日的日期

在下面,我可以得到阵亡将士纪念日:

//设置阵亡将士纪念日(5月最后一个星期一)的组件
让memorialDayComps=NSDateComponents()
memorialDayComps.weekday=2
纪念日公司月份=5
memorialDayComps.year=当前年份
var mondaysOfMay=[NSDate]()
对于var i=1;我我在GitHub上找到了一个解决方案,该解决方案精确地计算并返回复活节的
NSDate

以下代码是要点所包含的内容:

//匿名格里高利算法后swift中的复活节计算
//也称为Meeus/Jones/Butcher算法
func复活节(Y:Int)->NSDate{
设a=Y%19
设b=Int(楼层(双Y)/100))
设c=Y%100
设d=Int(楼层(双(b)/4))
设e=b%4
设f=Int(楼层(双(b+8)/25))
设g=Int(楼层(双(b-f+1)/3))
设h=(19*a+b-d-g+15)%30
设i=Int(楼层(双(c)/4))
设k=c%4
设L=(32+2*e+2*i-h-k)%7
设m=Int(楼层(双(a+11*h+22*L)/451))
let components=NSDateComponents()
组件。年=Y
月份=整数(楼层(双倍(h+L-7*m+114)/31))
日=((h+L-7*m+114)%31)+1
components.timeZone=NSTimeZone(forSecondsFromGMT:0)
设cal=NSCalendar(日历标识符:NSGregorianCalendar)
从组件返回cal.dateFromComponents(组件)
}
println(复活节(2014))/“2014-04-20 00:00:00+0000”

复活节算法非常有效! 与Swift 4.0和模式匹配一起使用。模式匹配使我更容易根据月、日、工作日、工作日序号添加其他日期

延期日期{
var isUSHoliday:Bool{
让components=Calendar.current.dateComponents([.year、.month、.day、.weekday、.weekdayOrdinal],from:self)
防护装置出租年份=组件。年份,
设month=components.month,
let day=components.day,
设weekday=components.weekday,
让weekdayOrdinal=components.weekdayOrdinal else{return false}
让easterDateComponents=Date.dateComponentsForEaster(年份:年)
设easterMonth:Int=easterDateComponents?月-1
让easterDay:Int=easterDateComponents?天???-1
让memorialDay=日期。日期组件FormmorialDay(年)?。日期???-1
//工作日是星期天==1…星期六==7
//weekdayOrdinal是当月第n个工作日实例
开关(月、日、工作日、工作日序号){
案例(1,1,uu,uu):回归真实//新年快乐
案例(1,0,2,3):返回true//MLK-1月的第三个周一
案例(2,0,2,3):返回真//华盛顿-2月3日星期一
案例(easterMonth,easterDay,u,u):返回真值//复活节-火箭科学计算
案例(5,纪念日):返回真//纪念日
案例(7,4,u,u):返回true//独立日
案例(9,0,2,1):返回true//劳动节-9月的第一个周一
案例(10,0,2,2):返回真//哥伦布日-十月的第二个星期一
案例(11,11,u,u):返回真实//退伍军人日
案例(11,0,5,4):返回真实//感恩节快乐-11月的第四个星期四
案例(12,25,uu,uu):返回真实//节日快乐
案例(12,31,uu,uu):返回真实//除夕夜
默认值:返回false
}
}
静态函数DateComponents FormMorialDay(年份:Int)->DateComponents{
guard let memorialDay=日期。memorialDay(年:年)else{return nil}
返回NSCalendar.current.dateComponents([.year、.month、.day、.weekday、.weekdayOrdinal],from:memorialDay)
}
静态函数纪念日(年份:Int)->日期{
让calendar=calendar.current
var firstMondayJune=DateComponents()
firstMondayJune.month=6
firstMondayJune.weekdayOrdinal=1//1月内的第一个
firstMondayJune.weekday=2//星期一
firstMondayJune.year=年
guard let refDate=calendar.date(从:firstMondayJune)else{return nil}
var timeMachine=DateComponents()
timeMachine.weekOfMonth=-1
返回calendar.date(通过添加:timeMachine,to:refDate)
}
静态函数easterHoliday(年份:Int)->日期{
guard let dateComponents=Date.dateComponentsForEaster(年份:year)else{return nil}
返回Calendar.current.date(起始日期:dateComponents)
}
静态函数dateComponentsForEaster(年份:Int)->DateComponents{
//基于匿名Gregorian算法的复活节计算
//又名Meeus/Jones/Butcher算法
假设a=年份%19
设b=Int(楼层(双(年)/100))
设c=年份%100
设d=Int(楼层(双(b)/4))
设e=b%4
设f=Int(楼层(双(b+8)/25))
设g=Int(楼层(双(b-f+1)/3))
设h=(19*a+b-d-g+15)%30
设i=Int(楼层(双(c)/4))
设k=c%4
设L=(32+2*e+2*i-h-k)%7
设m=Int(楼层(双(a+11*h+22*L)/451))
var dateComponents=dateComponents()
dateComponents.month=Int(楼层(双(h+L-7*m+114)/31))
dateComponents.day=((h+L-7*m+114)%31)+1
dateComponents.year=年
guard let easter=Calendar.current.date(from:dateComponents)else{return nil}//转换为计算工作日,工作日序号
返回Calendar.current.dateComponents([.year、.month、.day、.weekday、.weekdayOrdinal],from:easter)
}
}
Swift 4:

func复活节(Y:Int)->日期{
设a=Y%19
设b=Int(楼层(双Y)/100))
设c=Y%100
L
-(void) easterMonthAndDayForYear: (NSInteger) Y {
        NSInteger a = Y % 19;
        NSInteger b = (int) (floor( ((double)Y) / 100.0));
        NSInteger c = Y % 100;
        NSInteger d = (int)(floor(((double)b) / 4.0));
        NSInteger e = b % 4;
        NSInteger f = (int)(floor(((double)(b+8)) / 25.0));
        NSInteger g = (int)(floor(((double)(b-f+1)) / 3.0));
        NSInteger h = (19*a + b - d - g + 15) % 30;
        NSInteger i = (int)(floor(((double)c) / 4.0));
        NSInteger k = c % 4;
        NSInteger L = (32 + 2*e + 2*i - h - k) % 7;
        NSInteger m = (int)(floor(((double)(a + 11*h + 22*L)) / 451.0));
        NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear |NSCalendarUnitTimeZone  fromDate:[NSDate date]];
        components.year = Y;
        components.month = (int)(floor((double)(h + L - 7*m + 114) / 31.0));
        components.day = ((h + L - 7*m + 114) % 31) + 1;
        components.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];

        self.easterDayCache[@(Y)] = @{@"month": @(components.month), @"day":@(components.day)
};
/// **How ten divisions lead to Easter** *by T. H. O'Beirne, New Scientist, march 30 1961 - Vol. 9,Nr. 228*
func easter(in year: Int) -> (day: Int, month: Int) {
    /// Identify the position of the `year` in a 19-year cycle, to use this later to determine the principal constituent of the changes of full-moon dates from year to year
    let a = year % 19

    /// Take note of the corrections which the Gregorian calendar introduces in century years
    let (b, c) = year.quotientAndRemainder(dividingBy: 100)

    /// Take account of the leap-year exceptions in century years
    let (d, e) = b.quotientAndRemainder(dividingBy: 4)

    /// Provide similarly for the century years auxiliary corrections to the new-moon and full-moon dates
    let g = (8*b + 13) / 25

    /// Determine the number of days between 21 March and the coincident or next full moon, if no special exceptions arise
    let h = (19*a + b - d - g + 15) % 30

    /// Determine the position of the year in the ordinary leap-year cycle of four years
    let (i, k) = c.quotientAndRemainder(dividingBy: 4)

    /// Determine number of days (between 0 and 6) until the Sunday *after* full moon
    let l = (2*e + 2*i - h - k + 32) % 7

    /// The exceptions which make a 29-day month interrupt the regularity of a simpler pattern need here be considered *only* when they transfer the full moon *from a Sunday to a Saturday*: the *Easter date* is unaffected in other cases. When appropriate — 1954 and 1981 are quite rare examples — we have m=1; otherwise m=0 : this permits the necessary correction (failing which the Easter date *would* be 26 April in 1981.
    let m = (a + 11*h + 19*l) / 433

    /// Determine days between March 22 and Easter
    let relativeDayCount = h + l - 7*m

    /// Convert relative day count into absolute month and day index
    let month = (relativeDayCount + 90) / 25
    return (day: (relativeDayCount + 33*month + 19) % 32, month)
}

func easterDate(in year: Int) -> Date {
    let (day, month) = easter(in: year)
    let components = DateComponents(
        timeZone: TimeZone(secondsFromGMT: 0),
        year: year, month: month, day: day
    )
    return Calendar(identifier: .gregorian).date(from: components)!
}