web-dev-qa-db-ja.com

Swiftで2つの日付の差を計算する

特定の日付コンポーネントの観点から、2つの日付の差を計算する方法を多く見てきました。日、時間、月など( Stackoverflowのこの回答 を参照):

Calendar.current.dateComponents([.hour], from: fromDate, to: toDate).hour
Calendar.current.dateComponents([.day], from: fromDate, to: toDate).day
Calendar.current.dateComponents([.month], from: fromDate, to: toDate).month

私が見ていないのは、実際のDateオブジェクトを使用して計算を行う方法です。何かのようなもの

func computeNewDate(from fromDate: Date, to toDate: Date) -> Date    
     let delta = toDate - fromDate
     let today = Date()
     if delta < 0 {
         return today
     } else {
         return today + delta
     }
}

私は DateInterval を見ましたが、これはiOS 10で導入されましたが、ドキュメントによると

[it]は、逆の間隔、つまり、期間が0未満で、終了日が開始日よりも時間的に早い間隔をサポートしていません。

そのため、日付で計算することは本質的に難しくなります。特に、どちらが早い日付であるかわからない場合はそうです。

Dates間の時間差を直接計算するためのクリーンで適切なアプローチはありますか(そしてそれらをDateインスタンスに再度追加します) )timeIntervalSinceReferenceDateによる計算なし

10
Mischa

私はDateのカスタム演算子を作成することになりました:

extension Date {

    static func - (lhs: Date, rhs: Date) -> TimeInterval {
        return lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
    }

}

この演算子を使用すると、timeIntervalSinceReferenceDateや正確な参照日付を気にせずに、より正確なレベルで2つの日付の差を計算できます。

let delta = toDate - fromDate

明らかに、私はあまり変更しませんでしたが、私にとってははるかに読みやすく、結果的です:SwiftにはDateおよびTimeIntervalに対して+演算子が既に実装されています。

/// Returns a `Date` with a specified amount of time added to it.
public static func + (lhs: Date, rhs: TimeInterval) -> Date

すでにサポートしています

Date + TimeInterval = Date

その結果、それもサポートする必要があります

Date - Date = TimeInterval

私の意見では、それは-演算子の簡単な実装で追加したものです。これで、質問で述べたとおりに関数の例を簡単に書くことができます。

func computeNewDate(from fromDate: Date, to toDate: Date) -> Date    
     let delta = toDate - fromDate // `Date` - `Date` = `TimeInterval`
     let today = Date()
     if delta < 0 {
         return today
     } else {
         return today + delta // `Date` + `TimeInterval` = `Date`
     }
}

これには、現時点では気付いていないマイナス面がいくつかあり、これについてのあなたの考えを聞いてみたいと思います。

11
Mischa

単に toDate.timeIntervalSince(fromDate)

拡張機能を追加せずに関数を再実装するには:

func computeNewDate(from fromDate: Date, to toDate: Date) -> Date  {  
     let delta = toDate.timeIntervalSince(fromDate) 
     let today = Date()
     if delta < 0 {
         return today
     } else {
         return today.addingTimeInterval(delta) 
     }
}
5
cakraww

カスタム演算子で拡張し、タプルを返すことができます

extension Date {

    static func -(recent: Date, previous: Date) -> (month: Int?, day: Int?, hour: Int?, minute: Int?, second: Int?) {
        let day = Calendar.current.dateComponents([.day], from: previous, to: recent).day
        let month = Calendar.current.dateComponents([.month], from: previous, to: recent).month
        let hour = Calendar.current.dateComponents([.hour], from: previous, to: recent).hour
        let minute = Calendar.current.dateComponents([.minute], from: previous, to: recent).minute
        let second = Calendar.current.dateComponents([.second], from: previous, to: recent).second

        return (month: month, day: day, hour: hour, minute: minute, second: second)
    }

}

を使用して:

let interval = Date() - updatedDate
print(interval.day)
print(interval.month)
print(interval.hour)
2

次のようなものはどうですか…

func computeNewDate(from fromDate: Date, to toDate: Date) -> Date {
    let delta = Calendar.current.dateComponents([.second], from: fromDate, to: toDate).second!
    return Calendar.current.date(byAdding: .second, value: delta, to: Date())!
}
0
Ashley Mills