【问题标题】:How do you compare just the time of a Date in Swift?你如何比较 Swift 中日期的时间?
【发布时间】:2017-05-29 12:42:52
【问题描述】:

我有两个日期对象:

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

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

我只需要比较这些值的时间而忽略日期

例如:12:00am 和 12:01am,12:01 更晚(12:01am > 12:00am)== true

【问题讨论】:

  • “比较”是什么意思?
  • 查看哪个更大或更小,添加示例
  • 它们是日期对象还是字符串??
  • 它们是日期对象

标签: swift sorting date datetime time


【解决方案1】:

我的方法是使用Calendar 使它们成为同一天的Date 对象,然后使用例如timeIntervalSinceReferenceDate 比较它们。

另一种更简洁的方法(但很可能产生更多行代码)是为 Date 创建名为 secondsFromBeginningOfTheDay() -> TimeInterval 的扩展名,然后比较生成的双精度值。

基于第二种方法的示例:

// 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

【讨论】:

    【解决方案2】:

    一天中的时间没有标准类型。一个合理的类型开始只是一个元组:

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

    要创建这些TimeOfDay 值,您需要Calendar。默认情况下,Calendar 使用设备的系统范围的时区。如果您不想这样,请明确设置Calendar 的时区。示例:

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

    现在您可以使用DateFormatter 将字符串转换为Dates(如有必要),然后使用calendarDates 中提取时间组件:

    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")
    }
    

    【讨论】:

    • 这个帐户是否会在上午/下午交叉,例如下午 1:00 晚于上午 11:00?
    • 是的,因为下午 1 点在元组的 hour 元素中表示为 13。
    • 请注意,您问题中的字符串日期未提及上午/下午,因此我假设它们使用 24 小时制。
    【解决方案3】:

    这是我最后走的路线,这样很容易在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
    

    【讨论】:

    • 我懒得实现这个。谢谢:')
    【解决方案4】:

    比公认的答案简单得多:

    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】:

      我在忽略日期的情况下比较一天中的两个时间的解决方案:

      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。

      【讨论】:

        【解决方案6】:

        如果你使用Swifter Swift,这在 Swift 中非常简单

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

        现在您可以在 date1 和 date2 上使用 >,

        编辑 - 您可以通过扩展日期类来自己完成此操作,例如 swifter-swift 为 day 组件执行以下操作。

        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
                    }
                }
            } 
        

        【讨论】:

        • 这在swift中不起作用,你不能只从日期对象中设置日、月和年。虽然在正确的轨道上
        • 是的。你是对的。我在我们的生产代码中使用此代码.. 但我们使用的是 swifter-swift 扩展.. )))
        【解决方案7】:

        此代码有效,在操场上轻松检查

        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
        

        【讨论】:

        • 请用正确的描述回答
        • 也不回答问题
        【解决方案8】:

        假设我们有两个字符串格式的日期:

        // "2017-01-13 11:40:17 +0000"
        // "2016-03-15 10:22:14 +0000"
        

        我们需要将此字符串转换为日期格式,我们创建 DateFormatter() 并设置它要转换的格式 ("yyyy-MM-dd' 'HH:mm:ssZ")

        //date formatter converts string to date in our case
        let firstDateFormatter = DateFormatter()
        firstDateFormatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ssZ"
        

        现在我们可以将日期从字符串转换为日期格式

           //convert string to dates
            if let date1 = firstDateFormatter.date(from: "2017-01-13 09:40:17 +0000"),
                let date2 = firstDateFormatter.date(from: "2016-03-15 10:22:14 +0000") {
            
        

        我们想要的只是比较小时和分钟。所以将日期格式更改为“HH:mm”

        //we ve got the dates, now switch dateformat for other job
        firstDateFormatter.dateFormat = "HH:mm"
        

        现在从我们的日期中获取字符串值,它只包含“HH:mm”

           // convert date to string ( part of string we want to compare )
                let HHmmDate1 = firstDateFormatter.string(from: date1) //"17:40"
                let HHmmDate2 = firstDateFormatter.string(from: date2) //"18:22"
        

        最后一步是从我们的“HH:mm”值中获取日期,假设我们要求 DateFormatter 给我们一个仅基于时间的日期,在我们的例子中是“17:40”和“18:22”。 DateFormatter 将为日期设置一些值,因此我们会自动为两个日期获取 2000 年 1 月 1 日,但它会获取我们提供的时间。

           //produce "default" dates with desired HH:mm
            //default means same date, but time is different
                let HH1 = firstDateFormatter.date(from: HHmmDate1) //"Jan 1, 2000 at 5:40 PM"
                let HH2 = firstDateFormatter.date(from: HHmmDate2) //"Jan 1, 2000 at 6:22 PM"
        

        现在我们可以轻松比较日期

         //compare
                HH1! > HH2!
        }
        

        还有很多选项可以将日期与日历进行比较

        【讨论】:

        • @quicklikerabbit 完成!如果有不清楚的地方,请随时提出问题
        猜你喜欢
        • 2012-01-20
        • 2010-12-25
        • 2014-03-20
        • 1970-01-01
        • 1970-01-01
        • 2017-09-29
        • 2017-07-06
        • 1970-01-01
        • 2023-03-08
        相关资源
        最近更新 更多