web-dev-qa-db-ja.com

Swiftで日付の時刻だけをどのように比較しますか?

2つの日付オブジェクトがあります。

  1. 2017-01-13 11:40:17 +0000

  2. 2016-03-15 10:22:14 +0000

これらの値の時間のみを比較し、日付を無視する必要があります

例:12:00 amおよび12:01 am、12:01の方が遅い(12:01 am> 12:00 am)== true

10
Dylan

これは私が最後に取ったルートです。これにより、Swiftで日付の時刻だけを比較するのが簡単になります

新しいオブジェクト時間:

class Time: Comparable, Equatable {
init(_ date: Date) {
    //get the current calender
    let calendar = Calendar.current

    //get just the minute and the hour of the day passed to it
    let dateComponents = calendar.dateComponents([.hour, .minute], from: date)

        //calculate the seconds since the beggining of the day for comparisions
        let dateSeconds = dateComponents.hour! * 3600 + dateComponents.minute! * 60

        //set the varibles
        secondsSinceBeginningOfDay = dateSeconds
        hour = dateComponents.hour!
        minute = dateComponents.minute!
    }

    init(_ hour: Int, _ minute: Int) {
        //calculate the seconds since the beggining of the day for comparisions
        let dateSeconds = hour * 3600 + minute * 60

        //set the varibles
        secondsSinceBeginningOfDay = dateSeconds
        self.hour = hour
        self.minute = minute
    }

    var hour : Int
    var minute: Int

    var date: Date {
        //get the current calender
        let calendar = Calendar.current

        //create a new date components.
        var dateComponents = DateComponents()

        dateComponents.hour = hour
        dateComponents.minute = minute

        return calendar.date(byAdding: dateComponents, to: Date())!
    }

    /// the number or seconds since the beggining of the day, this is used for comparisions
    private let secondsSinceBeginningOfDay: Int

    //comparisions so you can compare times
    static func == (lhs: Time, rhs: Time) -> Bool {
        return lhs.secondsSinceBeginningOfDay == rhs.secondsSinceBeginningOfDay
    }

    static func < (lhs: Time, rhs: Time) -> Bool {
        return lhs.secondsSinceBeginningOfDay < rhs.secondsSinceBeginningOfDay
    }

    static func <= (lhs: Time, rhs: Time) -> Bool {
        return lhs.secondsSinceBeginningOfDay <= rhs.secondsSinceBeginningOfDay
    }


    static func >= (lhs: Time, rhs: Time) -> Bool {
        return lhs.secondsSinceBeginningOfDay >= rhs.secondsSinceBeginningOfDay
    }


    static func > (lhs: Time, rhs: Time) -> Bool {
        return lhs.secondsSinceBeginningOfDay > rhs.secondsSinceBeginningOfDay
    }
}

簡単にアクセスできる日付拡張://日付か​​ら時刻を取得する機能を追加します:

extension Date {
    var time: Time {
        return Time(self)
    }
}

例:

let firstDate = Date()
let secondDate = firstDate

//Will return true
let timeEqual = firstDate.time == secondDate.time
12
Dylan

私のアプローチは、 Calendar を使用してそれらを同じ日付のDateオブジェクトにしてから、たとえば timeIntervalSinceReferenceDateを使用してそれらを比較することです。

別のよりクリーンな(ただし、結果のコードの行数が増える可能性が高い)のは、DatesecondsFromBeginningOfTheDay() -> TimeIntervalと呼ばれる拡張を作成し、結果のdouble値を比較することです。

2番目のアプローチに基づく例:

// Creating Date from String
let textDate1 = "2017-01-13T12:21:00-0800"
let textDate2 = "2016-03-06T20:12:05-0900"

let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZ"
    formatter.timeZone = TimeZone.current
    return formatter
} ()

// Dates used for the comparison
let date1 = dateFormatter.date(from: textDate1)
let date2 = dateFormatter.date(from: textDate2)




// Date extensions
extension Date {
    func secondsFromBeginningOfTheDay() -> TimeInterval {
        let calendar = Calendar.current
        // omitting fractions of seconds for simplicity
        let dateComponents = calendar.dateComponents([.hour, .minute, .second], from: self)

        let dateSeconds = dateComponents.hour! * 3600 + dateComponents.minute! * 60 + dateComponents.second!

        return TimeInterval(dateSeconds)
    }

    // Interval between two times of the day in seconds
    func timeOfDayInterval(toDate date: Date) -> TimeInterval {
        let date1Seconds = self.secondsFromBeginningOfTheDay()
        let date2Seconds = date.secondsFromBeginningOfTheDay()
        return date2Seconds - date1Seconds
    }
}

if let date1 = date1, let date2 = date2 {
    let diff = date1.timeOfDayInterval(toDate: date2)

    // as text
    if diff > 0 {
        print("Time of the day in the second date is greater")
    } else if diff < 0 {
        print("Time of the day in the first date is greater")
    } else {
        print("Times of the day in both dates are equal")
    }


    // show interval as as H M S
    let timeIntervalFormatter = DateComponentsFormatter()
    timeIntervalFormatter.unitsStyle = .abbreviated
    timeIntervalFormatter.allowedUnits = [.hour, .minute, .second]
    print("Difference between times since midnight is", timeIntervalFormatter.string(from: diff) ?? "n/a")

}

// Output: 
// Time of the day in the second date is greater
// Difference between times since midnight is 8h 51m 5s
7
MirekE

私はこれだけを行うのに問題があり、2つの日付の時間を比較したいだけなら、もっと簡単な解決策を見つけたと思います。少し「ハック」を感じますが、うまく機能しているようです。

Swift 4

// date1 and date2 are the dates you want to compare

let calendar = Calendar.current

var newDate = Date(TimeIntervalSinceReferenceDate: 0) // Initiates date at 2001-01-01 00:00:00 +0000
var newDate1 = Date(TimeIntervalSinceReferenceDate: 0) // Same as above

// Recieving the components from the dates you want to compare 
let newDateComponents = calendar.dateComponents([.hour, .minute], from: date1)!
let newDate1Components = calendar.dateComponents([.hour, .minute], from: date2)!

// Adding those components
newDate = calendar.date(byAdding: newDateComponents, to: newDate)
newDate1 = calendar.date(byAdding: newDate1Components, to: newDate1)
5
Bartek Spitza

日付を無視して1日2回を比較するための私の解決策:

let date1 = some time as a date
let date2 = some other time as a date

let time1 = 60*Calendar.current.component(.hour, from: date1!) + Calendar.current.component(.minute, from: date1!)
let time2 =  60*Calendar.current.component(.hour, from: date2!) + Calendar.current.component(.minute, from: date2!)

これで、曜日に関係なく整数time1とtime2を比較できます。より高い精度が必要な場合は、seconds/60を追加できます。

4
Wayne Henderson

時刻の標準タイプはありません。最初に妥当なタイプはタプルです:

typealias TimeOfDay = (hour: Int, minute: Int, second: Int)

これらのTimeOfDay値を作成するには、Calendarが必要です。デフォルトでは、Calendarはデバイスのシステム全体のタイムゾーンを使用します。そうしたくない場合は、Calendarのタイムゾーンを明示的に設定してください。例:

var calendar = Calendar.autoupdatingCurrent
calendar.timeZone = TimeZone(abbreviation: "UTC")!

これで、DateFormatterを使用して文字列をDatesに変換し(必要な場合)、次にcalendarを使用してDates:

let strings: [String] = ["2017-01-13 11:40:17 +0000", "2016-03-15 10:22:14 +0000"]
let parser = DateFormatter()
parser.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let timesOfDay: [TimeOfDay] = strings.map({ (string) -> TimeOfDay in
    let components = calendar.dateComponents([.hour, .minute, .second], from: parser.date(from: string)!)
    return (hour: components.hour!, minute: components.minute!, second: components.second!)
})

Swift.print(timesOfDay)
// Output: [(11, 40, 17), (10, 22, 14)]

最後に、これらのTimeOfDay値を比較できます。 Swiftには、要素がComparableであるタプルの標準比較演算子が付属しているため、このTimeOfDay型が適格です。次のように言うだけです。

if timesOfDay[0] < timesOfDay[1] {
    Swift.print("date[0] comes first")
} else if timesOfDay[0] == timesOfDay[1] {
    Swift.print("times are equal")
} else {
    Swift.print("date[1] comes first")
}
2
rob mayoff

これは、Swiftを使用する場合、非常に簡単です Swifter Swift

date1.day = 1
date1.month = 1
date1.year = 2000

date2.day = 1
date2.month = 1
date2.year = 2000

これで、date1およびdate2で​​>、<、==演算子を使用して、時間コンポーネントのみを比較できます。

編集-日付クラスを拡張することでこれを自分で行うことができます。たとえば、swifter-Swiftは日コンポーネントのベローズを行います。

public var day: Int {
        get {
            return Calendar.current.component(.day, from: self)
        }
        set {
            let allowedRange = Calendar.current.range(of: .day, in: .month, for: self)!
            guard allowedRange.contains(newValue) else { return }

            let currentDay = Calendar.current.component(.day, from: self)
            let daysToAdd = newValue - currentDay
            if let date = Calendar.current.date(byAdding: .day, value: daysToAdd, to: self) {
                self = date
            }
        }
    } 
1
Alex

このコードは機能し、遊び場で簡単に確認できます

let s1 = "22:31"
let s2 = "14:31"
let f = DateFormatter()
f.dateFormat = "HH:mm"

f.date(from: s1)! //"Jan 1, 2000 at 10:31 PM"
f.date(from: s2)! //"Jan 1, 2000 at 2:31 PM"
f.date(from: s1)! > f.date(from: s2)!  // true
0
John Eugene