1 Mississippi, 2 Mississippi…

Where I learn about crates and modules and time… and sheep

Recycle logo on bag
Re-use code to make their owners proud!

Let’s learn about stealing reusing code! Rust has a developing library of code, from contributors, that you pull into your own programs and then not have to reinvent the wheel. Perl calls these modules and has CPAN as a repository and for searches, updates, and documentation. In Rust, these are instead called library crates and you can look around at the crates.io repository and others – plus create your own, internal repositories.

Searching Through Crates

For instance, go to crates.io and search for “chrono“. You should come to the chrono crates.io page. Right now, I’m seeing the most recent version as 0.4.7. Note if you had searched for “date time” instead, you’ll find many results, and the one with the huge number of downloads is chrono!

Like CPAN, crates.io can tell you the latest version (and how recent it is), if the current build of the crate is passing tests, usage information, and more. Note that if you click on the documentation link on the chrono crate page, you are taken to the docs.rs page: docs.rs/chrono/0.4.6/chrono/ and can read the full documentstion.

Now, we come to the term modules as it applies to Rust. A Rust crate has a default module, but can also have additional modules, providing additional features. For instance, from the docs.rs page about chrono, click modules on the left-side and you will see which modules are a part of chrono: format, naive, offset, prelude, and serde. We won’t need any of those additional modules, just some pieces of what the default chrono crate provides.

Rust Chrono Crate

Sheep and lamb looking at us
One second for every sheep in the world – plus some sheep left over.

I see our next Exercism problem uses the chrono crate in the solution (coincidence?!) Let’s take a look! So, they want us to display the date and time when 1 Gigasecond, from a given date and time, would occur. That is, given a date and time, figure out the date and time 1,000,000,000 seconds later. Who needs this? I dunno, but who cares about that.

Looking in the tests/gigasecond.rs file from Exercism, where the tests for this package are stored, the first one will be giving our code Utc.ymd(2011, 4, 25).and_hms(0, 0, 0) and expecting back Utc.ymd(2043, 1, 1).and_hms(1, 46, 40). Looks like a gigasecond is just shy of 32 years. If we check tests by running cargo test, we can see, of course, that it fails – we haven’t done any work yet!




Crate Semantic Versioning

Exercism did help us out though – they had already figured out the most popular crate to use for date/time types and added it as a dependency to our project. Check out the included Cargo.toml file and notice the one dependency at the end: chrono = “0.4”. Cargo looks on crates.io by default, and the version number listed is a semver (for semantic versioning). It is like a pattern to be used to determine which versions are allowed to be used for this project. In this case, specifying 0.4 means the latest 0.4.x version of the library should be pulled (so it will pull the 0.4.7 version we saw as the latest), but Cargo will not advance to 0.5. You’d have to test 0.5 and, if your code still works, modify your toml file manually. This prevents a potentially major upgrade of a library to suddenly break your code in your production deployment cycle.

Geese
We don’t tweet, we jabber – but not about Rust!

Enough jabbering – with all of the help (and documentation) chrono gives us, and all that background knowledge, I turn this into a single expression like prior problems we’ve had:

 use chrono::{DateTime, Utc, Duration}; 

 pub fn after(start: DateTime) -> DateTime {
     start + Duration::seconds(1_000_000_000)
 }

Exercism gave us use chrono::{DateTime, Utc}; in the answer already, I just tacked on “, Duration” when I realized I needed that struct of the chrono crate as well. We are passed in the parameter start, we add 1,000,000,000 seconds as a Duration type. Then the expression calculates and returns a DateTime result.

We could have written this without the use statement but I hope you’ll see its help in shortening the code is worth it:

 pub fn after(start: chrono::DateTime)
 -> chrono::DateTime {
     start + chrono::Duration::seconds(1_000_000_000)
 }

Light’s Green, Trap is Clean

Anyway, running cargo test now is green! We also run cargo test — –ignored to run all of the additional tests the Exercism team wrote, and they all pass as well!

So, another simple answer – but ONLY because someone went to all the trouble of DateTime and Duration processing and manipulation!