Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shortcut for timeIntervalSince(_:) #84

Open
naoty opened this issue Mar 1, 2017 · 3 comments
Open

Shortcut for timeIntervalSince(_:) #84

naoty opened this issue Mar 1, 2017 · 3 comments

Comments

@naoty
Copy link
Owner

naoty commented Mar 1, 2017

// shortcut for date1.timeIntervalSince(date2)
date1 - date2
@basememara
Copy link
Contributor

basememara commented Apr 30, 2017

Hi @naoty, thanks for the great library and recent update!

I like this enhancement and was going to create a PR, but it was kind of tricky due to months not being a straight forward conversion. It's a WIP but this is what I have so far:

extension Date {

    static func - (left: Date, right: Date) -> DateComponents {
        return Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: right, to: left)
    }

    static func - (left: Date, right: Date) -> TimeInterval {
        return left.timeIntervalSince(right)
    }
}

extension TimeInterval {

    func seconds(to component: Calendar.Component) -> Double {
        switch component {
        case .year:
            return self / 31536000
        case .month:
            assertionFailure("Month component is not supported for conversion from seconds.")
            return 0 //Fail
        case .day:
            return self.truncatingRemainder(dividingBy: 31536000) / 86400
        case .hour:
            return self.truncatingRemainder(dividingBy: 86400) / 3600
        case .minute:
            return self.truncatingRemainder(dividingBy: 3600) / 60
        case .second:
            return self
        default:
            assertionFailure("Specified component is not supported for conversion from seconds.")
            return 0 //Fail
        }
    }
}

let date1 = Date()
let date2 = Date(timeIntervalSinceNow: -7200)

let component: DateComponents = date1 - date2
print(component) //year: 0 month: 0 day: 0 hour: 1 minute: 59 second: 59 isLeapMonth: false

let interval: TimeInterval = date1 - date2
print(interval.seconds(to: .year)) //0.000228
print(interval.seconds(to: .day)) //0.0833
print(interval.seconds(to: .hour)) //1.99
print(interval.seconds(to: .minute)) //59.99
print(interval) //7199.99

Any thoughts or suggestions on what to do about months or this approach in general?

@basememara
Copy link
Contributor

Not my favorite API but we can do something like this also:

extension Date {
        
    func minus(_ date: Date, to component: Calendar.Component) -> TimeInterval? {
        guard component != .month else {
            return Double(Calendar.current.dateComponents([.month], from: date, to: self).month!)
        }
    
        let seconds = timeIntervalSince(date)
        
        switch component {
        case .year:
            return seconds / 31536000
        case .day:
            return seconds.truncatingRemainder(dividingBy: 31536000) / 86400
        case .hour:
            return seconds.truncatingRemainder(dividingBy: 86400) / 3600
        case .minute:
            return seconds.truncatingRemainder(dividingBy: 3600) / 60
        case .second:
            return seconds
        default:
            return nil
        }
    }
}

=> date1.minus(date2, to: .month)

@naoty
Copy link
Owner Author

naoty commented May 1, 2017

@basememara Thanks!

As you said, the conversion between DateComponents and TimeInterval will be possible if we assume that 1 month always has 30 days and DST can be ignored.

I have obsoleted this conversion before at #30. So, I don't want to merge implementation on incorrect assumption.

Timepiece should use Calendar API for calendrical calculation. Timepiece is a thin wrapper of Calendar API. So, it cannot provide any APIs which Calendar doesn't provide.

Your extension for Date is good because this implementations are thin wrappers of Calendar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants