Introducing "Time"

Today is Leap Day, so I'd like to introduce you to a new Swift package I've been working on for over 2 years:

Time is a package that makes date and time calculations more expressive and safe in Swift. It's built on the power of Foundation's APIs, but smooths away their many rough and ambiguous edges. It relies heavily on Swift's generics to guarantee that the calculations you're performing are calendrically correct. If you'd like an overview of how it works, be sure to check out the documentation.

I'm releasing it today as an 0.9.0 version. I hope you will clone it and use it in your apps!

54 Likes

Soā€¦how do you feel about bikeshedding?

It's a fun diversion. What's on your mind?

1 Like

Well first off, having read through the documentation, Iā€™m wondering what the rationale is for choosing the spelling clock.thisInstant() instead of clock.now().

And second, I think some of the type names are not specific enough, including Absolute, Value, Difference, and AbsoluteValueSequence.

3 Likes

It actually has both:

https://github.com/davedelong/time/blob/master/Sources/Time/3.%20Clock/Clock%2BCurrentValues.swift#L13

now() is the same thing as thisInstant(). It has both because now() is the "proper" naming, but thisInstant() also helps it be consistent with thisDay(), thisMonth(), thisSecond(), etc.

Naming has been my #1 most difficult task with this framework. If you look on the "Roadmap" page, you'll see that I definitely want to rename Value, but only if I can find something better. I've spent weeks scouring sources for more definitive names for "a subset of calendrical values that may or may not be anchored to an actual calendrical point", but haven't come up with anything that really feels "better".

Difference used to be Delta; I renamed it in the hopes that Difference would be a bit clearer. Absolute (and the WIP Relative) used to be Anchored and Floating. AbsoluteValueSequence is basically just derived from Absolute.

I'm absolutely open to suggestions on better names. I'd prefer names that are terms-of-art, but I have yet to find such nomenclature.

9 Likes

Yeah, I donā€™t know what the types should be named, but I think the names should at least indicate that they have something to do with time. Spellings like Value, Difference, Anchored, and Delta seem too general-purpose, especially when used in an app that imports many different libraries.

2 Likes

To be fair, the names are all technically namespaced within the module, so we're really talking about a Time.Value, a Time.Difference, a Time.Absolute, etc..

But yes, in principle I agree. The current names are the "least bad" ones I've been able to come up with. :smile:

3 Likes

Sure, you can write Time.Value, but you donā€™t have to and most people wonā€™t. So itā€™ll just be ā€œValueā€ at the point of use.

After all, how often do you see Swift.Array (or any other type) written in the wild?

2 Likes

FWIW, the lack of a better name for Value and friends is also why this is 0.9.0 and not 1.0.0...

9 Likes

This looks super interesting!

From reading the documentation, I have one comment, and thatā€™s that your usage of the term ā€unsafeā€ seems to be at odds with how itā€™s generally used in Swift.

ā€Unsafeā€ in Swift generally refers to memory safety. For example, in the Standard Library unsafe in the name of a type, method or parameter means that Swiftā€™s standard guarantee of memory safety no longer applies, and unless you know what youā€™re doing you might have memory leaks, memory corruption or even undefined behavior on your hands.

You seem to be using ā€unsafeā€ to mean that an adjustment may throw. Thatā€™s not the same. To someone accustomed to the Standard Libraryā€™s usage of ā€unsafeā€, it makes these adjustments look much scarier than they actually are.

12 Likes

This looks really cool, great job! :tada:

Skimmed through the code a bit and it seems quite serious in tackling the calendar weirdnesses, that's great :slight_smile: The topic of time/calendars is such a complete minefield... :sweat:

Have you considered using Time/AbsoluteTime or RelativeTime/Time instead of Value and Absolute respectively?

(In my own Calendar library I have Day/Month/etc... and RelativeDay/RelativeMonth/etc...)

I havenā€˜t read the code, but I noticed some APIā€˜s mentioned upthread.

Why are some of the operations methods (e.g. .now())?

I believe in Dispatch that was a mistake that got stuck on us forever. Could we change those into properties? The parentheses are really redundant.

I'd push back against this one. IMO properties ought to produce the same value when accessed repeatedly unless there's some intervening (imperative) logic.

28 Likes

Fair point. I canā€˜t remember a case where this wasnā€˜t true either. :thinking:

1 Like

There's been some discussion about this in one of the issues on GH: All zero-argument methods that return a value should be computed properties instead Ā· Issue #7 Ā· davedelong/time Ā· GitHub

1 Like

If you have alternative naming suggestions, I'd love to hear them. :slight_smile:

1 Like

The name that comes to mind is FailableAdjustment, since thatā€™s essentially what they are: adjustments that can fail. I guess you could argue that ā€failableā€ also means that they should return nil instead of throw, since thatā€™s what failable means when we talk about initializers. I donā€™t have enough experience with the API yet to know if that would make sense. Regardless, something ā€failableā€ that doesn't return nil seems to me a lesser sin than something ā€unsafeā€ thatā€™s completely memory safe.

There are different kinds of "safe" in Swift. There's the memory safety you've brought up, but there's also type safety, the safety of exhaustiveness checking, etc.

It's true that "unsafe" has typically only referred to memory safety, but given then other kinds of "safety" guarantees that Swift provides, it seems reasonable to me to use the same term here.

However, I'm absolutely willing to change it if we can come up with a superior name. :slight_smile:

We can just drop Unsafe. throws-ness signals plenty enough of that. And while I agree that there are multiple kinds of safety in swift, Unsafe is still used exclusively for memory safety.

19 Likes