DateComponentsを利用していますが計算の本質ではないです。
extension DateComponents {
//need year, month, day
func dateCountFrom20010101() -> Int? {
let y = year! - 2001
let m = month! - 1
let d = day! - 1
var count = y * 365 + y/4 - y/100 + y/400
if (year! % 4 == 0 && year! % 100 != 0) || year! % 400 == 0 { //uru doshi
let tmp = [0,31,60,91,121,152,182,213,244,274,305,335]
count += tmp[m] + d
} else {
let tmp = [0,31,59,90,120,151,181,212,243,273,304,334]
count += tmp[m] + d
}
return count
}
}
以下はテストコード。
20001/01/01のDateをとり、i日進めたものをnewDateとします。
newDateからnewCompを取り出して、dateCountFrom20010101の値とiを比較します。
10000年だと処理に1分くらいかかります(かかりました。)
let a = 365 * 10000
let b = DateComponents(calendar: nil, timeZone: nil, era: nil, year: 2001, month: 1, day: 1, hour: 12, minute: nil, second: nil, nanosecond: nil, weekday: nil, weekdayOrdinal: nil, quarter: nil, weekOfMonth: nil, weekOfYear: nil, yearForWeekOfYear: nil)
let date20010101noon = Calendar(identifier: .gregorian).date(from: b)!
let daysecond = 24 * 60 * 60
print("start--------------------")
for i in 0..<a {
let newDate = Date(timeInterval: TimeInterval(daysecond * i), since: date20010101noon)
let newComp = Calendar(identifier: .gregorian).dateComponents([.year,.month,.day], from: newDate)
let j = newComp.dateCountFrom20010101()
if i != j {
print("failed:\(j)")
}
}
print("end-------------------")