Differencebetween Date.Addingtimeinterval(_:) and Date.Advanced(By:)

What is the difference between Date.addingTimeInterval(_:) and Date.advanced(by:)?

.addingTimeInterval(_:) is a long-existing method, coming from ObjC NSDate. .advanced(by:) exists to match Strideable conformance in Swift. Date similarly has a Stride typealias.

That said, Date does not actually conform to Strideable, and this has been discussed and generally rejected.

The Strideable pseudo-conformance seems to have been added as part of a large merge from Xcode 11.4 in an extension called Schedulers+Date that appears to be part of Combine (which is not open source). I don't see any discussion of it in the forums, except for a note that it broke existing code. The change notes:

// Date cannot conform to Strideable per rdar://35158274
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
extension Date /* : Strideable */ {

My hunch is that somewhere inside of Combine, there's a retroactive conformance of Date to Strideable. You can get the same by just asking for it:

extension Date: Strideable {}

It feels like the Swift stdlib team accepted that Date should not be Strideable (and I agree with the reasoning, because it invites a lot of common date bugs), but some other team in Apple wanted it and put the hooks into stdlib anyway, without putting in the conformance.

What is the difference between timeIntervalSince and distance on Date?

timeIntervalSince(_:) is an old NSDate method bridged from Objective C Cocoa Foundation.

distance(to:) is purely a newer Swift method, part of the Date overlay. It expresses itself in a more Swifty way, consonant with things like the + overload and other conveniences, and is basically just a natural consequence of the fact that a Date is configured to be Strideable.

How to get 1 hour ago from a date in iOS swift?

For correct calculations involving NSDate that take into account all edge cases of different calendars (e.g. switching between day saving time) you should use NSCalendar class:

Swift 3+

let earlyDate = Calendar.current.date(
byAdding: .hour,
value: -1,
to: Date())

Older

// Get the date that was 1hr before now
let earlyDate = NSCalendar.currentCalendar().dateByAddingUnit(
.Hour,
value: -1,
toDate: NSDate(),
options: [])

Calculating the difference between two dates in Swift

I ended up creating a custom operator for Date:

extension Date {

static func - (lhs: Date, rhs: Date) -> TimeInterval {
return lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
}

}

With this operator I can now compute the difference between two dates on a more abstract level without caring about timeIntervalSinceReferenceDate or what exactly the reference date is – and without losing precision, for example:

let delta = toDate - fromDate

Obviously, I didn't change much, but for me it's a lot more readable and consequent: Swift has the + operator already implemented for a Date and a TimeInterval:

/// Returns a `Date` with a specified amount of time added to it.
public static func + (lhs: Date, rhs: TimeInterval) -> Date

So it's already supporting

Date + TimeInterval = Date

Consequently, it should also support

Date - Date = TimeInterval

in my opinion and that's what I added with the simple implementation of the - operator. Now I can simply write the example function exactly as mentioned in my question:

func computeNewDate(from fromDate: Date, to toDate: Date) -> Date    
let delta = toDate - fromDate // `Date` - `Date` = `TimeInterval`
let today = Date()
if delta < 0 {
return today
} else {
return today + delta // `Date` + `TimeInterval` = `Date`
}
}

It might very well be that this has some downsides that I'm not aware of at this moment and I'd love to hear your thoughts on this.

Higher order function to generate interval of dates between 2 dates?

You should always use Calendar methods for you calendrical calculations. What you need is to create a while loop and add a date component value on each iteration to your a date and stop the iteration when it reaches the end date:

var date = DateComponents(calendar: .current, year: 2021, month: 7, day: 15, hour: 10, minute: 14).date!
let end = DateComponents(calendar: .current, year: 2021, month: 7, day: 15, hour: 10, minute: 16).date!

var dates = [date]
while let nextDate = Calendar.current.date(byAdding: .second, value: 15, to: date) {
if nextDate <= end {
dates.append(nextDate)
date = nextDate
} else {
break
}
}

dates.forEach { print($0.description(with: .current)) }

edit/update:

If all you need to add to your date is seconds you can simply use += operator:

var date = DateComponents(calendar: .current, year: 2021, month: 7, day: 15, hour: 10, minute: 14).date!
let end = DateComponents(calendar: .current, year: 2021, month: 7, day: 15, hour: 10, minute: 16).date!

var dates = [date]
while date <= end {
date += 15
if date <= end {
dates.append(date)
} else {
break
}
}

dates.forEach { print($0.description(with: .current)) }

Those will print:

Thursday, July 15, 2021 at 10:14:00 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:14:15 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:14:30 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:14:45 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:15:00 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:15:15 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:15:30 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:15:45 AM Brasilia Standard Time

Thursday, July 15, 2021 at 10:16:00 AM Brasilia Standard Time

And a not so clean but one liner:

let dates = (0...Int(end.timeIntervalSince(date)/15))
.map { date.addingTimeInterval(.init($0)*15) }

Difference between 2 dates in weeks and days using swift 3 and xcode 8

You can use Calendar's dateComponents(_:from:to:) to find the difference between 2 dates to your desired units.

Example:

let dateRangeStart = Date()
let dateRangeEnd = Date().addingTimeInterval(12345678)
let components = Calendar.current.dateComponents([.weekOfYear, .month], from: dateRangeStart, to: dateRangeEnd)

print(dateRangeStart)
print(dateRangeEnd)
print("difference is \(components.month ?? 0) months and \(components.weekOfYear ?? 0) weeks")

> 2017-02-17 10:05:19 +0000
> 2017-07-10 07:26:37 +0000
> difference is 4 months and 3 weeks

let months = components.month ?? 0
let weeks = components.weekOfYear ?? 0


Related Topics



Leave a reply



Submit