我需要精确计算两个日期之间的距离(以年为单位)。鉴于所有年份的天数并不相同,有些年份有 366 天,我无法计算两天之间的天数并除以 365...是否有比以下更直接的方法或更精确的方法:
import Foundation
func isLeapYear(_ year: Int) -> Bool {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
}
func countLeapYears(_ startDate: Date, _ endDate: Date) -> (leapYears: Int, nonLeapYears: Int) {
let calendar = Calendar.current
let startYear = calendar.component(.year, from: startDate)
let endYear = calendar.component(.year, from: endDate)
var leapYears = 0
var nonLeapYears = 0
for year in startYear...endYear {
if isLeapYear(year) {
leapYears += 1
} else {
nonLeapYears += 1
}
}
return (leapYears, nonLeapYears)
}
func yearsBetween(_ startDate: Date, _ endDate: Date) -> Double {
let calendar = Calendar.current
let totalSeconds = endDate.timeIntervalSince(startDate)
let secondsInCommonYear = 365.0 * 24 * 60 * 60
let secondsInLeapYear = 366.0 * 24 * 60 * 60
let (leap, nonleap) = countLeapYears(startDate, endDate)
let nominator = (Double(nonleap) * secondsInCommonYear + Double(leap) * secondsInLeapYear)
let denominamtor = (nonleap + leap)
let averageSecondsInYear = nominator / Double(denominamtor)
let years = totalSeconds / averageSecondsInYear
return years
}
let startDate = Calendar.current.date(byAdding: .year, value: -46, to: .now)!
let endDate = Date.now
yearsBetween(startDate, endDate) // returns 46,00069901
以下是如何在 VBA (VB) 中执行此操作。您也许可以轻松地将其转换为 Swift。
方法是找出年差,然后对于每个日期,找到一年中的第几天,并将其除以一年中的天数,然后计算总差并将其四舍五入到小数点后三位或更少。
' Returns the decimal count of years between Date1 and Date2.
'
' Rounds by default to three decimals, as more decimals has no meaning
' because of the leap years.
' Optionally, don't round, by setting Round3 to False.
'
' 2017-01-24. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function TotalYears( _
ByVal Date1 As Date, _
ByVal Date2 As Date, _
Optional Round3 As Boolean = True) _
As Double
Dim Years As Double
Dim Part1 As Double
Dim Part2 As Double
Dim Fraction As Double
Dim Result As Double
Years = DateDiff(IntervalSetting(DtInterval.dtYear), Date1, Date2)
Part1 = (DatePart(IntervalSetting(DtInterval.dtDayOfYear), Date1) - 1) / DaysInYear(Date1)
Part2 = (DatePart(IntervalSetting(DtInterval.dtDayOfYear), Date2) - 1) / DaysInYear(Date2)
If Round3 = True Then
' Round to three decimals.
Fraction = (-Part1 + Part2) * 1000
Result = Years + Int(Fraction + 0.5) / 1000
Else
Result = Years - Part1 + Part2
End If
TotalYears = Result
End Function
来源:VBA.日期