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
Ios-Charts Set Maximum Visible X Axis Values
Swiftui Pick a Value from a List with Ontap Gesture
Diffrence Between Function and Generic Function in Swift
Why Does My @Lazy Property Crash, But If I Make It Non Lazy It Works
Pod Install Gpuimage Does Not Work
Realm Swift: Always Put Nil Values Last in Sort
Global Var VS Shared Instance Swift
Swiftui: How to Only Run Code When the User Stops Typing in a Textfield
Define Struct That Is Treated Like a Class in Swift
Optional Type 'Bool' Cannot Be Used as a Boolean; Test for '!=Nil' Instead
Cloudkit - "Invalid Bundle Id for Container"
Get Nil When Looking for File in Subdirectory of Main Bundle
Swiftui on MACos - Handle Single-Click and Double-Click at the Same Time
Swift. Declaring Private Functions in Internal Protocol
Using Foreach with a String Array - [String] Has No Member 'Identified'
Guard Let Error: Initializer for Conditional Binding Must Have Optional Type Not 'String'
Why Specify [Unowned Self] in Blocks Where You Depend on Self Being There
Comparing Two Enum Variables Regardless of Their Associated Values