Search code examples
swiftswiftdate

SwiftDate and date calculation


I'm trying to calculate the number of weeks and days that a pet is alive. I'm using SwiftDate for that. So I let the user select a birthdate and compare it to the current date.

I don't want to compare the time... so both the birthdate and current date should have the same time.

My code is:

let greg = Calendar(identifier: .gregorian)
var date1 = birthday // from datepicker
var date2 = Date()
var components1 = greg.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date1)
var components2 = greg.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date2)
components1.hour = 15
components1.minute = 0
components1.second = 0
components2.hour = 15
components2.minute = 0
components2.second = 0
date1 = greg.date(from: components1)!
date2 = greg.date(from: components2)!

let daysAlive = (date2 - date1).in(.day)
let weeksAlive = Int(weeksAlive! / 7)
let restDays = daysAlive! - (weeksAlive * 7)
let aLive = "Age: \(weeksAlive) wk, \(restDays) d (\(daysAlive!) d)"

Output is "Age: 28 wk, 3 d (199 d)"

The code works... but how can I refactor it? And is there an easier way to set the 'same time' for two given dates?


Solution

  • To ignore the time just omit the components for .hour, .minute and .second

    let components1 = greg.dateComponents([.year, .month, .day], from: date1)
    let components2 = greg.dateComponents([.year, .month, .day], from: date2)
    
    date1 = greg.date(from: components1)!
    date2 = greg.date(from: components2)!
    

    This is a simpler solution without any third party library. It calculates the difference once for weekOfMonth and day and once for day with the Calendar method dateComponents(:from:to:. Extra math is not needed.

    let greg = Calendar(identifier: .gregorian)
    var date1 = greg.date(from: DateComponents(year: 2017, month: 6, day: 25))!
    var date2 = Date()
    var components1 = greg.dateComponents([.year, .month, .day], from: date1)
    var components2 = greg.dateComponents([.year, .month, .day], from: date2)
    
    let weeksAndDays = greg.dateComponents([.weekOfMonth, .day], from: components1, to: components2)
    let justDays = greg.dateComponents([.day], from: components1, to: components2)
    
    let aLive = "Age: \(weeksAndDays.weekOfMonth!) wk, \(weeksAndDays.day!) d (\(justDays.day!) d)"
    // "Age: 28 wk, 3 d (199 d)"