Created
November 4, 2017 19:15
-
-
Save mrackwitz/e91892f3a22c5e0a797e60f8d7e75127 to your computer and use it in GitHub Desktop.
Dates around DST end
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
let calendar = Calendar(identifier: .gregorian) | |
// Daylight Saving Time ends in 2017 on Nov 5th, 2:00 AM in the United States. | |
// Let's instantiate some `Date`s around that. | |
let nov4_1am = calendar.date(from: DateComponents(year: 2017, month: 11, day: 4, hour: 1))! | |
let nov4_2am = calendar.date(from: DateComponents(year: 2017, month: 11, day: 4, hour: 2))! | |
let nov4_3am = calendar.date(from: DateComponents(year: 2017, month: 11, day: 4, hour: 3))! | |
let nov5_1am = calendar.date(from: DateComponents(year: 2017, month: 11, day: 5, hour: 1))! | |
let nov5_2am = calendar.date(from: DateComponents(year: 2017, month: 11, day: 5, hour: 2))! | |
let nov5_3am = calendar.date(from: DateComponents(year: 2017, month: 11, day: 5, hour: 3))! | |
// We should always rely on a calendar to get specific dates. Assuming that | |
// a day always has 86400s (24*60*60) can break, as we can see below. | |
Date(timeIntervalSince1970: nov4_1am.timeIntervalSince1970 + 86400) // That's expected… | |
Date(timeIntervalSince1970: nov4_2am.timeIntervalSince1970 + 86400) // … but this? | |
Date(timeIntervalSince1970: nov5_1am.timeIntervalSince1970 + 3600) // Or this? | |
// We cannot rely on this assumption for calculating the difference between two dates. | |
func naiveDaysDifference(from: Date, to: Date) -> Int { | |
let timestampDifference = to.timeIntervalSince1970 - from.timeIntervalSince1970 | |
return Int((timestampDifference / 86400).rounded(.up)) | |
} | |
// We can and should use the Foundation classes instead though! | |
func calendarBasedDaysDifference(from: Date, to: Date) -> Int { | |
return calendar.dateComponents(Set([Calendar.Component.day]), from: from, to: to).day! | |
} | |
// Helper function | |
func compare(from: Date, to: Date) -> (naive: Int, calendarBased: Int) { | |
return (naiveDaysDifference(from: from, to: to), calendarBasedDaysDifference(from: from, to: to)) | |
} | |
compare(from: nov4_1am, to: nov5_1am) | |
compare(from: nov4_2am, to: nov5_2am) // 2 ≠ 1 ⚡️ | |
compare(from: nov4_3am, to: nov5_3am) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment