Swift 中两个日期之间的精确小数年距离

问题描述 投票:0回答:1

我需要精确计算两个日期之间的距离(以年为单位)。鉴于所有年份的天数并不相同,有些年份有 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
swift date calendar foundation
1个回答
0
投票

以下是如何在 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.日期

© www.soinside.com 2019 - 2024. All rights reserved.