Struct Date

struct Date { ... }

A representation of a civil date in the Gregorian calendar.

A Date value corresponds to a triple of year, month and day. Every Date value is guaranteed to be a valid Gregorian calendar date. For example, both 2023-02-29 and 2023-11-31 are invalid and cannot be represented by a Date.

Civil dates

A Date value behaves without regard to daylight saving time or time zones in general. When doing arithmetic on dates with spans defined in units of time (such as with Date::checked_add), days are considered to always be precisely 86,400 seconds long.

Parsing and printing

The Date type provides convenient trait implementations of std::str::FromStr and [std::fmt::Display]:

use jiff::civil::Date;

let date: Date = "2024-06-19".parse()?;
assert_eq!(date.to_string(), "2024-06-19");

# Ok::<(), Box<dyn std::error::Error>>(())

A civil Date can also be parsed from something that contains a date, but with perhaps other data (such as an offset or time zone):

use jiff::civil::Date;

let date: Date = "2024-06-19T15:22:45-04[America/New_York]".parse()?;
assert_eq!(date.to_string(), "2024-06-19");

# Ok::<(), Box<dyn std::error::Error>>(())

For more information on the specific format supported, see the fmt::temporal module documentation.

Default value

For convenience, this type implements the Default trait. Its default value corresponds to 0000-01-01. One can also access this value via the Date::ZERO constant.

Comparisons

The Date type provides both Eq and Ord trait implementations to facilitate easy comparisons. When a date d1 occurs before a date d2, then d1 < d2. For example:

use jiff::civil::date;

let d1 = date(2024, 3, 11);
let d2 = date(2025, 1, 31);
assert!(d1 < d2);

Arithmetic

This type provides routines for adding and subtracting spans of time, as well as computing the span of time between two Date values.

For adding or subtracting spans of time, one can use any of the following routines:

Additionally, checked arithmetic is available via the Add and Sub trait implementations. When the result overflows, a panic occurs.

use jiff::{civil::date, ToSpan};

let start = date(2024, 2, 25);
let one_week_later = start + 1.weeks();
assert_eq!(one_week_later, date(2024, 3, 3));

One can compute the span of time between two dates using either Date::until or Date::since. It's also possible to subtract two Date values directly via a Sub trait implementation:

use jiff::{civil::date, ToSpan};

let date1 = date(2024, 3, 3);
let date2 = date(2024, 2, 25);
assert_eq!(date1 - date2, 7.days().fieldwise());

The until and since APIs are polymorphic and allow re-balancing and rounding the span returned. For example, the default largest unit is days (as exemplified above), but we can ask for bigger units:

use jiff::{civil::date, ToSpan, Unit};

let date1 = date(2024, 5, 3);
let date2 = date(2024, 2, 25);
assert_eq!(
    date1.since((Unit::Year, date2))?,
    2.months().days(7).fieldwise(),
);

# Ok::<(), Box<dyn std::error::Error>>(())

Or even round the span returned:

use jiff::{civil::{DateDifference, date}, RoundMode, ToSpan, Unit};

let date1 = date(2024, 5, 15);
let date2 = date(2024, 2, 25);
assert_eq!(
    date1.since(
        DateDifference::new(date2)
            .smallest(Unit::Month)
            .largest(Unit::Year),
    )?,
    2.months().fieldwise(),
);
// `DateDifference` uses truncation as a rounding mode by default,
// but you can set the rounding mode to break ties away from zero:
assert_eq!(
    date1.since(
        DateDifference::new(date2)
            .smallest(Unit::Month)
            .largest(Unit::Year)
            .mode(RoundMode::HalfExpand),
    )?,
    // Rounds up to 8 days.
    3.months().fieldwise(),
);

# Ok::<(), Box<dyn std::error::Error>>(())

Rounding

Rounding dates is currently not supported. If you want this functionality, please participate in the issue tracking its support.

Implementations

impl Date

fn new(year: i16, month: i8, day: i8) -> Result<Date, Error>

Creates a new Date value from its component year, month and day values.

To set the component values of a date after creating it, use DateWith via Date::with to build a new Date from the fields of an existing date.

Errors

This returns an error when the given year-month-day does not correspond to a valid date. Namely, all of the following must be true:

  • The year must be in the range -9999..=9999.
  • The month must be in the range 1..=12.
  • The day must be at least 1 and must be at most the number of days in the corresponding month. So for example, 2024-02-29 is valid but 2023-02-29 is not.

Example

This shows an example of a valid date:

use jiff::civil::Date;

let d = Date::new(2024, 2, 29).unwrap();
assert_eq!(d.year(), 2024);
assert_eq!(d.month(), 2);
assert_eq!(d.day(), 29);

This shows an example of an invalid date:

use jiff::civil::Date;

assert!(Date::new(2023, 2, 29).is_err());
const fn constant(year: i16, month: i8, day: i8) -> Date

Creates a new Date value in a const context.

Panics

This routine panics when Date::new would return an error. That is, when the given year-month-day does not correspond to a valid date. Namely, all of the following must be true:

  • The year must be in the range -9999..=9999.
  • The month must be in the range 1..=12.
  • The day must be at least 1 and must be at most the number of days in the corresponding month. So for example, 2024-02-29 is valid but 2023-02-29 is not.

Example

use jiff::civil::Date;

let d = Date::constant(2024, 2, 29);
assert_eq!(d.year(), 2024);
assert_eq!(d.month(), 2);
assert_eq!(d.day(), 29);
fn from_iso_week_date(weekdate: ISOWeekDate) -> Date

Construct a Gregorian date from an ISO 8601 week date.

The ISOWeekDate type describes itself in more detail, but in breif, the ISO week date calendar system eschews months in favor of weeks.

The minimum and maximum values of an ISOWeekDate correspond precisely to the minimum and maximum values of a Date. Therefore, converting between them is lossless and infallible.

This routine is equivalent to ISOWeekDate::date. It is also available via a From<ISOWeekDate> trait implementation for Date.

Example

This shows a number of examples demonstrating the conversion from an ISO 8601 week date to a Gregorian date.

use jiff::civil::{Date, ISOWeekDate, Weekday, date};

let weekdate = ISOWeekDate::new(1994, 52, Weekday::Sunday).unwrap();
let d = Date::from_iso_week_date(weekdate);
assert_eq!(d, date(1995, 1, 1));

let weekdate = ISOWeekDate::new(1997, 1, Weekday::Tuesday).unwrap();
let d = Date::from_iso_week_date(weekdate);
assert_eq!(d, date(1996, 12, 31));

let weekdate = ISOWeekDate::new(2020, 1, Weekday::Monday).unwrap();
let d = Date::from_iso_week_date(weekdate);
assert_eq!(d, date(2019, 12, 30));

let weekdate = ISOWeekDate::new(2024, 10, Weekday::Saturday).unwrap();
let d = Date::from_iso_week_date(weekdate);
assert_eq!(d, date(2024, 3, 9));

let weekdate = ISOWeekDate::new(9999, 52, Weekday::Friday).unwrap();
let d = Date::from_iso_week_date(weekdate);
assert_eq!(d, date(9999, 12, 31));
fn with(self: Self) -> DateWith

Create a builder for constructing a Date from the fields of this date.

See the methods on DateWith for the different ways one can set the fields of a new Date.

Example

The builder ensures one can chain together the individual components of a date without it failing at an intermediate step. For example, if you had a date of 2024-10-31 and wanted to change both the day and the month, and each setting was validated independent of the other, you would need to be careful to set the day first and then the month. In some cases, you would need to set the month first and then the day!

But with the builder, you can set values in any order:

use jiff::civil::date;

let d1 = date(2024, 10, 31);
let d2 = d1.with().month(11).day(30).build()?;
assert_eq!(d2, date(2024, 11, 30));

let d1 = date(2024, 4, 30);
let d2 = d1.with().day(31).month(7).build()?;
assert_eq!(d2, date(2024, 7, 31));

# Ok::<(), Box<dyn std::error::Error>>(())
fn year(self: Self) -> i16

Returns the year for this date.

The value returned is guaranteed to be in the range -9999..=9999.

Example

use jiff::civil::date;

let d1 = date(2024, 3, 9);
assert_eq!(d1.year(), 2024);

let d2 = date(-2024, 3, 9);
assert_eq!(d2.year(), -2024);

let d3 = date(0, 3, 9);
assert_eq!(d3.year(), 0);
fn era_year(self: Self) -> (i16, Era)

Returns the year and its era.

This crate specifically allows years to be negative or 0, where as years written for the Gregorian calendar are always positive and greater than 0. In the Gregorian calendar, the era labels BCE and CE are used to disambiguate between years less than or equal to 0 and years greater than 0, respectively.

The crate is designed this way so that years in the latest era (that is, CE) are aligned with years in this crate.

The year returned is guaranteed to be in the range 1..=10000.

Example

use jiff::civil::{Era, date};

let d = date(2024, 10, 3);
assert_eq!(d.era_year(), (2024, Era::CE));

let d = date(1, 10, 3);
assert_eq!(d.era_year(), (1, Era::CE));

let d = date(0, 10, 3);
assert_eq!(d.era_year(), (1, Era::BCE));

let d = date(-1, 10, 3);
assert_eq!(d.era_year(), (2, Era::BCE));

let d = date(-10, 10, 3);
assert_eq!(d.era_year(), (11, Era::BCE));

let d = date(-9_999, 10, 3);
assert_eq!(d.era_year(), (10_000, Era::BCE));
fn month(self: Self) -> i8

Returns the month for this date.

The value returned is guaranteed to be in the range 1..=12.

Example

use jiff::civil::date;

let d1 = date(2024, 3, 9);
assert_eq!(d1.month(), 3);
fn day(self: Self) -> i8

Returns the day for this date.

The value returned is guaranteed to be in the range 1..=31.

Example

use jiff::civil::date;

let d1 = date(2024, 2, 29);
assert_eq!(d1.day(), 29);
fn weekday(self: Self) -> Weekday

Returns the weekday corresponding to this date.

Example

use jiff::civil::{Weekday, date};

// The Unix epoch was on a Thursday.
let d1 = date(1970, 1, 1);
assert_eq!(d1.weekday(), Weekday::Thursday);
// One can also get the weekday as an offset in a variety of schemes.
assert_eq!(d1.weekday().to_monday_zero_offset(), 3);
assert_eq!(d1.weekday().to_monday_one_offset(), 4);
assert_eq!(d1.weekday().to_sunday_zero_offset(), 4);
assert_eq!(d1.weekday().to_sunday_one_offset(), 5);
fn day_of_year(self: Self) -> i16

Returns the ordinal day of the year that this date resides in.

For leap years, this always returns a value in the range 1..=366. Otherwise, the value is in the range 1..=365.

Example

use jiff::civil::date;

let d = date(2006, 8, 24);
assert_eq!(d.day_of_year(), 236);

let d = date(2023, 12, 31);
assert_eq!(d.day_of_year(), 365);

let d = date(2024, 12, 31);
assert_eq!(d.day_of_year(), 366);
fn day_of_year_no_leap(self: Self) -> Option<i16>

Returns the ordinal day of the year that this date resides in, but ignores leap years.

That is, the range of possible values returned by this routine is 1..=365, even if this date resides in a leap year. If this date is February 29, then this routine returns None.

The value 365 always corresponds to the last day in the year, December 31, even for leap years.

Example

use jiff::civil::date;

let d = date(2006, 8, 24);
assert_eq!(d.day_of_year_no_leap(), Some(236));

let d = date(2023, 12, 31);
assert_eq!(d.day_of_year_no_leap(), Some(365));

let d = date(2024, 12, 31);
assert_eq!(d.day_of_year_no_leap(), Some(365));

let d = date(2024, 2, 29);
assert_eq!(d.day_of_year_no_leap(), None);
fn first_of_month(self: Self) -> Date

Returns the first date of the month that this date resides in.

Example

use jiff::civil::date;

let d = date(2024, 2, 29);
assert_eq!(d.first_of_month(), date(2024, 2, 1));
fn last_of_month(self: Self) -> Date

Returns the last date of the month that this date resides in.

Example

use jiff::civil::date;

let d = date(2024, 2, 5);
assert_eq!(d.last_of_month(), date(2024, 2, 29));
fn days_in_month(self: Self) -> i8

Returns the total number of days in the the month in which this date resides.

This is guaranteed to always return one of the following values, depending on the year and the month: 28, 29, 30 or 31.

Example

use jiff::civil::date;

let d = date(2024, 2, 10);
assert_eq!(d.days_in_month(), 29);

let d = date(2023, 2, 10);
assert_eq!(d.days_in_month(), 28);

let d = date(2024, 8, 15);
assert_eq!(d.days_in_month(), 31);
fn first_of_year(self: Self) -> Date

Returns the first date of the year that this date resides in.

Example

use jiff::civil::date;

let d = date(2024, 2, 29);
assert_eq!(d.first_of_year(), date(2024, 1, 1));
fn last_of_year(self: Self) -> Date

Returns the last date of the year that this date resides in.

Example

use jiff::civil::date;

let d = date(2024, 2, 5);
assert_eq!(d.last_of_year(), date(2024, 12, 31));
fn days_in_year(self: Self) -> i16

Returns the total number of days in the the year in which this date resides.

This is guaranteed to always return either 365 or 366.

Example

use jiff::civil::date;

let d = date(2024, 7, 10);
assert_eq!(d.days_in_year(), 366);

let d = date(2023, 7, 10);
assert_eq!(d.days_in_year(), 365);
fn in_leap_year(self: Self) -> bool

Returns true if and only if the year in which this date resides is a leap year.

Example

use jiff::civil::date;

assert!(date(2024, 1, 1).in_leap_year());
assert!(!date(2023, 12, 31).in_leap_year());
fn tomorrow(self: Self) -> Result<Date, Error>

Returns the date immediately following this one.

Errors

This returns an error when this date is the maximum value.

Example

use jiff::civil::{Date, date};

let d = date(2024, 2, 28);
assert_eq!(d.tomorrow()?, date(2024, 2, 29));

// The max doesn't have a tomorrow.
assert!(Date::MAX.tomorrow().is_err());

# Ok::<(), Box<dyn std::error::Error>>(())
fn yesterday(self: Self) -> Result<Date, Error>

Returns the date immediately preceding this one.

Errors

This returns an error when this date is the minimum value.

Example

use jiff::civil::{Date, date};

let d = date(2024, 3, 1);
assert_eq!(d.yesterday()?, date(2024, 2, 29));

// The min doesn't have a yesterday.
assert!(Date::MIN.yesterday().is_err());

# Ok::<(), Box<dyn std::error::Error>>(())
fn nth_weekday_of_month(self: Self, nth: i8, weekday: Weekday) -> Result<Date, Error>

Returns the "nth" weekday from the beginning or end of the month in which this date resides.

The nth parameter can be positive or negative. A positive value computes the "nth" weekday from the beginning of the month. A negative value computes the "nth" weekday from the end of the month. So for example, use -1 to "find the last weekday" in this date's month.

Errors

This returns an error when nth is 0, or if it is 5 or -5 and there is no 5th weekday from the beginning or end of the month.

Example

This shows how to get the nth weekday in a month, starting from the beginning of the month:

use jiff::civil::{Weekday, date};

let month = date(2017, 3, 1);
let second_friday = month.nth_weekday_of_month(2, Weekday::Friday)?;
assert_eq!(second_friday, date(2017, 3, 10));

# Ok::<(), Box<dyn std::error::Error>>(())

This shows how to do the reverse of the above. That is, the nth last weekday in a month:

use jiff::civil::{Weekday, date};

let month = date(2024, 3, 1);
let last_thursday = month.nth_weekday_of_month(-1, Weekday::Thursday)?;
assert_eq!(last_thursday, date(2024, 3, 28));
let second_last_thursday = month.nth_weekday_of_month(
    -2,
    Weekday::Thursday,
)?;
assert_eq!(second_last_thursday, date(2024, 3, 21));

# Ok::<(), Box<dyn std::error::Error>>(())

This routine can return an error if there isn't an nth weekday for this month. For example, March 2024 only has 4 Mondays:

use jiff::civil::{Weekday, date};

let month = date(2024, 3, 25);
let fourth_monday = month.nth_weekday_of_month(4, Weekday::Monday)?;
assert_eq!(fourth_monday, date(2024, 3, 25));
// There is no 5th Monday.
assert!(month.nth_weekday_of_month(5, Weekday::Monday).is_err());
// Same goes for counting backwards.
assert!(month.nth_weekday_of_month(-5, Weekday::Monday).is_err());

# Ok::<(), Box<dyn std::error::Error>>(())
fn nth_weekday(self: Self, nth: i32, weekday: Weekday) -> Result<Date, Error>

Returns the "nth" weekday from this date, not including itself.

The nth parameter can be positive or negative. A positive value computes the "nth" weekday starting at the day after this date and going forwards in time. A negative value computes the "nth" weekday starting at the day before this date and going backwards in time.

For example, if this date's weekday is a Sunday and the first Sunday is asked for (that is, date.nth_weekday(1, Weekday::Sunday)), then the result is a week from this date corresponding to the following Sunday.

Errors

This returns an error when nth is 0, or if it would otherwise result in a date that overflows the minimum/maximum values of Date.

Example

This example shows how to find the "nth" weekday going forwards in time:

use jiff::civil::{Weekday, date};

// Use a Sunday in March as our start date.
let d = date(2024, 3, 10);
assert_eq!(d.weekday(), Weekday::Sunday);

// The first next Monday is tomorrow!
let next_monday = d.nth_weekday(1, Weekday::Monday)?;
assert_eq!(next_monday, date(2024, 3, 11));

// But the next Sunday is a week away, because this doesn't
// include the current weekday.
let next_sunday = d.nth_weekday(1, Weekday::Sunday)?;
assert_eq!(next_sunday, date(2024, 3, 17));

// "not this Thursday, but next Thursday"
let next_next_thursday = d.nth_weekday(2, Weekday::Thursday)?;
assert_eq!(next_next_thursday, date(2024, 3, 21));

# Ok::<(), Box<dyn std::error::Error>>(())

This example shows how to find the "nth" weekday going backwards in time:

use jiff::civil::{Weekday, date};

// Use a Sunday in March as our start date.
let d = date(2024, 3, 10);
assert_eq!(d.weekday(), Weekday::Sunday);

// "last Saturday" was yesterday!
let last_saturday = d.nth_weekday(-1, Weekday::Saturday)?;
assert_eq!(last_saturday, date(2024, 3, 9));

// "last Sunday" was a week ago.
let last_sunday = d.nth_weekday(-1, Weekday::Sunday)?;
assert_eq!(last_sunday, date(2024, 3, 3));

// "not last Thursday, but the one before"
let prev_prev_thursday = d.nth_weekday(-2, Weekday::Thursday)?;
assert_eq!(prev_prev_thursday, date(2024, 2, 29));

# Ok::<(), Box<dyn std::error::Error>>(())

This example shows that overflow results in an error in either direction:

use jiff::civil::{Date, Weekday};

let d = Date::MAX;
assert_eq!(d.weekday(), Weekday::Friday);
assert!(d.nth_weekday(1, Weekday::Saturday).is_err());

let d = Date::MIN;
assert_eq!(d.weekday(), Weekday::Monday);
assert!(d.nth_weekday(-1, Weekday::Sunday).is_err());

Example: the start of Israeli summer time

Israeli law says (at present, as of 2024-03-11) that DST or "summer time" starts on the Friday before the last Sunday in March. We can find that date using both nth_weekday and [Date::nth_weekday_of_month]:

use jiff::civil::{Weekday, date};

let march = date(2024, 3, 1);
let last_sunday = march.nth_weekday_of_month(-1, Weekday::Sunday)?;
let dst_starts_on = last_sunday.nth_weekday(-1, Weekday::Friday)?;
assert_eq!(dst_starts_on, date(2024, 3, 29));

# Ok::<(), Box<dyn std::error::Error>>(())

Example: getting the start of the week

Given a date, one can use nth_weekday to determine the start of the week in which the date resides in. This might vary based on whether the weeks start on Sunday or Monday. This example shows how to handle both.

use jiff::civil::{Weekday, date};

let d = date(2024, 3, 15);
// For weeks starting with Sunday.
let start_of_week = d.tomorrow()?.nth_weekday(-1, Weekday::Sunday)?;
assert_eq!(start_of_week, date(2024, 3, 10));
// For weeks starting with Monday.
let start_of_week = d.tomorrow()?.nth_weekday(-1, Weekday::Monday)?;
assert_eq!(start_of_week, date(2024, 3, 11));

# Ok::<(), Box<dyn std::error::Error>>(())

In the above example, we first get the date after the current one because nth_weekday does not consider itself when counting. This works as expected even at the boundaries of a week:

use jiff::civil::{Weekday, date};

// The start of the week.
let d = date(2024, 3, 10);
let start_of_week = d.tomorrow()?.nth_weekday(-1, Weekday::Sunday)?;
assert_eq!(start_of_week, date(2024, 3, 10));
// The end of the week.
let d = date(2024, 3, 16);
let start_of_week = d.tomorrow()?.nth_weekday(-1, Weekday::Sunday)?;
assert_eq!(start_of_week, date(2024, 3, 10));

# Ok::<(), Box<dyn std::error::Error>>(())
fn iso_week_date(self: Self) -> ISOWeekDate

Construct an ISO 8601 week date from this Gregorian date.

The ISOWeekDate type describes itself in more detail, but in brief, the ISO week date calendar system eschews months in favor of weeks.

The minimum and maximum values of an ISOWeekDate correspond precisely to the minimum and maximum values of a Date. Therefore, converting between them is lossless and infallible.

This routine is equivalent to ISOWeekDate::from_date.

Example

This shows a number of examples demonstrating the conversion from a Gregorian date to an ISO 8601 week date:

use jiff::civil::{Date, Weekday, date};

let weekdate = date(1995, 1, 1).iso_week_date();
assert_eq!(weekdate.year(), 1994);
assert_eq!(weekdate.week(), 52);
assert_eq!(weekdate.weekday(), Weekday::Sunday);

let weekdate = date(1996, 12, 31).iso_week_date();
assert_eq!(weekdate.year(), 1997);
assert_eq!(weekdate.week(), 1);
assert_eq!(weekdate.weekday(), Weekday::Tuesday);

let weekdate = date(2019, 12, 30).iso_week_date();
assert_eq!(weekdate.year(), 2020);
assert_eq!(weekdate.week(), 1);
assert_eq!(weekdate.weekday(), Weekday::Monday);

let weekdate = date(2024, 3, 9).iso_week_date();
assert_eq!(weekdate.year(), 2024);
assert_eq!(weekdate.week(), 10);
assert_eq!(weekdate.weekday(), Weekday::Saturday);

let weekdate = Date::MIN.iso_week_date();
assert_eq!(weekdate.year(), -9999);
assert_eq!(weekdate.week(), 1);
assert_eq!(weekdate.weekday(), Weekday::Monday);

let weekdate = Date::MAX.iso_week_date();
assert_eq!(weekdate.year(), 9999);
assert_eq!(weekdate.week(), 52);
assert_eq!(weekdate.weekday(), Weekday::Friday);
fn in_tz(self: Self, time_zone_name: &str) -> Result<Zoned, Error>

Converts a civil date to a Zoned datetime by adding the given time zone and setting the clock time to midnight.

This is a convenience function for date.to_datetime(midnight).in_tz(name). See DateTime::to_zoned for more details. Note that ambiguous datetimes are handled in the same way as DateTime::to_zoned.

Errors

This returns an error when the given time zone name could not be found in the default time zone database.

This also returns an error if this date could not be represented as a timestamp. This can occur in some cases near the minimum and maximum boundaries of a Date.

Example

This is a simple example of converting a civil date (a "wall" or "local" or "naive" date) to a precise instant in time that is aware of its time zone:

use jiff::civil::date;

let zdt = date(2024, 6, 20).in_tz("America/New_York")?;
assert_eq!(zdt.to_string(), "2024-06-20T00:00:00-04:00[America/New_York]");

# Ok::<(), Box<dyn std::error::Error>>(())

Example: dealing with ambiguity

Since a Zoned corresponds to a precise instant in time (to nanosecond precision) and a Date can be many possible such instants, this routine chooses one for this date: the first one, or midnight.

Interestingly, some regions implement their daylight saving time transitions at midnight. This means there are some places in the world where, once a year, midnight does not exist on their clocks. As a result, it's possible for the datetime string representing a Zoned to be something other than midnight. For example:

use jiff::civil::date;

let zdt = date(2024, 3, 10).in_tz("Cuba")?;
assert_eq!(zdt.to_string(), "2024-03-10T01:00:00-04:00[Cuba]");

# Ok::<(), Box<dyn std::error::Error>>(())

Since this uses Disambiguation::Compatible, and since that also chooses the "later" time in a forward transition, it follows that the date of the returned Zoned will always match this civil date. (Unless there is a pathological time zone with a 24+ hour transition forward.)

But if a different disambiguation strategy is used, even when only dealing with standard one hour transitions, the date returned can be different:

use jiff::{civil::date, tz::TimeZone};

let tz = TimeZone::get("Cuba")?;
let dt = date(2024, 3, 10).at(0, 0, 0, 0);
let zdt = tz.to_ambiguous_zoned(dt).earlier()?;
assert_eq!(zdt.to_string(), "2024-03-09T23:00:00-05:00[Cuba]");

# Ok::<(), Box<dyn std::error::Error>>(())
fn to_zoned(self: Self, tz: TimeZone) -> Result<Zoned, Error>

Converts a civil datetime to a Zoned datetime by adding the given TimeZone and setting the clock time to midnight.

This is a convenience function for date.to_datetime(midnight).to_zoned(tz). See DateTime::to_zoned for more details. Note that ambiguous datetimes are handled in the same way as DateTime::to_zoned.

In the common case of a time zone being represented as a name string, like Australia/Tasmania, consider using Date::in_tz instead.

Errors

This returns an error if this date could not be represented as a timestamp. This can occur in some cases near the minimum and maximum boundaries of a Date.

Example

This example shows how to create a zoned value with a fixed time zone offset:

use jiff::{civil::date, tz};

let tz = tz::offset(-4).to_time_zone();
let zdt = date(2024, 6, 20).to_zoned(tz)?;
// A time zone annotation is still included in the printable version
// of the Zoned value, but it is fixed to a particular offset.
assert_eq!(zdt.to_string(), "2024-06-20T00:00:00-04:00[-04:00]");

# Ok::<(), Box<dyn std::error::Error>>(())
const fn to_datetime(self: Self, time: Time) -> DateTime

Given a Time, this constructs a DateTime value with its time component equal to this time.

This is a convenience function for DateTime::from_parts.

Example

use jiff::civil::{DateTime, date, time};

let date = date(2010, 3, 14);
let time = time(2, 30, 0, 0);
assert_eq!(DateTime::from_parts(date, time), date.to_datetime(time));
const fn at(self: Self, hour: i8, minute: i8, second: i8, subsec_nanosecond: i32) -> DateTime

A convenience function for constructing a DateTime from this date at the time given by its components.

Example

use jiff::civil::date;

assert_eq!(
    date(2010, 3, 14).at(2, 30, 0, 0).to_string(),
    "2010-03-14T02:30:00",
);

One can also flip the order by making use of [Time::on]:

use jiff::civil::time;

assert_eq!(
    time(2, 30, 0, 0).on(2010, 3, 14).to_string(),
    "2010-03-14T02:30:00",
);
fn checked_add<A: Into<DateArithmetic>>(self: Self, duration: A) -> Result<Date, Error>

Add the given span of time to this date. If the sum would overflow the minimum or maximum date values, then an error is returned.

This operation accepts three different duration types: Span, SignedDuration or std::time::Duration. This is achieved via From trait implementations for the DateArithmetic type.

Properties

When adding a Span duration, this routine is not reversible because some additions may be ambiguous. For example, adding 1 month to the date 2024-03-31 will produce 2024-04-30 since April has only 30 days in a month. Conversely, subtracting 1 month from 2024-04-30 will produce 2024-03-30, which is not the date we started with.

If spans of time are limited to units of days (or less), then this routine is reversible. This also implies that all operations with a SignedDuration or a std::time::Duration are reversible.

Errors

If the span added to this date would result in a date that exceeds the range of a Date, then this will return an error.

Examples

This shows a few examples of adding spans of time to various dates. We make use of the ToSpan trait for convenient creation of spans.

use jiff::{civil::date, ToSpan};

let d = date(2024, 3, 31);
assert_eq!(d.checked_add(1.months())?, date(2024, 4, 30));
// Adding two months gives us May 31, not May 30.
let d = date(2024, 3, 31);
assert_eq!(d.checked_add(2.months())?, date(2024, 5, 31));
// Any time in the span that does not exceed a day is ignored.
let d = date(2024, 3, 31);
assert_eq!(d.checked_add(23.hours())?, date(2024, 3, 31));
// But if the time exceeds a day, that is accounted for!
let d = date(2024, 3, 31);
assert_eq!(d.checked_add(28.hours())?, date(2024, 4, 1));

# Ok::<(), Box<dyn std::error::Error>>(())

Example: available via addition operator

This routine can be used via the + operator. Note though that if it fails, it will result in a panic.

use jiff::{civil::date, ToSpan};

let d = date(2024, 3, 31);
assert_eq!(d + 1.months(), date(2024, 4, 30));

Example: negative spans are supported

use jiff::{civil::date, ToSpan};

let d = date(2024, 3, 31);
assert_eq!(
    d.checked_add(-1.months())?,
    date(2024, 2, 29),
);
# Ok::<(), Box<dyn std::error::Error>>(())

Example: error on overflow

use jiff::{civil::date, ToSpan};

let d = date(2024, 3, 31);
assert!(d.checked_add(9000.years()).is_err());
assert!(d.checked_add(-19000.years()).is_err());

Example: adding absolute durations

This shows how to add signed and unsigned absolute durations to a Date. Only whole numbers of days are considered. Since this is a civil date unaware of time zones, days are always 24 hours.

use std::time::Duration;

use jiff::{civil::date, SignedDuration};

let d = date(2024, 2, 29);

let dur = SignedDuration::from_hours(24);
assert_eq!(d.checked_add(dur)?, date(2024, 3, 1));
assert_eq!(d.checked_add(-dur)?, date(2024, 2, 28));

// Any leftover time is truncated. That is, only
// whole days from the duration are considered.
let dur = Duration::from_secs((24 * 60 * 60) + (23 * 60 * 60));
assert_eq!(d.checked_add(dur)?, date(2024, 3, 1));

# Ok::<(), Box<dyn std::error::Error>>(())
fn checked_sub<A: Into<DateArithmetic>>(self: Self, duration: A) -> Result<Date, Error>

This routine is identical to Date::checked_add with the duration negated.

Errors

This has the same error conditions as Date::checked_add.

Example

use std::time::Duration;

use jiff::{civil::date, SignedDuration, ToSpan};

let d = date(2024, 2, 29);
assert_eq!(d.checked_sub(1.year())?, date(2023, 2, 28));

let dur = SignedDuration::from_hours(24);
assert_eq!(d.checked_sub(dur)?, date(2024, 2, 28));

let dur = Duration::from_secs(24 * 60 * 60);
assert_eq!(d.checked_sub(dur)?, date(2024, 2, 28));

# Ok::<(), Box<dyn std::error::Error>>(())
fn saturating_add<A: Into<DateArithmetic>>(self: Self, duration: A) -> Date

This routine is identical to Date::checked_add, except the result saturates on overflow. That is, instead of overflow, either Date::MIN or Date::MAX is returned.

Example

use jiff::{civil::{Date, date}, SignedDuration, ToSpan};

let d = date(2024, 3, 31);
assert_eq!(Date::MAX, d.saturating_add(9000.years()));
assert_eq!(Date::MIN, d.saturating_add(-19000.years()));
assert_eq!(Date::MAX, d.saturating_add(SignedDuration::MAX));
assert_eq!(Date::MIN, d.saturating_add(SignedDuration::MIN));
assert_eq!(Date::MAX, d.saturating_add(std::time::Duration::MAX));
fn saturating_sub<A: Into<DateArithmetic>>(self: Self, duration: A) -> Date

This routine is identical to Date::saturating_add with the span parameter negated.

Example

use jiff::{civil::{Date, date}, SignedDuration, ToSpan};

let d = date(2024, 3, 31);
assert_eq!(Date::MIN, d.saturating_sub(19000.years()));
assert_eq!(Date::MAX, d.saturating_sub(-9000.years()));
assert_eq!(Date::MIN, d.saturating_sub(SignedDuration::MAX));
assert_eq!(Date::MAX, d.saturating_sub(SignedDuration::MIN));
assert_eq!(Date::MIN, d.saturating_sub(std::time::Duration::MAX));
fn until<A: Into<DateDifference>>(self: Self, other: A) -> Result<Span, Error>

Returns a span representing the elapsed time from this date until the given other date.

When other occurs before this date, then the span returned will be negative.

Depending on the input provided, the span returned is rounded. It may also be balanced up to bigger units than the default. By default, the span returned is balanced such that the biggest and smallest possible unit is days.

This operation is configured by providing a DateDifference value. Since this routine accepts anything that implements Into<DateDifference>, once can pass a Date directly. One can also pass a (Unit, Date), where Unit is treated as DateDifference::largest.

Properties

It is guaranteed that if the returned span is subtracted from other, and if no rounding is requested, and if the largest unit request is at most Unit::Day, then the original date will be returned.

This routine is equivalent to self.since(other).map(|span| -span) if no rounding options are set. If rounding options are set, then it's equivalent to self.since(other_without_rounding_options).map(|span| -span), followed by a call to Span::round with the appropriate rounding options set. This is because the negation of a span can result in different rounding results depending on the rounding mode.

Errors

An error can occur if DateDifference is misconfigured. For example, if the smallest unit provided is bigger than the largest unit.

It is guaranteed that if one provides a date with the default DateDifference configuration, then this routine will never fail.

Examples

use jiff::{civil::date, ToSpan};

let earlier = date(2006, 8, 24);
let later = date(2019, 1, 31);
assert_eq!(earlier.until(later)?, 4543.days().fieldwise());

// Flipping the dates is fine, but you'll get a negative span.
let earlier = date(2006, 8, 24);
let later = date(2019, 1, 31);
assert_eq!(later.until(earlier)?, -4543.days().fieldwise());

# Ok::<(), Box<dyn std::error::Error>>(())

Example: using bigger units

This example shows how to expand the span returned to bigger units. This makes use of a From<(Unit, Date)> for DateDifference trait implementation.

use jiff::{civil::date, Unit, ToSpan};

let d1 = date(1995, 12, 07);
let d2 = date(2019, 01, 31);

// The default limits durations to using "days" as the biggest unit.
let span = d1.until(d2)?;
assert_eq!(span.to_string(), "P8456D");

// But we can ask for units all the way up to years.
let span = d1.until((Unit::Year, d2))?;
assert_eq!(span.to_string(), "P23Y1M24D");

# Ok::<(), Box<dyn std::error::Error>>(())

Example: rounding the result

This shows how one might find the difference between two dates and have the result rounded to the nearest month.

In this case, we need to hand-construct a DateDifference in order to gain full configurability.

use jiff::{civil::{date, DateDifference}, Unit, ToSpan};

let d1 = date(1995, 12, 07);
let d2 = date(2019, 02, 06);

let span = d1.until(DateDifference::from(d2).smallest(Unit::Month))?;
assert_eq!(span, 277.months().fieldwise());

// Or even include years to make the span a bit more comprehensible.
let span = d1.until(
    DateDifference::from(d2)
        .smallest(Unit::Month)
        .largest(Unit::Year),
)?;
// Notice that we are one day shy of 23y2m. Rounding spans computed
// between dates uses truncation by default.
assert_eq!(span, 23.years().months(1).fieldwise());

# Ok::<(), Box<dyn std::error::Error>>(())

Example: units biggers than days inhibit reversibility

If you ask for units bigger than days, then adding the span returned to the other date is not guaranteed to result in the original date. For example:

use jiff::{civil::date, Unit, ToSpan};

let d1 = date(2024, 3, 2);
let d2 = date(2024, 5, 1);

let span = d1.until((Unit::Month, d2))?;
assert_eq!(span, 1.month().days(29).fieldwise());
let maybe_original = d2.checked_sub(span)?;
// Not the same as the original datetime!
assert_eq!(maybe_original, date(2024, 3, 3));

// But in the default configuration, days are always the biggest unit
// and reversibility is guaranteed.
let span = d1.until(d2)?;
assert_eq!(span, 60.days().fieldwise());
let is_original = d2.checked_sub(span)?;
assert_eq!(is_original, d1);

# Ok::<(), Box<dyn std::error::Error>>(())

This occurs because spans are added as if by adding the biggest units first, and then the smaller units. Because months vary in length, their meaning can change depending on how the span is added. In this case, adding one month to 2024-03-02 corresponds to 31 days, but subtracting one month from 2024-05-01 corresponds to 30 days.

fn since<A: Into<DateDifference>>(self: Self, other: A) -> Result<Span, Error>

This routine is identical to Date::until, but the order of the parameters is flipped.

Errors

This has the same error conditions as Date::until.

Example

This routine can be used via the - operator. Since the default configuration is used and because a Span can represent the difference between any two possible dates, it will never panic.

use jiff::{civil::date, ToSpan};

let earlier = date(2006, 8, 24);
let later = date(2019, 1, 31);
assert_eq!(later - earlier, 4543.days().fieldwise());
// Equivalent to:
assert_eq!(later.since(earlier).unwrap(), 4543.days().fieldwise());
fn duration_until(self: Self, other: Date) -> SignedDuration

Returns an absolute duration representing the elapsed time from this date until the given other date.

When other occurs before this date, then the duration returned will be negative.

Unlike Date::until, this returns a duration corresponding to a 96-bit integer of nanoseconds between two dates. In this case of computing durations between civil dates where all days are assumed to be 24 hours long, the duration returned will always be divisible by 24 hours. (That is, 24 * 60 * 60 * 1_000_000_000 nanoseconds.)

Fallibility

This routine never panics or returns an error. Since there are no configuration options that can be incorrectly provided, no error is possible when calling this routine. In contrast, Date::until can return an error in some cases due to misconfiguration. But like this routine, Date::until never panics or returns an error in its default configuration.

When should I use this versus Date::until?

See the type documentation for SignedDuration for the section on when one should use Span and when one should use SignedDuration. In short, use Span (and therefore Date::until) unless you have a specific reason to do otherwise.

Example

use jiff::{civil::date, SignedDuration};

let earlier = date(2006, 8, 24);
let later = date(2019, 1, 31);
assert_eq!(
    earlier.duration_until(later),
    SignedDuration::from_hours(4543 * 24),
);

Example: difference with Date::until

The main difference between this routine and Date::until is that the latter can return units other than a 96-bit integer of nanoseconds. While a 96-bit integer of nanoseconds can be converted into other units like hours, this can only be done for uniform units. (Uniform units are units for which each individual unit always corresponds to the same elapsed time regardless of the datetime it is relative to.) This can't be done for units like years, months or days without a relative date.

use jiff::{civil::date, SignedDuration, Span, SpanRound, ToSpan, Unit};

let d1 = date(2024, 1, 1);
let d2 = date(2025, 4, 1);

let span = d1.until((Unit::Year, d2))?;
assert_eq!(span, 1.year().months(3).fieldwise());

let duration = d1.duration_until(d2);
assert_eq!(duration, SignedDuration::from_hours(456 * 24));
// There's no way to extract years or months from the signed
// duration like one might extract hours (because every hour
// is the same length). Instead, you actually have to convert
// it to a span and then balance it by providing a relative date!
let options = SpanRound::new().largest(Unit::Year).relative(d1);
let span = Span::try_from(duration)?.round(options)?;
assert_eq!(span, 1.year().months(3).fieldwise());

# Ok::<(), Box<dyn std::error::Error>>(())

Example: getting an unsigned duration

If you're looking to find the duration between two dates as a std::time::Duration, you'll need to use this method to get a SignedDuration and then convert it to a std::time::Duration:

use std::time::Duration;

use jiff::{civil::date, SignedDuration};

let d1 = date(2024, 7, 1);
let d2 = date(2024, 8, 1);
let duration = Duration::try_from(d1.duration_until(d2))?;
assert_eq!(duration, Duration::from_secs(31 * 24 * 60 * 60));

// Note that unsigned durations cannot represent all
// possible differences! If the duration would be negative,
// then the conversion fails:
assert!(Duration::try_from(d2.duration_until(d1)).is_err());

# Ok::<(), Box<dyn std::error::Error>>(())
fn duration_since(self: Self, other: Date) -> SignedDuration

This routine is identical to Date::duration_until, but the order of the parameters is flipped.

Example

use jiff::{civil::date, SignedDuration};

let earlier = date(2006, 8, 24);
let later = date(2019, 1, 31);
assert_eq!(
    later.duration_since(earlier),
    SignedDuration::from_hours(4543 * 24),
);
fn series(self: Self, period: Span) -> DateSeries

Return an iterator of periodic dates determined by the given span.

The given span may be negative, in which case, the iterator will move backwards through time. The iterator won't stop until either the span itself overflows, or it would otherwise exceed the minimum or maximum Date value.

Example: Halloween day of the week

As a kid, I always hoped for Halloween to fall on a weekend. With this program, we can print the day of the week for all Halloweens in the 2020s.

use jiff::{civil::{Weekday, date}, ToSpan};

let start = date(2020, 10, 31);
let mut halloween_days_of_week = vec![];
for halloween in start.series(1.years()).take(10) {
    halloween_days_of_week.push(
        (halloween.year(), halloween.weekday()),
    );
}
assert_eq!(halloween_days_of_week, vec![
    (2020, Weekday::Saturday),
    (2021, Weekday::Sunday),
    (2022, Weekday::Monday),
    (2023, Weekday::Tuesday),
    (2024, Weekday::Thursday),
    (2025, Weekday::Friday),
    (2026, Weekday::Saturday),
    (2027, Weekday::Sunday),
    (2028, Weekday::Tuesday),
    (2029, Weekday::Wednesday),
]);

Example: how many times do I mow the lawn in a year?

I mow the lawn about every week and a half from the beginning of May to the end of October. About how many times will I mow the lawn in 2024?

use jiff::{ToSpan, civil::date};

let start = date(2024, 5, 1);
let end = date(2024, 10, 31);
let mows = start
    .series(1.weeks().days(3).hours(12))
    .take_while(|&d| d <= end)
    .count();
assert_eq!(mows, 18);

Example: a period less than a day

Using a period less than a day works, but since this type exists at the granularity of a day, some dates may be repeated.

use jiff::{civil::{Date, date}, ToSpan};

let start = date(2024, 3, 11);
let every_five_hours: Vec<Date> =
    start.series(15.hours()).take(7).collect();
assert_eq!(every_five_hours, vec![
    date(2024, 3, 11),
    date(2024, 3, 11),
    date(2024, 3, 12),
    date(2024, 3, 12),
    date(2024, 3, 13),
    date(2024, 3, 14),
    date(2024, 3, 14),
]);

Example: finding the most recent Friday the 13th

When did the most recent Friday the 13th occur?

use jiff::{civil::{Weekday, date}, ToSpan};

let start = date(2024, 3, 13);
let mut found = None;
for date in start.series(-1.months()) {
    if date.weekday() == Weekday::Friday {
        found = Some(date);
        break;
    }
}
assert_eq!(found, Some(date(2023, 10, 13)));

impl Date

fn strptime<impl AsRef<[u8]>: AsRef<[u8]>, impl AsRef<[u8]>: AsRef<[u8]>>(format: impl AsRef<[u8]>, input: impl AsRef<[u8]>) -> Result<Date, Error>

Parses a civil date in input matching the given format.

The format string uses a "printf"-style API where conversion specifiers can be used as place holders to match components of a datetime. For details on the specifiers supported, see the fmt::strtime module documentation.

Errors

This returns an error when parsing failed. This might happen because the format string itself was invalid, or because the input didn't match the format string.

This also returns an error if there wasn't sufficient information to construct a civil date. For example, if an offset wasn't parsed.

Example

This example shows how to parse a civil date:

use jiff::civil::Date;

// Parse an American date with a two-digit year.
let date = Date::strptime("%m/%d/%y", "7/14/24")?;
assert_eq!(date.to_string(), "2024-07-14");

# Ok::<(), Box<dyn std::error::Error>>(())
fn strftime<'f, F: 'f + ?Sized + AsRef<[u8]>>(self: &Self, format: &'f F) -> Display<'f>

Formats this civil date according to the given format.

The format string uses a "printf"-style API where conversion specifiers can be used as place holders to format components of a datetime. For details on the specifiers supported, see the fmt::strtime module documentation.

Errors and panics

While this routine itself does not error or panic, using the value returned may result in a panic if formatting fails. See the documentation on fmt::strtime::Display for more information.

To format in a way that surfaces errors without panicking, use either fmt::strtime::format or fmt::strtime::BrokenDownTime::format.

Example

This example shows how to format a civil date:

use jiff::civil::date;

let date = date(2024, 7, 15);
let string = date.strftime("%Y-%m-%d is a %A").to_string();
assert_eq!(string, "2024-07-15 is a Monday");

impl Add for Date

fn add(self: Self, rhs: Span) -> Date

impl Add for Date

fn add(self: Self, rhs: SignedDuration) -> Date

impl Add for Date

fn add(self: Self, rhs: UnsignedDuration) -> Date

impl AddAssign for Date

fn add_assign(self: &mut Self, rhs: SignedDuration)

impl AddAssign for Date

fn add_assign(self: &mut Self, rhs: UnsignedDuration)

impl AddAssign for Date

fn add_assign(self: &mut Self, rhs: Span)

impl Clone for Date

fn clone(self: &Self) -> Date

impl Copy for Date

impl Debug for Date

fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result

impl Default for Date

fn default() -> Date

impl Display for Date

fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result

impl Eq for Date

impl Freeze for Date

impl From for Date

fn from(weekdate: ISOWeekDate) -> Date

impl From for Date

fn from(dt: DateTime) -> Date

impl From for Date

fn from(zdt: Zoned) -> Date

impl FromStr for Date

fn from_str(string: &str) -> Result<Date, Error>

impl Hash for Date

fn hash<__H: $crate::hash::Hasher>(self: &Self, state: &mut __H)

impl Ord for Date

fn cmp(self: &Self, other: &Date) -> Ordering

impl PartialEq for Date

fn eq(self: &Self, other: &Date) -> bool

impl PartialOrd for Date

fn partial_cmp(self: &Self, other: &Date) -> Option<Ordering>

impl RefUnwindSafe for Date

impl Send for Date

impl Serialize for Date

fn serialize<S: serde::Serializer>(self: &Self, serializer: S) -> Result<<S as >::Ok, <S as >::Error>

impl Sub for Date

fn sub(self: Self, rhs: Span) -> Date

impl Sub for Date

fn sub(self: Self, rhs: SignedDuration) -> Date

impl Sub for Date

fn sub(self: Self, rhs: UnsignedDuration) -> Date

impl Sub for Date

fn sub(self: Self, rhs: Date) -> Span

impl SubAssign for Date

fn sub_assign(self: &mut Self, rhs: Span)

impl SubAssign for Date

fn sub_assign(self: &mut Self, rhs: SignedDuration)

impl SubAssign for Date

fn sub_assign(self: &mut Self, rhs: UnsignedDuration)

impl Sync for Date

impl Unpin for Date

impl UnsafeUnpin for Date

impl UnwindSafe for Date

impl<'a> From for Date

fn from(zdt: &'a Zoned) -> Date

impl<'de> Deserialize for Date

fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Date, <D as >::Error>

impl<T> Any for Date

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for Date

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for Date

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CloneToUninit for Date

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> DeserializeOwned for Date

impl<T> From for Date

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> ToOwned for Date

fn to_owned(self: &Self) -> T
fn clone_into(self: &Self, target: &mut T)

impl<T> ToString for Date

fn to_string(self: &Self) -> String

impl<T, U> Into for Date

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for Date

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for Date

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>