Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Calendaring Feats: Understanding Dates and Dayp...

lauraragone
November 01, 2017

Calendaring Feats: Understanding Dates and Dayparts

Is it the weekend, yet? The answer isn’t quite as straightforward as it seems. In this talk, we'll discuss considerations for developing features displaying dates and times at an international scale. We'll walk through a few common pitfalls when working with Foundation's Calendar and DateInterval APIs and evaluate how dependency injection and test driven development can be used to prevent bugs around the world.

Presented at iOSoHo - November 2017

lauraragone

November 01, 2017
Tweet

More Decks by lauraragone

Other Decks in Programming

Transcript

  1. “[…] I am unable to find meetups as easily as

    I did before.” “There is no apparent way to filter meetups” “[…] if I have to dig to find stuff that’s a dealbreaker.” iOSoHo - November 2017 Laura Ragone
  2. iOSoHo - November 2017 Laura Ragone • Date filtering Adapt

    ranges relative to the current day • Time filtering Adapt intervals to the user’s language and locale FIND EVENTS BY DATE AND TIME Filtered Meetups
  3. Today, we’ll discuss… What makes working with dates and times

    so difficult 1 2 Common mistakes when working with datetime 3 How TDD and dependency injection can help iOSoHo - November 2017 Laura Ragone
  4. • The de facto calendar has not remained constant throughout

    history • Lunar → Solar • Roman calendar → Julian Calendar → Gregorian Calendar • Cultural variations A Brief History of Datetime iOSoHo - November 2017 Laura Ragone
  5. Is the first day of the week Sunday or Monday?

    …or Saturday? Additional Constraints iOSoHo - November 2017 Laura Ragone
  6. Additional Constraints: When is the weekend? iOSoHo - November 2017

    Laura Ragone Friday - Saturday Saturday - Sunday
  7. Is it made up of multiple, contiguous days? Additional Constraints:

    When is the weekend? iOSoHo - November 2017 Laura Ragone
  8. …Is it made up of multiple days? Additional Constraints: When

    is the weekend? iOSoHo - November 2017 Laura Ragone
  9. iOSoHo - November 2017 Laura Ragone • Date filters •

    Any day • Today • Tomorrow • This week • This weekend • Next week • Next weekend FIND EVENTS BY DATE AND TIME Filtered Meetups
  10. Defining Date Filters iOSoHo - November 2017 Laura Ragone enum

    DateFilter { case any case today case tomorrow case thisWeek case thisWeekend case nextWeek case nextWeekend } • Date filters • Any day • Today • Tomorrow • This week • This weekend • Next week • Next weekend
  11. Defining Date Intervals iOSoHo - November 2017 Laura Ragone func

    dateInterval(from currentDate: Date = Date(), in calendar: Calendar = .current) -> DateInterval? { switch self { case .any: // ... case .today: // ... case .tomorrow: // ... case .thisWeek: // ... case .thisWeekend: // ... case .nextWeek: // ... case .nextWeekend: // ... } }
  12. Defining Date Intervals: Any iOSoHo - November 2017 Laura Ragone

    switch self { case .any: return nil // ... }
  13. Defining Date Intervals: Today iOSoHo - November 2017 Laura Ragone

    // ... case .today: return calendar.dateInterval(of: .day, for: currentDate) // ...
  14. Defining Date Intervals: Tomorrow iOSoHo - November 2017 Laura Ragone

    // ... case .tomorrow: guard let todayInterval = DateFilter.today.dateInterval(from: currentDate, in: calendar) else { return nil } let startDate = todayInterval.end return calendar.dateInterval(of: .day, for: startDate) // ...
  15. Defining Date Intervals: This week iOSoHo - November 2017 Laura

    Ragone // ... case .thisWeek: return calendar.dateInterval(of: .weekOfMonth, for: currentDate) // ... }
  16. Defining Date Intervals: Next week iOSoHo - November 2017 Laura

    Ragone // ... case .nextWeek: guard let thisWeekInterval = DateFilter.thisWeek.dateInterval(from: currentDate, in: calendar) else { return nil } let startDate = thisWeekInterval.end return calendar.dateInterval(of: .weekOfMonth, for: startDate) // ...
  17. A Look at Date Components: This week iOSoHo - November

    2017 Laura Ragone // First, extract date components from the current date object. let currentDateComponents = calendar.dateComponents(in: calendar.timeZone, from: currentDate) // Next, use these current date's `DateComponents` to define the start date for "this week". let startDateComponents = DateComponents(calendar: calendar, timeZone: calendar.timeZone, month: currentDateComponents.month, weekOfYear: currentDateComponents.weekOfYear, yearForWeekOfYear: currentDateComponents.yearForWeekOfYear) // Then, create a start `Date` object from those date components. let startDate = calendar.date(from: startDateComponents)
  18. A Look at Date Components: This week iOSoHo - November

    2017 Laura Ragone // . . . // Create another `DateComponents` by incrementing the appropriate component. let endDateComponents = DateComponents(calendar: calendar, timeZone: calendar.timeZone, month: currentDateComponents.month, // Did I mention individual date components are optional? weekOfYear: currentDateComponents.weekOfYear! + 1, yearForWeekOfYear: currentDateComponents.yearForWeekOfYear) // Finally, create the end `Date` object. let endDate = calendar.date(from: endDateComponents)
  19. Defining Date Intervals: This weekend iOSoHo - November 2017 Laura

    Ragone // ... case .thisWeekend: if calendar.isDateInWeekend(currentDate) { return calendar.dateIntervalOfWeekend(containing: currentDate) } else { return calendar.nextWeekend(startingAfter: currentDate) } // ...
  20. Test Driven Development (TDD) Tests are written in advance of

    the code 1 2 Code is revised until all tests pass iOSoHo - November 2017 Laura Ragone
  21. Dependency Injection Decouples code from other dependencies, like instances controlled

    at the system level 1 2 Method Injection + default parameters = iOSoHo - November 2017 Laura Ragone
  22. Dependency Injection iOSoHo - November 2017 Laura Ragone func dateInterval(from

    currentDate: Date = Date(), in calendar: Calendar = .current) -> DateInterval? { // ... } let _ = DateFilter.thisWeekend.dateInterval()
  23. iOSoHo - November 2017 Laura Ragone DATE FORMATTERS Common Pitfalls

    Beware off-by-one errors when formatting dates for display Every nanosecond counts!
  24. iOSoHo - November 2017 Laura Ragone • Time filters •

    Any time • Morning • Afternoon • Evening • Night FIND EVENTS BY DATE AND TIME Filtered Meetups
  25. • Dayparts vary by language and locale • Time intervals

    associated with dayparts differ Time Filters iOSoHo - November 2017 Laura Ragone
  26. <dayPeriodRules locales="en"> <dayPeriodRule type="midnight" at="00:00"/> <!-- midnight --> <dayPeriodRule type="noon"

    at="12:00"/> <!-- noon --> <dayPeriodRule type="morning1" from="06:00" before="12:00"/> <!-- morning --> <dayPeriodRule type="afternoon1" from="12:00" before="18:00"/> <!-- afternoon --> <dayPeriodRule type="evening1" from="18:00" before="21:00"/> <!-- evening --> <dayPeriodRule type="night1" from="21:00" before="06:00"/> <!-- night --> </dayPeriodRules> CLDR: TL;DR iOSoHo - November 2017 Laura Ragone
  27. A Wrinkle in Time: Reverse Intervals iOSoHo - November 2017

    Laura Ragone <dayPeriodRule type="night1" from="21:00" before="06:00"/> <!-- night -->
  28. <dayPeriodRules locales="de"> <dayPeriodRule type="midnight" at="00:00"/> <!-- Mitternacht --> <dayPeriodRule type="morning1"

    from="05:00" before="10:00"/> <!-- Morgen —> <dayPeriodRule type="morning2" from=“10:00" before="12:00"/> <!-- Vormittag --> <dayPeriodRule type="afternoon1" from="12:00" before="13:00"/> <!-- Mittag —> <dayPeriodRule type="afternoon2" from="13:00" before="18:00"/> <!-- Nachmittag --> <dayPeriodRule type="evening1" from="18:00" before="24:00"/> <!-- Abend --> <dayPeriodRule type="night1" from="00:00" before="05:00"/> <!-- Nacht --> </dayPeriodRules> A Wrinkle in Time: 24:00 iOSoHo - November 2017 Laura Ragone
  29. • Considerations when working with dates and times in an

    international app • Common pitfalls to avoid • TDD and Dependency Injection Today, we discussed… iOSoHo - November 2017 Laura Ragone
  30. • Your Calendrical Fallacy is… - Knowledge paddles • http://yourcalendricalfallacyis.com

    • CLDR Day Periods - Unicode standardized time ranges • http://www.unicode.org/cldr/charts/32/supplemental/day_periods.html • Solutions to Common Date and Time Challenges - WWDC 2013: Session 227 • https://developer.apple.com/videos/play/wwdc2013/227/ Additional Resources iOSoHo - November 2017 Laura Ragone