I'm seeking a way to get all American holidays as an array of NSDate
s. Is there a way to implement that?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
- 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
回答2:
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];
}
回答3:
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, 0, 2, 3): return true // Martin Luther King - 3rd Mon in Jan
case (2, 14, _, _): return true // Valentine day - 14th in Feb
case (2, 0, 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, 0, 1, 2): return true // Mothers day - 2nd Sun in May
case (5, memorialDay, _, _): return true // Memorial Day
case (5, 0, 1, 3): return true // Fathers day - 3rd Sun in May
case (7, 4, _, _): return true // Independence Day - 4th July
case (9, 0, 2, 1): return true // Labor Day - 1st Mon in Sept
case (10, 0, 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, 0, 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)
}
}
Get date:
let date = Date.easterHoliday(year: 2019)