[][src]Crate relativedelta

relativedelta: Relative date time representation for smart date calculations


Put this in your Cargo.toml:

relativedelta = "0.2"

Optional features:

  • serde1: Enable serialization/deserialization via serde.


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 update 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));


pub use crate::relativedelta::RelativeDelta;