Chrono 0.3 released, and the future


#1

So Chrono 0.3.0, a much delayed major version of Rust date and time library, is here. Update and watch your build breaking Enjoy.

Breaking Changes

I have described all changes to the changelog but the recent issue seems to indicate that it is not enough. So the following is the list of breaking changes primarily relevant to the users.

  • Rust 1.13.0 or later is required.

    As we have moved to Serde 0.9, we have bumped the minimal supported version to 1.13.0. It is possible to use Chrono on older versions with or without Serde (previously 1.8.0 was the minimal, and Serde 0.9 seems to work well with 1.12.0) but they are no longer supported now.

  • The subtraction between two time instants/points is gone.

    You should use a.signed_duration_since(b) instead of a - b. As you can expect, this name is very similar to the standard library’s one, but returns time::Duration instead of std::time::Duration. The proper name, duration_since has been reserved for the transition.

    (As aside, I don’t think that the subtraction operator in this case will return. It is very awkward to return Result<Duration, NegativeDuration> from an operator, and risking the panic every time one subtract two normal points seems to be unreasonable.)

    I don’t know if these methods are used a lot, but checked_{add,sub} and overflowing_{add,sub} methods had met the same fate: They are now called checked_{add,sub}_signed and overflowing_{add,sub}_signed, respectively. The older names are reserved for the transition.

  • Rustc-serialize support is now exactly identical to the counterpart for Serde.

    Previously two implementations didn’t agree to each other primarily because they are written by different contributors. Now they standardize on the std::fmt::Debug output, previously used by Serde implementations. This will cause the format change if you are using rustc-serialize to read and write a long lasting format, so you should be prepared for it.

    Rustc-serialize implementations actually covered more types than Serde in the past. They are now removed—more specifically, Date<Tz> and all offset types (DateTime<Tz> support is rewritten per each Tz). While it is not very trivial to reintroduce them in a sane manner, this removal should be considered temporary.

Near Future

This release contains lots of other minor breaking changes to allow more changes without breaking the compatibility. (Many fixes were blocked by them, for instance.)

The most significant one is that we no longer use Duration (that is, time::Duration) for representing the time zone offset. It might sound strange but Offset is the “storage” offset type and Offset::local_minus_utc used to return the Duration for the offset “value”. Now the offset “value” is represented by FixedOffset (which is also a stroage type by its own), which has a good side effect that the offset is guaranteed to be within one day. In my experience this was a single biggest problem in implementing advanced time zone support—I expect this can be done much better by now.

We have also sorted out any types that were too public to be extended without breaking changes. For 0.3.0 they consist solely of formatting types, and they have received a private (dummy) field for the future expansion. We can now extend formatting (privately) without breaking public interfaces.

Far Future

There are two major concerns in the far future (I mean, next year or so) of Chrono.

First, Chrono will become a community project at last. I had initiated and maintained the project so far, but in the last year (2016) I had significant energy depletion that has prevented me to do anything that is not a daily job (as you may know, I also use Rust at work). Not that I think that the current version is good enough—I’ve resolved many required breaking changes I was aware of during the 0.3.0 release for example.

The Chronotope organization is, I think, the major step towards the community project, but that is not enough. I have reserved it in the past, but I invite you to #chronotope IRC channel at irc.mozilla.org. Also I’m willing to invite more contributors and relevant projects to the organization (chrono-tz comes to my mind). I’m not sure how to start but having a venue for the discussion could be a good start.

Second, Chrono will set the official relationship to the standard library types. std::time::Duration support is the beginning, and what I’m most concerned is std::time::SystemTime.

In the past I thought that the time library will be kept as is and Chrono will fill the niche gap. The situation has changed—SystemTime no longer concerns about the calendar time. This means that the Chrono date and time types should be a canonical type for the calendar time while also filling the niche. This discrepancy was a source of design issues:

  • People seems to use DateTime<Tz> as a primary storage type, rather than as an alternative type used for formatting and calculation.

  • While it is designed to be much faster than alternatives, Chrono’s main representation still is a calendar time and causes overhead when you don’t need that. SystemTime::now() is at least 10x faster than UTC::now().

  • The TimeZone type parameter is a source of many complaints. The original design was selected so that we don’t have to deal with the synchronization or sharing issue, and also we can get the needed information for date and time calculation, but my observation is that calculation is less used than formatting.

There are several approaches to solve them, and I have one particular approach in mind—removing a TimeZone parameter at all and delegating all tz-aware operation to the external object. The alternative datetime library seems to explore another possibiltiy (to make the time zone object internal) as well. No matter which design is selected, I believe this needs many eyes to perfect, and want to gather users’ feedback as well.


#2

Thank you for this release. I am actually the one who didn’t see the subtraction change in the ChangeLog–sorry about that!

I was wondering how to contribute/be involved in the future? I find the TimeZone parameter to be very useful, as I deal with data that comes from different timezones, and conversion issues are a major headache. I’d like to extend it to be more powerful, rather than plan to remove it. My use cases don’t use the library for formatting or parsing, but for data analysis, and the type parameter has been incredibly useful for statically removing a big class of errors.


#3

@lifthrasiir thanks for the thorough update and all your ongoing work on chrono. It’s a core piece of Rust infrastructure. As we all know, maturing core Rust crates is a key goal this year, and I’m hoping together we can all make chrono really solid.


#4

(Small nit-pick, but 0.3.0 would be a minor release in semver. major.minor.patch.)


#5

From the semver spec:

Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.

Still, the convention that I’ve seen is to bump the most-significant non-zero number when making a breaking change.


#6

As @cramertj has pointed out it’s just a matter of convention. However Cargo does consider 0.x.y to be compatible to 0.x.y’, so I guess it’s fine to call 0.x.0 as a “pre-1.0 major version”.


#7

You are right—not having a time zone inside the type is slightly more error-prone.

Why I’m thinking of removing the time zone data is that you can add a wrapper type when you don’t have a time zone inside but you cannot remove the time zone data from the existing type. In this design, we would have a main DateTime type that would be structurally isomorphic to today’s DateTime<FixedOffset> but any operation needs to be done via the external TimeZone type, and also a ZonedDateTime wrapper type which contains both DateTime and Arc<TimeZone> (or so) so that the operator overloading works as expected. Not having operator overloading in the main type would reduce errors from any confusion.

(As always, take this design with a grain of salt; I haven’t analyzed its effectiveness yet.)