Search code examples
swiftdatecompareutc

Swift: Compare date by days


I try to compare two days ignoring time. So I use

calendar.compare(date1, to: date2, toGranularity: .day)

BUT when transfering the string date to Date type, it is transformed to UTC. So it will be "moved" from 1.1.2016 0:05 to 31.12.2015 11:05 pm. When comparing daywise, this includes only the remaining hour. Before conversion it was 24 hours. Any idea to handle this issue without much effort?

Additionally: The code:

var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy hh:mm"
var date1 : Date = dateFormatter.date(from:  "01-01-2016 00:05")!
var date2 = dateFormatter.date(from:  "01-01-2016 03:30")

if let dateFromString = dateFormatter.date(from:  "01-01-2016 00:05") {
    print(dateFromString)
    dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
    let stringFromDate = dateFormatter.string(from: dateFromString)
}


Calendar.current.compare(date1, to: date2!, toGranularity: .day) == .orderedSame

Solution

  • Details

    • Xcode 11.5 (11E608c), Swift 5.1

    Idea

    base on usage dateComponents(_:from:to:) function

    Solution

    import Foundation
    
    extension Date {
    
        func fullDistance(from date: Date, resultIn component: Calendar.Component, calendar: Calendar = .current) -> Int? {
            calendar.dateComponents([component], from: self, to: date).value(for: component)
        }
    
        func distance(from date: Date, only component: Calendar.Component, calendar: Calendar = .current) -> Int {
            let days1 = calendar.component(component, from: self)
            let days2 = calendar.component(component, from: date)
            return days1 - days2
        }
    
        func hasSame(_ component: Calendar.Component, as date: Date) -> Bool {
            distance(from: date, only: component) == 0
        }
    }
    

    Full Sample

    Do not forget to put here the Solution code (look above)

    var dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd-MM-yyyy hh:mm:ss"
    //dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
    
    let smallerDate = dateFormatter.date(from: "01-01-2012 00:05:01")!
    let biggerDate  = dateFormatter.date(from: "03-12-2019 09:30:01")!
    
    print(smallerDate.fullDistance(from: biggerDate, resultIn: .day))       // Optional(2893)
    print(biggerDate.fullDistance(from: smallerDate, resultIn: .day))       // Optional(-2893)
    print(smallerDate.fullDistance(from: biggerDate, resultIn: .year))      // Optional(7)
    print(biggerDate.fullDistance(from: smallerDate, resultIn: .year))      // Optional(7)
    print(smallerDate.fullDistance(from: biggerDate, resultIn: .hour))      // Optional(69441)
    print(biggerDate.fullDistance(from: smallerDate, resultIn: .hour))      // Optional(-69441)
    
    print(smallerDate.distance(from: biggerDate, only: .day))               // -2
    print(biggerDate.distance(from: smallerDate, only: .day))               // 2
    print(smallerDate.distance(from: biggerDate, only: .year))              // -7
    print(biggerDate.distance(from: smallerDate, only: .year))              // 7
    print(smallerDate.distance(from: biggerDate, only: .hour))              // -9
    print(biggerDate.distance(from: smallerDate, only: .hour))              // 9
    
    print(smallerDate.hasSame(.day, as: biggerDate))                        // false
    print(biggerDate.hasSame(.second, as: smallerDate))                     // true