我正在处理一个需要使用国家法定日期的申请。
下面,我能够获得阵亡将士纪念日:
// Set the components for Memorial Day (last Monday of May)
let memorialDayComps = NSDateComponents()
memorialDayComps.weekday = 2
memorialDayComps.month = 5
memorialDayComps.year = currentYear
var mondaysOfMay = [NSDate]()
for var i = 1; i <= 5; i++ {
memorialDayComps.weekdayOrdinal = i
let monday = calendar.dateFromComponents(memorialDayComps)
let components = calendar.components(.CalendarUnitMonth, fromDate: monday!)
if components.month == 5 {
mondaysOfMay.append(monday!)
}
}
let memorialDayDate = mondaysOfMay.last
由于日期设置得很好,我可以在以下假期成功创建NSDate
个实例:
然而,我唯一一个难以弄清楚如何得到的是复活节。它每年都有所不同,所以我很好奇其他人是否能够通过API或其他方式如此成功地获得复活节的约会。
答案 0 :(得分:3)
我能够在GitHub上找到一个gist,它有一个准确计算并返回复活节By css = By.cssSelector("body.loading-complete"));
(new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(css))
的解决方案。
以下代码是gist包含的内容:
NSDate
答案 1 :(得分:1)
复活节算法效果很好! 使用Swift 4.0和模式匹配。模式匹配使我更容易根据月,日,工作日,工作日的日期添加其他日期。
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 // MLK - 3rd Mon in Jan
case (2, 0, 2, 3): return true // Washington - 3rd Mon in Feb
case (easterMonth, easterDay, _, _): return true // Easter - rocket science calculation
case (5, memorialDay, _, _): return true // Memorial Day
case (7, 4, _, _): return true // Independence Day
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 (11, 11, _, _): return true // Veterans Day
case (11, 0, 5, 4): return true // Happy Thanksgiving - 4th Thurs in Nov
case (12, 25, _, _): return true // Happy Holidays
case (12, 31, _, _): return true // New years Eve
default: return false
}
}
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)
}
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)
}
}
答案 2 :(得分:0)
func easter(Y : Int) -> Date {
let a = Y % 19
let b = Int(floor(Double(Y) / 100))
let c = Y % 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 components = DateComponents()
components.year = Y
components.month = Int(floor(Double(h + L - 7*m + 114) / 31))
components.day = ((h + L - 7*m + 114) % 31) + 1
components.timeZone = TimeZone(secondsFromGMT: 0)
return Calendar.autoupdatingCurrent.date(from: components)!
}
print(easter(Y: 2018)) // "2018-04-01 00:00:00 +0000"
答案 3 :(得分:0)
目标-C!
{{1}}
答案 4 :(得分:0)
这是O'Beirne's algorithm的Swift 5实现,带有内联文档。
该代码比其他提供的答案更紧凑,因为它利用了整数算法,因此无需显式舍入数字并在Float
和Int
之间进行转换。 / p>
/// **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)!
}