# Announcing Time 1.0.0: Type-safe Calendar Calculations

**URL:** <https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366>\
**Category:** Community Showcase\
**Created:** [February 29, 2024, 4:19pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366 "2024-02-29T16:19:03Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![davedelong](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davedelong/32/38708_2.png) [@davedelong](https://forums.swift.org/u/davedelong)\
**Post date:** [February 29, 2024, 4:19pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/1 "2024-02-29T16:19:03Z")

</div>

[Four years ago](https://forums.swift.org/t/introducing-time/34196) I introduced **Time** 0.9.0. It is appropriate that today, on its first birthday, it finally graduates to `1.0.0`! 🥳

**Time** is a package that provides extensive functionality for performing date and time calculations. It is built with _safety_ and _convenience_ in mind, so that "correct" calculations are easy, and "wrong" operations are either not possible (thanks to Swift's type system) or throw an error.

**Time** is [available on Github](https://github.com/davedelong/time), and its extensive documentation is hosted at [the Swift Package Index](https://swiftpackageindex.com/davedelong/time).

Here's a brief overview of what **Time** can do for you:

```swift
// get the current device time:
let instantaneousNow = Clocks.system.now

// get the current calendar minute, a "Fixed<Minute>":
let currentMinute = Clocks.system.currentMinute

// round the current minute to the nearest quarter-hour:
let quarterHour = currentMinute.roundedToNearestMultiple(of: .minutes(15))

// advance the quarter hour by two months (accurate to the minute):
let thisTimeInTwoMonths = quarterHour + .months(2)

// from the quarter hour, get its calendar day:
let today = currentMinute.fixedDay

// get a Sequence of all the hours in the day:
let hours = today.hours

// print information about the hours in the day:
for hour in hours {
    // there are many ".format(...)" methods to handle just about any use-case
    print(hour.format(date: .medium, time: .long))
}

// be notified about the next 10 clock seconds:
for try await aSecond in Clocks.system.strike(every: Second.self).asyncValues.prefix(10) {

    let formatted = aSecond.format(year: .naturalDigits, month: .naturalName, day: .naturalDigits, weekday: .naturalName, hour: .naturalDigits, minute: .twoDigits, second: .twoDigits)
    
    print("The time is now: ", formatted)
}

```

All "fixed values" keep track of their calendar, locale, and time zone, enabling you to easily work with calendar values from around the world with the knowledge that their relative calculations are correct.

Beyond this, **Time** has numerous other capabilities, including:

- Creating clocks in any combination of calendar, locale, or time zone
- Creating clocks that move faster or slower than real time to facilitate testing time-dependent code
- Adopting the `RegionalClock` protocol to create your own clocks for controlling time
- Listening for time changes via a Combine publisher or AsyncSequence
- Retrieving the `Range<Instant>` for any calendar value
- Converting calendar values between time zones, locales, and calendars
- Truncating calendar values to get their containing units
- Finding differences between calendar values
- Offsetting (adjusting) calendar values by specific amounts
- And so much more!

---

<div class="post-metadata">

**Author:** ![hassila](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hassila/32/22647_2.png) [@hassila](https://forums.swift.org/u/hassila)\
**Post date:** [February 29, 2024, 5:48pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/2 "2024-02-29T17:48:58Z")

</div>

@davedelong I must say I love the timing of the releases, looking forward to 1.1 in 4 years 😂

---

<div class="post-metadata">

**Author:** ![maartene](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/maartene/32/42076_2.png) [@maartene](https://forums.swift.org/u/maartene)\
**Post date:** [February 29, 2024, 7:30pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/3 "2024-02-29T19:30:06Z")

</div>

Off course we had a sev 2 incident at work today, because a (non Swift) system could not cope with todays leap day. 😓

Sooo... due to the auspicious timing of this release, this is not something we should have to worry about with this package?

---

<div class="post-metadata">

**Author:** ![rhx](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rhx/32/14647_2.png) [@rhx](https://forums.swift.org/u/rhx)\
**Post date:** [February 29, 2024, 8:56pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/4 "2024-02-29T20:56:37Z")

</div>

Very nice, this is really great! Given the release date, I had to run some experiments, of course:

```swift
import Time

let startingPoint = try! Fixed(region: .current, year: 2024, month: 2, day: 29)
print("\(startingPoint.year)-\(startingPoint.month)-\(startingPoint.day)") // 2024-2-29

let twentyFive = startingPoint + .years(1)
print("\(twentyFive.year)-\(twentyFive.month)-\(twentyFive.day)") // 2025-2-28

let twentyFive2 = startingPoint.adding(years: 1)
print("\(twentyFive2.year)-\(twentyFive2.month)-\(twentyFive2.day)") // 2025-2-28

let twentyFive3 = startingPoint + .days(366)
print("\(twentyFive3.year)-\(twentyFive3.month)-\(twentyFive3.day)") // 2025-3-1

let twentyEight = startingPoint + .years(4)
print("\(twentyEight.year)-\(twentyEight.month)-\(twentyEight.day)") // 2028-2-29

let twentyEight2 = startingPoint + .years(1) + .years(1) + .years(1) + .years(1)
print("\(twentyEight2.year)-\(twentyEight2.month)-\(twentyEight2.day)") // 2028-2-28

```

Is there a way to do leap year aware calculations based on context? I.e., I would have hoped that `twentyFive2` might give me the same result as `twentyFive3`.

---

<div class="post-metadata">

**Author:** ![davedelong](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davedelong/32/38708_2.png) [@davedelong](https://forums.swift.org/u/davedelong)\
**Post date:** [February 29, 2024, 9:20pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/5 "2024-02-29T21:20:11Z")

</div>

Essentially, no. There's a semantic distinction between "adding one year" and "adding 366 days". The implementation of that distinction is left up to the underlying libicu library which Foundation wraps.

(It's also worth pointing out that **Time** supports calendars where the years are much shorter than 365 days)

---

<div class="post-metadata">

**Author:** ![kiel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kiel/32/1392_2.png) [@kiel](https://forums.swift.org/u/kiel)\
**Post date:** [February 29, 2024, 10:47pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/6 "2024-02-29T22:47:34Z")

</div>

Whoa, calendrical computations without the optionals. Looks like the calendar API we all wish Foundation offered. Thanks for sharing your effort, @davedelong!

---

<div class="post-metadata">

**Author:** ![AliSoftware](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alisoftware/32/2764_2.png) [@AliSoftware](https://forums.swift.org/u/AliSoftware)\
**Post date:** [March 1, 2024, 6:34pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/7 "2024-03-01T18:34:46Z")

</div>

@davedelong Time to update the very last entry of your [https://yourcalendricalfallacyis.com/](https://yourcalendricalfallacyis.com/) site to suggest using `Time` instead of `NSCalendar` API 😛

---

<div class="post-metadata">

**Author:** ![davedelong](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/davedelong/32/38708_2.png) [@davedelong](https://forums.swift.org/u/davedelong)\
**Post date:** [March 14, 2024, 3:24pm UTC](https://forums.swift.org/t/announcing-time-1-0-0-type-safe-calendar-calculations/70366/8 "2024-03-14T15:24:23Z")

</div>

Done! It's also using some nifty new stuff from @benscheirman to dynamically format timestamps in different calendars 😁
