开发者

List of all American holidays as NSDates

开发者 https://www.devze.com 2023-01-27 19:15 出处:网络
I\'m seeking a way to get all American ho开发者_高级运维lidays as an array of NSDates. Is there a way to implement that?If you only want US federal Holidays, I wrote this method.You could use these te

I'm seeking a way to get all American ho开发者_高级运维lidays as an array of NSDates. Is there a way to implement that?


If you only want US federal Holidays, I wrote this method. You could use these techniques to calculate any holiday though.

-(NSArray *)getUSHolidyas{
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy";

    NSString *year = [formatter stringFromDate:[NSDate date]];
    formatter.dateFormat = @"M/d/yyyy";

    //Constant Holidays
    NSDate *newYearsDay = [formatter dateFromString:[NSString stringWithFormat:@"1/1/%@",year]]; //Use next year for the case where we are adding days near end of december.
    NSDate *indDay = [formatter dateFromString:[NSString stringWithFormat:@"7/4/%@",year]];
    NSDate *vetDay = [formatter dateFromString:[NSString stringWithFormat:@"11/11/%@",year]];
    NSDate *xmasDay = [formatter dateFromString:[NSString stringWithFormat:@"12/25/%@",year]];


    //Variable Holidays
    NSInteger currentYearInt = [[[NSCalendar currentCalendar]
                                 components:NSYearCalendarUnit fromDate:[NSDate date]] year];

    NSDate *mlkDay = [self getTheNth:3 occurrenceOfDay:2 inMonth:1 forYear:currentYearInt];
    NSDate *presDay = [self getTheNth:3 occurrenceOfDay:2 inMonth:2 forYear:currentYearInt];
    NSDate *memDay = [self getTheNth:5 occurrenceOfDay:2 inMonth:5 forYear:currentYearInt]; // Let's see if there are 5 Mondays in May
    NSInteger month = [[[NSCalendar currentCalendar] components:NSYearCalendarUnit fromDate:memDay] month];
    if (month > 5) { //Check that we are still in May
        memDay = [self getTheNth:4 occurrenceOfDay:2 inMonth:5 forYear:currentYearInt];
    }
    NSDate *labDay = [self getTheNth:1 occurrenceOfDay:2 inMonth:9 forYear:currentYearInt];
    NSDate *colDay = [self getTheNth:2 occurrenceOfDay:2 inMonth:10 forYear:currentYearInt];
    NSDate *thanksDay = [self getTheNth:4 occurrenceOfDay:5 inMonth:11 forYear:currentYearInt];

    return @[newYearsDay,mlkDay,presDay,memDay,indDay,labDay,colDay,vetDay,thanksDay,xmasDay];
}

-(NSDate *)getTheNth:(NSInteger)n occurrenceOfDay:(NSInteger)day inMonth:(NSInteger)month forYear:(NSInteger)year{

    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];

    dateComponents.year = year;
    dateComponents.month = month;
    dateComponents.weekday = day; // sunday is 1, monday is 2, ...
    dateComponents.weekdayOrdinal = n; // this means, the first of whatever weekday you specified
    return [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
}


Swift 4: Check this link for getting the US Holiday Dates for easter and memorial day. Using NSDate to get date for Easter

I edited the above link code add some more Holidays:

extension Date {
var isUSHoliday: Bool {
    let components = Calendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: self)
    guard let year = components.year,
        let month = components.month,
        let day = components.day,
        let weekday = components.weekday,
        let weekdayOrdinal = components.weekdayOrdinal else { return false }
    
    let easterDateComponents = Date.dateComponentsForEaster(year: year)
    let easterMonth: Int = easterDateComponents?.month ?? -1
    let easterDay: Int = easterDateComponents?.day ?? -1
    let memorialDay = Date.dateComponentsForMemorialDay(year: year)?.day ?? -1
    
    // weekday is Sunday==1 ... Saturday==7
    // weekdayOrdinal is nth instance of weekday in month
    
    switch (month, day, weekday, weekdayOrdinal) {
    case (1, 1, _, _): return true                      // Happy New Years
    case (1, _, 2, 3): return true                      // Martin Luther King - 3rd Mon in Jan
    case (2, 14, _, _): return true                     // Valentine day - 14th in Feb
    case (2, _, 2, 3): return true                      // Washington's Birthday - 3rd Mon in Feb
    case (3, 17, _, _): return true                     // Saint Patrick's Day - 17th Mar
    case (easterMonth, easterDay, _, _): return true    // Easter - rocket science calculation
    case (5, _, 1, 2): return true                      // Mothers day - 2nd Sun in May
    case (5, memorialDay, _, _): return true            // Memorial Day
    case (5, _, 1, 3): return true                      // Fathers day - 3rd Sun in May
    case (7, 4, _, _): return true                      // Independence Day - 4th July
    case (9, _, 2, 1): return true                      // Labor Day - 1st Mon in Sept
    case (10, _, 2, 2): return true                     // Columbus Day - 2nd Mon in Oct
    case (10, 31, _, _): return true                    // Halloween Day - 31st Oct
    case (11, 11, _, _): return true                    // Veterans Day  - 11th Nov
    case (11, _, 5, 4): return true                     // Happy Thanksgiving - 4th Thurs in Nov
    case (12, 25, _, _): return true                    // Christmas/Happy Holiday
    case (12, 31, _, _): return true                    // New years Eve
    default: return false
    }
    
}
//New Year
static func newYearDay(year: Int) -> Date? {
    var firstDayJan = DateComponents()
    firstDayJan.month = 1 // 1st Month
    firstDayJan.day  = 1  // 1st Day
    firstDayJan.year = year
    return Calendar.current.date(from: firstDayJan)
}
// Martin Luther King Jr Day
static func martinLKDay(year: Int) -> Date? {
    var thirdMonJan = DateComponents()
    thirdMonJan.month = 1 //1 month
    thirdMonJan.weekday  = 2 // Monday
    thirdMonJan.weekdayOrdinal = 3 //3rd week
    thirdMonJan.year = year
    return Calendar.current.date(from: thirdMonJan)
}
//Valentine Day
static func valentineDay(year: Int) -> Date? {
    var firstDayFeb = DateComponents()
    firstDayFeb.month = 2
    firstDayFeb.day  = 14
    firstDayFeb.year = year
    return Calendar.current.date(from: firstDayFeb)
}
//Washington's Birthday
static func washingtonBDay(year: Int) -> Date? {
    var thirdMonFeb = DateComponents()
    thirdMonFeb.month = 2 //month Feb
    thirdMonFeb.weekday  = 2 // Monday
    thirdMonFeb.weekdayOrdinal = 3 //3rd week
    thirdMonFeb.year = year
    return Calendar.current.date(from: thirdMonFeb)
}
//Saint Patrick's Day
static func stPatrickDay(year: Int) -> Date? {
    var seventeenthMar = DateComponents()
    seventeenthMar.month = 3
    seventeenthMar.day  = 17
    seventeenthMar.year = year
    return Calendar.current.date(from: seventeenthMar)
}
//Easter
static func easterHoliday(year: Int) -> Date? {
    guard let dateComponents = Date.dateComponentsForEaster(year: year) else { return nil }
    return Calendar.current.date(from: dateComponents)
}

static func dateComponentsForEaster(year: Int) -> DateComponents? {
    // Easter calculation from Anonymous Gregorian algorithm
    // AKA Meeus/Jones/Butcher algorithm
    let a = year % 19
    let b = Int(floor(Double(year) / 100))
    let c = year % 100
    let d = Int(floor(Double(b) / 4))
    let e = b % 4
    let f = Int(floor(Double(b+8) / 25))
    let g = Int(floor(Double(b-f+1) / 3))
    let h = (19*a + b - d - g + 15) % 30
    let i = Int(floor(Double(c) / 4))
    let k = c % 4
    let L = (32 + 2*e + 2*i - h - k) % 7
    let m = Int(floor(Double(a + 11*h + 22*L) / 451))
    var dateComponents = DateComponents()
    dateComponents.month = Int(floor(Double(h + L - 7*m + 114) / 31))
    dateComponents.day = ((h + L - 7*m + 114) % 31) + 1
    dateComponents.year = year
    guard let easter = Calendar.current.date(from: dateComponents) else { return nil } // Convert to calculate weekday, weekdayOrdinal
    return Calendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: easter)
}
//Mother's Days
static func mothersDay(year: Int) -> Date? {
    var secondSunMay = DateComponents()
    secondSunMay.month = 5
    secondSunMay.weekday = 1
    secondSunMay.weekdayOrdinal = 2
    secondSunMay.year = year
    return Calendar.current.date(from: secondSunMay)
}

//Memorial Day
static func dateComponentsForMemorialDay(year: Int) -> DateComponents? {
    guard let memorialDay = Date.memorialDay(year: year) else { return nil }
    return NSCalendar.current.dateComponents([.year, .month, .day, .weekday, .weekdayOrdinal], from: memorialDay)
}
static func memorialDay(year: Int) -> Date? {
    let calendar = Calendar.current
    var firstMondayJune = DateComponents()
    firstMondayJune.month = 6
    firstMondayJune.weekdayOrdinal = 1  // 1st in month
    firstMondayJune.weekday = 2 // Monday
    firstMondayJune.year = year
    guard let refDate = calendar.date(from: firstMondayJune) else { return nil }
    var timeMachine = DateComponents()
    timeMachine.weekOfMonth = -1
    return calendar.date(byAdding: timeMachine, to: refDate)
}
//Fathers Day
static func fathersDay(year: Int) -> Date? {
    var thirdSunJun = DateComponents()
    thirdSunJun.month = 6
    thirdSunJun.weekday = 1
    thirdSunJun.weekdayOrdinal = 3
    thirdSunJun.year = year
    return Calendar.current.date(from: thirdSunJun)
}

//Independence Day
static func independenceDay(year: Int) -> Date? {
    var fourthJuly = DateComponents()
    fourthJuly.month = 7
    fourthJuly.day = 4
    fourthJuly.year = year
    return Calendar.current.date(from: fourthJuly)
}
//Labor Day
static func laborDay(year: Int) -> Date? {
    var firstSunSep = DateComponents()
    firstSunSep.month = 9
    firstSunSep.weekday = 2
    firstSunSep.weekdayOrdinal = 1
    firstSunSep.year = year
    return Calendar.current.date(from: firstSunSep)
}
//Columbus Day
static func columbusDay(year: Int) -> Date? {
    var firstSunSep = DateComponents()
    firstSunSep.month = 10
    firstSunSep.weekday = 2
    firstSunSep.weekdayOrdinal = 2
    firstSunSep.year = year
    return Calendar.current.date(from: firstSunSep)
}
//Halloween
static func halloweenDay(year: Int) -> Date? {
    var thirtyFirstOct = DateComponents()
    thirtyFirstOct.month = 10
    thirtyFirstOct.day = 31
    thirtyFirstOct.year = year
    return Calendar.current.date(from: thirtyFirstOct)
}

//Veterans
static func veteransDay(year: Int) -> Date? {
    var eleventhNov = DateComponents()
    eleventhNov.month = 11
    eleventhNov.day = 11
    eleventhNov.year = year
    return Calendar.current.date(from: eleventhNov)
}
//Thanks Giving Day
static func thanksGivingDay(year: Int) -> Date? {
    var fourthThuNov = DateComponents()
    fourthThuNov.month = 11
    fourthThuNov.weekday = 5
    fourthThuNov.weekdayOrdinal = 4
    fourthThuNov.year = year
    return Calendar.current.date(from: fourthThuNov)
}
//Christmas
static func christmasDay(year: Int) -> Date? {
    var christmasDay = DateComponents()
    christmasDay.month = 12
    christmasDay.day = 25
    christmasDay.year = year
    return Calendar.current.date(from: christmasDay)
}

//New Year Eve
static func newYearEve(year: Int) -> Date? {
    var thirtyFirstDec = DateComponents()
    thirtyFirstDec.month = 12
    thirtyFirstDec.day = 31
    thirtyFirstDec.year = year
    return Calendar.current.date(from: thirtyFirstDec)
}


static func getHolidayArray(year: Int) -> [Date?] {
    return [newYearEve(year:year),Date.martinLKDay(year: year),Date.valentineDay(year: year),Date.washingtonBDay(year: year),Date.stPatrickDay(year: year),Date.easterHoliday(year: year),Date.mothersDay(year: year),Date.memorialDay(year: year),Date.fathersDay(year: year),Date.independenceDay(year: year),Date.laborDay(year: year),Date.columbusDay(year: year),Date.halloweenDay(year: year),Date.veteransDay(year: year),Date.thanksGivingDay(year: year),Date.christmasDay(year: year),Date.newYearEve(year: year)]
}
}

Get date:

let date = Date.easterHoliday(year: 2019)

For holiday array:

let holidayArr = Date.getHolidayArray(year: 2019)


  • Here you'll find RSS-feeds with the holidays. It doesn't list year, but in the docs you'll find information how to change date ranges.
  • Download it. I would suggest ASIHTTPRequest for that task.
    parse the RSS-feed. you can do so by normal XML-parsing, or you use a specialized parser. MWFeedParser would be one option.
  • Save the dates. either by using CoreData, or Event Kit Framework


Thank you Kiran! I found your code very helpful for a MacOS app I'm building that relies on when the US Stock Markets are open or closed.

Building on your extension, I added some additional functionality to handle holiday observations in addition to the actual holidays. Also, some of the holidays like Labor Day weren't being caught because the switch case was looking for a DateComponent.day of 0 which just needed to be changed to '_'.

For example, I changed:

case (9, 0, 2, 1): return true                      // Labor Day - 1st Mon in Sept

to this:

case (9, _, 2, 1): return true                      // Labor Day - 1st Mon in Sept

The example below is specific to Christmas, which is not always observed on the 25th of December. If Christmas falls on a Saturday, then it's observed Friday December 24, or if it falls on a Sunday it's observed Monday December 26. Same logic applies to any other holiday as well:

//Christmas Observed
    static func christmasObserved(year: Int) -> Date? {
        var christmasDay = DateComponents()
        christmasDay.month = 12
        christmasDay.day = 25
        christmasDay.year = year
        let christmas = Calendar.current.date(from: christmasDay) ?? Date()
        switch christmasDay.weekday {
        case 6:
            do {
                return Calendar.current.date(byAdding: Calendar.Component.day, value: -1, to: christmas)
            }
        case 7:
            do {
                return Calendar.current.date(byAdding: Calendar.Component.day, value: 1, to: christmas)
            }
        default:
            do {
                return christmas
            }
        }
    }

This can be used in your isUSHoliday like so:

    let christmas = Date.christmasObserved(year: year)
    let christmasDay = Calendar.current.component(.day, from: christmas ?? Date())
    switch (month, day, weekday, weekdayOrdinal) {
    // All your other cases and then...            
    case (12, christmasDay, _, _): return true                    // Christmas Observed
    default: return false
    }

That way the result is true if the date is either the actual holiday itself or the day it is observed if it falls on a weekend.

0

精彩评论

暂无评论...
验证码 换一张
取 消