#datetime #relative #calendar #chrono #deltatime


Rust implementation of relativedelta known from Python’s dateutil library. An extension to Duration in the chrono library to deal with relative dates

2 releases

0.2.2 Aug 27, 2020
0.2.1 Aug 22, 2020
0.2.0 Aug 21, 2020
0.1.0 Aug 20, 2020

#47 in Date and time

31 downloads per month


875 lines


Travis Status License crates.io codecov.io

Rust implementation of relativedelta known from Python's dateutil library. Extension to the Duration from the the time library, which allows for calculating datetimes based on a relative representation of date and time.


Put this in your Cargo.toml:

relativedelta = "0.2"

Optional features

  • serde1: Enable serialization/deserialization via serde.

In the pipeline:

  • Hook up to travis.com.
  • Mitigation of month rounding error when init with floats or mul with floats.
  • Create a proper crate and publish on crates.io.
  • Documentation and doctest.
  • Code coverage setup and badge with travis.com and codecov.io


The RelativeDelta datatype holds both relative and absolute values for year, month, day, hour, minute, seconds and nanosecond.

Relative parts are manipulated and accessed through methods typically ending in "s" (e.g. ::with_years, .and_days). Absolute values without "s".

All relative values represents an offset to date and time and therefore can take on both positive and negative values, and can take on any value within its datatypes limitations. On creation, the Builder will attempt to aggregate values up, so e.g. if hours are not in the range [-23;23], the datatype will be updated to instead add or subtract extra days, with only the remainder as hours. All offsets are set to zero as default.

Absolute values represents explicit years, months, days and so on. So if one e.g. always seeks a certain day in the month, one would use the ::with_month or .and_month method. All absolute values are Options and set to None as default.

RelativeDelta also holds a weekday value, which is an Option of a tuple with (Weekday, nth). This allows one to e.g. ask for the second tuesday one year from today, with Utc::now() + RelativeDelta::with_years(1).and_weekday(Some(Weekday::Tue, 2)).new().


// Construction
let years1 = RelativeDelta::with_years(1).new();
let months12 = RelativeDelta::with_months(12).new();
assert_eq!(years1, months12);

let years1 = RelativeDelta::with_years(1).and_days(32).new();
// If same parameter is specified twice, only the latest is applied.
let months6 = RelativeDelta::with_months(12).with_months(6).new();
assert_eq!(months6, RelativeDelta::with_months(6).new());
// Below is identical to: RelativeDelta::yysmmsdds(Some(2020), 1, Some(1), 3, None, 12).new();
let rddt = RelativeDelta::with_year(2020).and_years(1).and_month(Some(1)).and_months(3).and_days(12).new();

// Two or more RelativeDeltas can be added and substracted. However, note that constants are lost in the process.
let lhs = RelativeDelta::yysmmsdds(Some(2020), -4, Some(1), 3, None, 0).new();
let rhs = RelativeDelta::yysmmsdds(Some(2020), 1, Some(1), 42, None, 0).new();
assert_eq!(lhs + rhs, RelativeDelta::with_years(-3).and_months(45).new());
assert_eq!(lhs - rhs, RelativeDelta::with_years(-5).and_months(-39).new());
assert_eq!(-lhs + rhs, RelativeDelta::with_years(5).and_months(39).new());

// The RelativeDelta can be multiplied with a f64.
assert_eq!(rhs * 0.5, RelativeDelta::with_years(2).and_year(Some(2020)).and_months(3).and_month(Some(1)).new());

// This crates party piece is the ability to calculate dates based on already existing chrono::DateTime
// If one would like to get the last day of the month that one is currently in, it could be done with:
println!("{}", Utc::now() + RelativeDelta::with_day(1).and_months(1).and_days(-1).new());
// Above first sets the day of the month to the 1st, then adds a month and subtracts a day.

// One could also request the first monday after one year by
let first_monday_after_one_year = RelativeDelta::with_years(1).and_weekday(Some((Weekday::Mon, 1))).new();
let d = Utc.ymd(2020, 1, 1).and_hms(0,0,0) + first_monday_after_one_year;
assert_eq!(d, Utc.ymd(2021, 1, 4).and_hms(0,0,0));


~17K SLoC