0

Hi how to get time difference for two sting value

startTime = "09:00 AM" EndTime = "05:30 PM"

func timeDifferenceBetweenTwoTime(startTime: String, endTime:String) ->CGFloat{
    let start = startTime
    let end = endTime

    let dateFormatter = DateFormatter()
    dateFormatter.locale = Locale(identifier: "en_US_POSIX")
    dateFormatter.dateFormat = "hh:mm a"

    if let startDate = dateFormatter.date(from: start),
       let endDate = dateFormatter.date(from: end) {
        let hours: CGFloat = CGFloat(Calendar.current.dateComponents([.hour], from: startDate, to: endDate < startDate ? Calendar.current.date(byAdding: .day, value: 1, to: endDate) ?? endDate : endDate).hour ?? 00 )
        return hours
    }
    return 00.00
}

The expected result is 08.50, But for me its giving 8.0

kiran
  • 4,285
  • 7
  • 53
  • 98

2 Answers2

2

You just need to get the minutes instead of hours and divide it by 60. Btw you should also set your dateFormatter's default date to today:

func timeDifferenceBetweenTwoTime(startTime: String, endTime: String) -> CGFloat {
    let dateFormatter = DateFormatter()
    dateFormatter.locale = Locale(identifier: "en_US_POSIX")
    dateFormatter.defaultDate = Calendar(identifier: .iso8601).startOfDay(for: Date())
    dateFormatter.dateFormat = "hh:mm a"
    if let startDate = dateFormatter.date(from: startTime),
       var endDate = dateFormatter.date(from: endTime) {
        if startDate > endDate {
            endDate = Calendar.current.date(byAdding: .day, value: 1, to: endDate)!
        }
        let minute = Calendar.current.dateComponents([.minute], from: startDate, to: endDate).minute!
        return CGFloat(minute) / 60
    }
    return 0
}

let startTime = "09:00 AM"
let endTime = "05:30 PM"
timeDifferenceBetweenTwoTime(startTime: startTime, endTime: endTime)  // 8.5
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
1

You asked for the difference in hours. The Calendar function dateComponents(_:from:to:) will give you the number of whole hours between your dates if that's what you ask it for. By not also asking for the number of minutes, that gets truncated.

If you want hours and whole minutes you could ask for hours and minutes and do some math to combine them, or just ask for minutes as Leo suggests and divide minutes by 60.

You could also use endDate.timeIntervalSinceReferenceDate-startDate.timeIntervalSinceReferenceDate)/3600.0. That will give you a Double representing the exact number of hours between the two dates, including seconds and fractions of a second. (Not relevant given that your source Dates only specify hours and minutes, but there are other cases where that might be useful.)

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Why not symply `endDate.timeIntervalSince(startDate)/3600`? – Leo Dabus Jan 21 '22 at 16:30
  • Oh, true that. I can never remember that function without looking it up, so I just do math on the Dates' timeIntervals. I bet there's little or no difference in the resulting assumbly though. – Duncan C Jan 22 '22 at 03:20
  • Sure the only difference here is syntax. The date under the hood is stored as time interval since reference date. – Leo Dabus Jan 22 '22 at 03:22
  • actually not sure why Date `public func timeIntervalSince(date: Date) -> TimeInterval` method uses timeIntervalSince1970 https://gist.github.com/DonaldHays/8e5b2831313acfaea86b – Leo Dabus Jan 22 '22 at 03:26
  • Don't you mean `public func timeIntervalSince(_ date: Date) -> TimeInterval`) (the parameter is anonymous). Since that calculates the difference between Date objects, in seconds, it doesn't matter whether it uses `timeIntervalSince1970` or `timeIntervalSinceReferenceDate`. The epoch date gets subtracted away. Given that, what makes you think it uses `timeIntervalSince1970` internally? – Duncan C Jan 22 '22 at 13:49
  • the difference when calculating the time interval is negligible. The only think you should be aware is if you save a timeIntervalSince1970 instead of the timeIntervalSinceReference date and then you need to compare of to os equal it might fail due to precision loss (nanosecond). Check this [post](https://stackoverflow.com/a/47502712/2303865). Might first solution was using timeIntervalSince1970 and OP said it was failing with some dates. timeIntervalSinceReferenceDate worked as expected. – Leo Dabus Jan 22 '22 at 14:23
  • Actually I am not sure if I posted the correct swift date repository. I will double check – Leo Dabus Jan 22 '22 at 16:42