-2

I'm trying to display "days: hours: min: sec" from a Date in a UILabel. I'm using this extension Date from this answer here but it doesn't update the UILabel I have. Not sure what I'm doing wrong. Here's my code:

extension Date {

    func offsetFrom(date : Date) -> String {

        let dayHourMinuteSecond: Set<Calendar.Component> = [.day, .hour, .minute, .second]
        let now = Date()
        let difference = NSCalendar.current.dateComponents(dayHourMinuteSecond, from: date, to: now)

        let seconds = "\(difference.second ?? 0)s"
        let minutes = "\(difference.minute ?? 0)m" + " " + seconds
        let hours = "\(difference.hour ?? 0)h" + " " + minutes
        let days = "\(difference.day ?? 0)d" + " " + hours

        if let day = difference.day, day          > 0 { return days }
        if let hour = difference.hour, hour       > 0 { return hours }
        if let minute = difference.minute, minute > 0 { return minutes }
        if let second = difference.second, second > 0 { return seconds }
        return ""
    }

}

        // MARK: - Poll Expiration Date
        if let expirationTimeInt = post?.pollExpirationTime {
            let expirationDate = Date(timeIntervalSince1970: Double(expirationTimeInt))
            print(expirationDate) // prints "2018-07-11 164:19:58 PM +0000" 
            pollExpirationDate.text = expirationDate.offsetFrom(date: expirationDate) // shows nothing

        }
Dani
  • 3,427
  • 3
  • 28
  • 54
  • 1.: you return from `offsetFrom(date:)` as soon as one component is not zero — without ever assembling the string as you describe what should be done. 2.: you create second, minutes, hour, days, just to overwrite the variable names in the next step 3.: `expirationDate.offsetFrom(date: expirationDate)` what should be the offset by date from the same date? – vikingosegundo Jul 07 '18 at 09:58
  • **Debug** your code. Set a breakpoint in the offsetFrom function and single-step. At what point is the program flow not as you would expect it? – Martin R Jul 07 '18 at 09:59
  • Are you sure that printing the date shows `"2018-07-11 164:19:58 PM +0000" ` ? With hours being 164? – Martin R Jul 07 '18 at 10:03
  • Please add the real `Int` value of `expirationTimeInt` to the question. – vadian Jul 07 '18 at 10:10
  • 1
    `expirationDate` is in the future, so that all components of `difference` are negative. Therefore `offsetFrom()` returns an empty string. – Martin R Jul 07 '18 at 10:17

1 Answers1

3

There is a much more convenient API: DateComponentsFormatter

extension Date {

    func offsetFromNow() -> String {
        let formatter = DateComponentsFormatter()
        formatter.allowedUnits = [.day, .hour, .minute, .second]
        formatter.unitsStyle = .abbreviated
        return formatter.string(from: Date(), to: self)!
    }
}

let date = Date().addingTimeInterval(100000)

print(date.offsetFromNow())
vadian
  • 274,689
  • 30
  • 353
  • 361
  • That is correct, but not an answer to the question *"... it doesn't update the UILabel ... what I'm doing wrong ..."* – Martin R Jul 07 '18 at 10:06
  • This actually solves the problem and updates the label correctly! Now it shows `3d 6h 30 min 34s` – Dani Jul 07 '18 at 10:16