Struct DateTime
struct DateTime { ... }
A representation of a civil datetime in the Gregorian calendar.
A DateTime value corresponds to a pair of a Date and a Time.
That is, a datetime contains a year, month, day, hour, minute, second and
the fractional number of nanoseconds.
A DateTime value is guaranteed to contain a valid date and time. For
example, neither 2023-02-29T00:00:00 nor 2015-06-30T23:59:60 are
valid DateTime values.
Civil datetimes
A DateTime value behaves without regard to daylight saving time or time
zones in general. When doing arithmetic on datetimes with spans defined in
units of time (such as with DateTime::checked_add), days are considered
to always be precisely 86,400 seconds long.
Parsing and printing
The DateTime type provides convenient trait implementations of
std::str::FromStr and [std::fmt::Display]:
use DateTime;
let dt: DateTime = "2024-06-19 15:22:45".parse?;
assert_eq!;
# Ok::
A civil DateTime can also be parsed from something that contains a
datetime, but with perhaps other data (such as an offset or time zone):
use DateTime;
let dt: DateTime = "2024-06-19T15:22:45-04[America/New_York]".parse?;
assert_eq!;
# Ok::
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-01T00:00:00.000000000. That is, it is
the datetime corresponding to DateTime::from_parts(Date::default(), Time::default()). One can also access this value via the DateTime::ZERO
constant.
Leap seconds
Jiff does not support leap seconds. Jiff behaves as if they don't exist.
The only exception is that if one parses a datetime with a second component
of 60, then it is automatically constrained to 59:
use ;
let dt: DateTime = "2016-12-31 23:59:60".parse?;
assert_eq!;
# Ok::
Comparisons
The DateTime type provides both Eq and Ord trait implementations to
facilitate easy comparisons. When a datetime dt1 occurs before a datetime
dt2, then dt1 < dt2. For example:
use date;
let dt1 = date.at;
let dt2 = date.at;
assert!;
Arithmetic
This type provides routines for adding and subtracting spans of time, as
well as computing the span of time between two DateTime values.
For adding or subtracting spans of time, one can use any of the following routines:
DateTime::checked_addorDateTime::checked_subfor checked arithmetic.DateTime::saturating_addorDateTime::saturating_subfor saturating arithmetic.
Additionally, checked arithmetic is available via the Add and Sub
trait implementations. When the result overflows, a panic occurs.
use ;
let start = date.at;
let one_week_later = start + 1.weeks;
assert_eq!;
One can compute the span of time between two datetimes using either
DateTime::until or DateTime::since. It's also possible to subtract
two DateTime values directly via a Sub trait implementation:
use ;
let datetime1 = date.at;
let datetime2 = date.at;
assert_eq!;
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 ;
let datetime1 = date.at;
let datetime2 = date.at;
assert_eq!;
# Ok::
Or even round the span returned:
use ;
let datetime1 = date.at;
let datetime2 = date.at;
assert_eq!;
// `DateTimeDifference` uses truncation as a rounding mode by default,
// but you can set the rounding mode to break ties away from zero:
assert_eq!;
# Ok::
Rounding
A DateTime can be rounded based on a DateTimeRound configuration of
smallest units, rounding increment and rounding mode. Here's an example
showing how to round to the nearest third hour:
use ;
let dt = date.at;
assert_eq!;
// Or alternatively, make use of the `From<(Unit, i64)> for DateTimeRound`
// trait implementation:
assert_eq!;
# Ok::
See DateTime::round for more details.
Implementations
impl DateTime
fn strptime<impl AsRef<[u8]>: AsRef<[u8]>, impl AsRef<[u8]>: AsRef<[u8]>>(format: impl AsRef<[u8]>, input: impl AsRef<[u8]>) -> Result<DateTime, Error>Parses a civil datetime in
inputmatching the givenformat.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::strtimemodule 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 datetime. For example, if an offset wasn't parsed.
Example
This example shows how to parse a civil datetime:
use DateTime; let dt = strptime?; assert_eq!; # Ok::fn strftime<'f, F: 'f + ?Sized + AsRef<[u8]>>(self: &Self, format: &'f F) -> Display<'f>Formats this civil datetime 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::strtimemodule 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::Displayfor more information.To format in a way that surfaces errors without panicking, use either
fmt::strtime::formatorfmt::strtime::BrokenDownTime::format.Example
This example shows how to format a civil datetime:
use date; let dt = date.at; let string = dt.strftime.to_string; assert_eq!;
impl DateTime
fn new(year: i16, month: i8, day: i8, hour: i8, minute: i8, second: i8, subsec_nanosecond: i32) -> Result<DateTime, Error>Creates a new
DateTimevalue from its component year, month, day, hour, minute, second and fractional subsecond (up to nanosecond precision) values.To create a new datetime from another with a particular component, use the methods on
DateTimeWithviaDateTime::with.Errors
This returns an error when the given components do not correspond to a valid datetime. 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
1and must be at most the number of days in the corresponding month. So for example,2024-02-29is valid but2023-02-29is not. 0 <= hour <= 230 <= minute <= 590 <= second <= 590 <= subsec_nanosecond <= 999,999,999
Example
This shows an example of a valid datetime:
use DateTime; let d = new.unwrap; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!;This shows some examples of invalid datetimes:
use DateTime; assert!; assert!; assert!;- The year must be in the range
const fn constant(year: i16, month: i8, day: i8, hour: i8, minute: i8, second: i8, subsec_nanosecond: i32) -> DateTimeCreates a new
DateTimevalue in aconstcontext.Note that an alternative syntax that is terser and perhaps easier to read for the same operation is to combine
civil::datewithDate::at.Panics
This routine panics when
DateTime::newwould return an error. That is, when the given components do not correspond to a valid datetime. 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
1and must be at most the number of days in the corresponding month. So for example,2024-02-29is valid but2023-02-29is not. 0 <= hour <= 230 <= minute <= 590 <= second <= 590 <= subsec_nanosecond <= 999,999,999
Similarly, when used in a const context, invalid parameters will prevent your Rust program from compiling.
Example
use DateTime; let dt = constant; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!;Or alternatively:
use date; let dt = date.at; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!;- The year must be in the range
const fn from_parts(date: Date, time: Time) -> DateTimeCreates a
DateTimefrom its constituent parts.Any combination of a valid
Dateand a validTimeresults in a validDateTime.Example
This example shows how to build a datetime from its parts:
use ; let dt = from_parts; assert_eq!;fn with(self: Self) -> DateTimeWithCreate a builder for constructing a new
DateTimefrom the fields of this datetime.See the methods on
DateTimeWithfor the different ways one can set the fields of a newDateTime.Example
The builder ensures one can chain together the individual components of a datetime without it failing at an intermediate step. For example, if you had a date of
2024-10-31T00:00:00and 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 date; let dt1 = date.at; let dt2 = dt1.with.month.day.build?; assert_eq!; let dt1 = date.at; let dt2 = dt1.with.day.month.build?; assert_eq!; # Ok::fn year(self: Self) -> i16Returns the year for this datetime.
The value returned is guaranteed to be in the range
-9999..=9999.Example
use date; let dt1 = date.at; assert_eq!; let dt2 = date.at; assert_eq!; let dt3 = date.at; assert_eq!;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 than0. In the Gregorian calendar, the era labelsBCEandCEare used to disambiguate between years less than or equal to0and years greater than0, 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 ; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!;fn month(self: Self) -> i8Returns the month for this datetime.
The value returned is guaranteed to be in the range
1..=12.Example
use date; let dt1 = date.at; assert_eq!;fn day(self: Self) -> i8Returns the day for this datetime.
The value returned is guaranteed to be in the range
1..=31.Example
use date; let dt1 = date.at; assert_eq!;fn hour(self: Self) -> i8Returns the "hour" component of this datetime.
The value returned is guaranteed to be in the range
0..=23.Example
use date; let dt = date.at; assert_eq!;fn minute(self: Self) -> i8Returns the "minute" component of this datetime.
The value returned is guaranteed to be in the range
0..=59.Example
use date; let dt = date.at; assert_eq!;fn second(self: Self) -> i8Returns the "second" component of this datetime.
The value returned is guaranteed to be in the range
0..=59.Example
use date; let dt = date.at; assert_eq!;fn millisecond(self: Self) -> i16Returns the "millisecond" component of this datetime.
The value returned is guaranteed to be in the range
0..=999.Example
use date; let dt = date.at; assert_eq!;fn microsecond(self: Self) -> i16Returns the "microsecond" component of this datetime.
The value returned is guaranteed to be in the range
0..=999.Example
use date; let dt = date.at; assert_eq!;fn nanosecond(self: Self) -> i16Returns the "nanosecond" component of this datetime.
The value returned is guaranteed to be in the range
0..=999.Example
use date; let dt = date.at; assert_eq!;fn subsec_nanosecond(self: Self) -> i32Returns the fractional nanosecond for this
DateTimevalue.If you want to set this value on
DateTime, then useDateTimeWith::subsec_nanosecondviaDateTime::with.The value returned is guaranteed to be in the range
0..=999_999_999.Example
This shows the relationship between constructing a
DateTimevalue with routines likewith().millisecond()and accessing the entire fractional part as a nanosecond:use date; let dt1 = date.at; assert_eq!; let dt2 = dt1.with.millisecond.build?; assert_eq!; # Ok::Example: nanoseconds from a timestamp
This shows how the fractional nanosecond part of a
DateTimevalue manifests from a specific timestamp.use ; // 1,234 nanoseconds after the Unix epoch. let zdt = new?.in_tz?; let dt = zdt.datetime; assert_eq!; // 1,234 nanoseconds before the Unix epoch. let zdt = new?.in_tz?; let dt = zdt.datetime; // The nanosecond is equal to `1_000_000_000 - 1_234`. assert_eq!; // Looking at the other components of the time value might help. assert_eq!; assert_eq!; assert_eq!; # Ok::fn weekday(self: Self) -> WeekdayReturns the weekday corresponding to this datetime.
Example
use ; // The Unix epoch was on a Thursday. let dt = date.at; assert_eq!; // One can also get the weekday as an offset in a variety of schemes. assert_eq!; assert_eq!; assert_eq!; assert_eq!;fn day_of_year(self: Self) -> i16Returns the ordinal day of the year that this datetime resides in.
For leap years, this always returns a value in the range
1..=366. Otherwise, the value is in the range1..=365.Example
use date; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!;fn day_of_year_no_leap(self: Self) -> Option<i16>Returns the ordinal day of the year that this datetime 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 returnsNone.The value
365always corresponds to the last day in the year, December 31, even for leap years.Example
use date; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!;fn start_of_day(self: &Self) -> DateTimeReturns the beginning of the day that this datetime resides in.
That is, the datetime returned always keeps the same date, but its time is always
00:00:00(midnight).Example
use date; let dt = date.at; assert_eq!;fn end_of_day(self: &Self) -> DateTimeReturns the end of the day that this datetime resides in.
That is, the datetime returned always keeps the same date, but its time is always
23:59:59.999999999.Example
use date; let dt = date.at; assert_eq!;fn first_of_month(self: Self) -> DateTimeReturns the first date of the month that this datetime resides in.
The time in the datetime returned remains unchanged.
Example
use date; let dt = date.at; assert_eq!;fn last_of_month(self: Self) -> DateTimeReturns the last date of the month that this datetime resides in.
The time in the datetime returned remains unchanged.
Example
use date; let dt = date.at; assert_eq!;fn days_in_month(self: Self) -> i8Returns the total number of days in the the month in which this datetime 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 date; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!;fn first_of_year(self: Self) -> DateTimeReturns the first date of the year that this datetime resides in.
The time in the datetime returned remains unchanged.
Example
use date; let dt = date.at; assert_eq!;fn last_of_year(self: Self) -> DateTimeReturns the last date of the year that this datetime resides in.
The time in the datetime returned remains unchanged.
Example
use date; let dt = date.at; assert_eq!;fn days_in_year(self: Self) -> i16Returns the total number of days in the the year in which this datetime resides.
This is guaranteed to always return either
365or366.Example
use date; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!;fn in_leap_year(self: Self) -> boolReturns true if and only if the year in which this datetime resides is a leap year.
Example
use date; assert!; assert!;fn tomorrow(self: Self) -> Result<DateTime, Error>Returns the datetime with a date immediately following this one.
The time in the datetime returned remains unchanged.
Errors
This returns an error when this datetime's date is the maximum value.
Example
use ; let dt = date.at; assert_eq!; // The max doesn't have a tomorrow. assert!; # Ok::fn yesterday(self: Self) -> Result<DateTime, Error>Returns the datetime with a date immediately preceding this one.
The time in the datetime returned remains unchanged.
Errors
This returns an error when this datetime's date is the minimum value.
Example
use ; let dt = date.at; assert_eq!; // The min doesn't have a yesterday. assert!; # Ok::fn nth_weekday_of_month(self: Self, nth: i8, weekday: Weekday) -> Result<DateTime, Error>Returns the "nth" weekday from the beginning or end of the month in which this datetime resides.
The
nthparameter 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-1to "find the last weekday" in this date's month.The time in the datetime returned remains unchanged.
Errors
This returns an error when
nthis0, or if it is5or-5and 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 ; let dt = date.at; let second_friday = dt.nth_weekday_of_month?; assert_eq!; # Ok::This shows how to do the reverse of the above. That is, the nth last weekday in a month:
use ; let dt = date.at; let last_thursday = dt.nth_weekday_of_month?; assert_eq!; let second_last_thursday = dt.nth_weekday_of_month?; assert_eq!; # Ok::This routine can return an error if there isn't an
nthweekday for this month. For example, March 2024 only has 4 Mondays:use ; let dt = date.at; let fourth_monday = dt.nth_weekday_of_month?; assert_eq!; // There is no 5th Monday. assert!; // Same goes for counting backwards. assert!; # Ok::fn nth_weekday(self: Self, nth: i32, weekday: Weekday) -> Result<DateTime, Error>Returns the "nth" weekday from this datetime, not including itself.
The
nthparameter 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 datetime's weekday is a Sunday and the first Sunday is asked for (that is,
dt.nth_weekday(1, Weekday::Sunday)), then the result is a week from this datetime corresponding to the following Sunday.The time in the datetime returned remains unchanged.
Errors
This returns an error when
nthis0, or if it would otherwise result in a date that overflows the minimum/maximum values ofDateTime.Example
This example shows how to find the "nth" weekday going forwards in time:
use ; // Use a Sunday in March as our start date. let dt = date.at; assert_eq!; // The first next Monday is tomorrow! let next_monday = dt.nth_weekday?; assert_eq!; // But the next Sunday is a week away, because this doesn't // include the current weekday. let next_sunday = dt.nth_weekday?; assert_eq!; // "not this Thursday, but next Thursday" let next_next_thursday = dt.nth_weekday?; assert_eq!; # Ok::This example shows how to find the "nth" weekday going backwards in time:
use ; // Use a Sunday in March as our start date. let dt = date.at; assert_eq!; // "last Saturday" was yesterday! let last_saturday = dt.nth_weekday?; assert_eq!; // "last Sunday" was a week ago. let last_sunday = dt.nth_weekday?; assert_eq!; // "not last Thursday, but the one before" let prev_prev_thursday = dt.nth_weekday?; assert_eq!; # Ok::This example shows that overflow results in an error in either direction:
use ; let dt = MAX; assert_eq!; assert!; let dt = MIN; assert_eq!; assert!;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_weekdayand [DateTime::nth_weekday_of_month]:use ; let march = date.at; let last_sunday = march.nth_weekday_of_month?; let dst_starts_on = last_sunday.nth_weekday?; assert_eq!; # Ok::Example: getting the start of the week
Given a date, one can use
nth_weekdayto 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 ; let dt = date.at; // For weeks starting with Sunday. let start_of_week = dt.tomorrow?.nth_weekday?; assert_eq!; // For weeks starting with Monday. let start_of_week = dt.tomorrow?.nth_weekday?; assert_eq!; # Ok::In the above example, we first get the date after the current one because
nth_weekdaydoes not consider itself when counting. This works as expected even at the boundaries of a week:use ; // The start of the week. let dt = date.at; let start_of_week = dt.tomorrow?.nth_weekday?; assert_eq!; // The end of the week. let dt = date.at; let start_of_week = dt .tomorrow? .nth_weekday? .with.time.build?; assert_eq!; # Ok::fn date(self: Self) -> DateReturns the date component of this datetime.
Example
use date; let dt = date.at; assert_eq!;fn time(self: Self) -> TimeReturns the time component of this datetime.
Example
use ; let dt = date.at; assert_eq!;fn iso_week_date(self: Self) -> ISOWeekDateConstruct an ISO 8601 week date from this datetime.
The
ISOWeekDatetype describes itself in more detail, but in brief, the ISO week date calendar system eschews months in favor of weeks.This routine is equivalent to
ISOWeekDate::from_date(dt.date()).Example
This shows a number of examples demonstrating the conversion from a Gregorian date to an ISO 8601 week date:
use ; let dt = date.at; let weekdate = dt.iso_week_date; assert_eq!; assert_eq!; assert_eq!; let dt = date.at; let weekdate = dt.iso_week_date; assert_eq!; assert_eq!; assert_eq!; let dt = date.at; let weekdate = dt.iso_week_date; assert_eq!; assert_eq!; assert_eq!; let dt = date.at; let weekdate = dt.iso_week_date; assert_eq!; assert_eq!; assert_eq!; let dt = MIN.to_datetime; let weekdate = dt.iso_week_date; assert_eq!; assert_eq!; assert_eq!; let dt = MAX.to_datetime; let weekdate = dt.iso_week_date; assert_eq!; assert_eq!; assert_eq!;fn in_tz(self: Self, time_zone_name: &str) -> Result<Zoned, Error>Converts a civil datetime to a
Zoneddatetime by adding the given time zone.The name given is resolved to a
TimeZoneby using the defaultTimeZoneDatabasecreated bytz::db. Indeed, this is a convenience function forDateTime::to_zonedwhere the time zone database lookup is done automatically.In some cases, a civil datetime may be ambiguous in a particular time zone. This routine automatically utilizes the
Disambiguation::Compatiblestrategy for resolving ambiguities. That is, if a civil datetime occurs in a backward transition (called a fold), then the earlier time is selected. Or if a civil datetime occurs in a forward transition (called a gap), then the later time is selected.To convert a datetime to a
Zonedusing a different disambiguation strategy, useTimeZone::to_ambiguous_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 datetime could not be represented as an instant. This can occur in some cases near the minimum and maximum boundaries of a
DateTime.Example
This is a simple example of converting a civil datetime (a "wall" or "local" or "naive" datetime) to a datetime that is aware of its time zone:
use DateTime; let dt: DateTime = "2024-06-20 15:06".parse?; let zdt = dt.in_tz?; assert_eq!; # Ok::Example: dealing with ambiguity
In the
America/New_Yorktime zone, there was a forward transition at2024-03-10 02:00:00civil time, and a backward transition at2024-11-03 01:00:00civil time. In the former case, a gap was created such that the 2 o'clock hour never appeared on clocks for folks in theAmerica/New_Yorktime zone. In the latter case, a fold was created such that the 1 o'clock hour was repeated. Thus, March 10, 2024 in New York was 23 hours long, while November 3, 2024 in New York was 25 hours long.This example shows how datetimes in these gaps and folds are resolved by default:
use DateTime; // This is the gap, where by default we select the later time. let dt: DateTime = "2024-03-10 02:30".parse?; let zdt = dt.in_tz?; assert_eq!; // This is the fold, where by default we select the earlier time. let dt: DateTime = "2024-11-03 01:30".parse?; let zdt = dt.in_tz?; // Since this is a fold, the wall clock time is repeated. It might be // hard to see that this is the earlier time, but notice the offset: // it is the offset for DST time in New York. The later time, or the // repetition of the 1 o'clock hour, would occur in standard time, // which is an offset of -05 for New York. assert_eq!; # Ok::Example: errors
This routine can return an error when the time zone is unrecognized:
use date; let dt = date.at; assert!;Note that even if a time zone exists in, say, the IANA database, there may have been a problem reading it from your system's installation of that database. To see what wrong, enable Jiff's
loggingcrate feature and install a logger. If there was a failure, then aWARNlevel log message should be emitted.This routine can also fail if this datetime cannot be represented within the allowable timestamp limits:
use ; let dt = MAX; // All errors because the combination of the offset and the datetime // isn't enough to fit into timestamp limits. assert!; assert!; assert!; // In fact, the only valid offset one can use to turn the maximum civil // datetime into a Zoned value is the maximum offset: let tz = from_seconds.unwrap.to_time_zone; assert!; // One second less than the maximum offset results in a failure at the // maximum datetime boundary. let tz = from_seconds.unwrap.to_time_zone; assert!;This behavior exists because it guarantees that every possible
Zonedvalue can be converted into a civil datetime, but not every possible combination of civil datetime and offset can be converted into aZonedvalue. There isn't a way to make every possible roundtrip lossless in both directions, so Jiff chooses to ensure that there is always a way to convert aZonedinstant to a human readable wall clock time.fn to_zoned(self: Self, tz: TimeZone) -> Result<Zoned, Error>Converts a civil datetime to a
Zoneddatetime by adding the givenTimeZone.In some cases, a civil datetime may be ambiguous in a particular time zone. This routine automatically utilizes the
Disambiguation::Compatiblestrategy for resolving ambiguities. That is, if a civil datetime occurs in a backward transition (called a fold), then the earlier time is selected. Or if a civil datetime occurs in a forward transition (called a gap), then the later time is selected.To convert a datetime to a
Zonedusing a different disambiguation strategy, useTimeZone::to_ambiguous_zoned.In the common case of a time zone being represented as a name string, like
Australia/Tasmania, consider usingDateTime::in_tzinstead.Errors
This returns an error if this datetime could not be represented as an instant. This can occur in some cases near the minimum and maximum boundaries of a
DateTime.Example
This example shows how to create a zoned value with a fixed time zone offset:
use ; let tz = fixed; let zdt = date.at.to_zoned?; // 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!; # Ok::Example: POSIX time zone strings
And this example shows how to create a time zone from a POSIX time zone string that describes the transition to and from daylight saving time for
America/St_Johns. In particular, this rule uses non-zero minutes, which is atypical.use ; let tz = posix?; let zdt = date.at.to_zoned?; // There isn't any agreed upon mechanism for transmitting a POSIX time // zone string within an RFC 9557 TZ annotation, so Jiff just emits the // offset. In practice, POSIX TZ strings are rarely user facing anyway. // (They are still in widespread use as an implementation detail of the // IANA Time Zone Database however.) assert_eq!; # Ok::fn checked_add<A: Into<DateTimeArithmetic>>(self: Self, duration: A) -> Result<DateTime, Error>Add the given span of time to this datetime. If the sum would overflow the minimum or maximum datetime values, then an error is returned.
This operation accepts three different duration types:
Span,SignedDurationorstd::time::Duration. This is achieved viaFromtrait implementations for theDateTimeArithmetictype.Properties
This routine is not reversible because some additions may be ambiguous. For example, adding
1 monthto the datetime2024-03-31T00:00:00will produce2024-04-30T00:00:00since April has only 30 days in a month. Moreover, subtracting1 monthfrom2024-04-30T00:00:00will produce2024-03-30T00:00:00, 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
SignedDurationor astd::time::Durationare reversible.Errors
If the span added to this datetime would result in a datetime that exceeds the range of a
DateTime, then this will return an error.Example
This shows a few examples of adding spans of time to various dates. We make use of the
ToSpantrait for convenient creation of spans.use ; let dt = date.at; let got = dt.checked_add?; assert_eq!; let dt = date.at; let got = dt.checked_add?; assert_eq!; # Ok::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 ; let dt = date.at; let got = dt + 20.years.months.nanoseconds; assert_eq!;Example: negative spans are supported
use ; let dt = date.at; assert_eq!; # Ok::Example: error on overflow
use ; let dt = date.at; assert!; assert!;Example: adding absolute durations
This shows how to add signed and unsigned absolute durations to a
DateTime.use Duration; use ; let dt = date.at; let dur = from_hours; assert_eq!; assert_eq!; let dur = from_secs; assert_eq!; // One cannot negate an unsigned duration, // but you can subtract it! assert_eq!; # Ok::fn checked_sub<A: Into<DateTimeArithmetic>>(self: Self, duration: A) -> Result<DateTime, Error>This routine is identical to
DateTime::checked_addwith the duration negated.Errors
This has the same error conditions as
DateTime::checked_add.Example
This routine can be used via the
-operator. Note though that if it fails, it will result in a panic.use Duration; use ; let dt = date.at; assert_eq!; let dur = new; assert_eq!; let dur = new; assert_eq!; # Ok::fn saturating_add<A: Into<DateTimeArithmetic>>(self: Self, duration: A) -> DateTimeThis routine is identical to
DateTime::checked_add, except the result saturates on overflow. That is, instead of overflow, eitherDateTime::MINorDateTime::MAXis returned.Example
use ; let dt = date.at; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!;fn saturating_sub<A: Into<DateTimeArithmetic>>(self: Self, duration: A) -> DateTimeThis routine is identical to
DateTime::saturating_addwith the span parameter negated.Example
use ; let dt = date.at; assert_eq!; assert_eq!; assert_eq!; assert_eq!; assert_eq!;fn until<A: Into<DateTimeDifference>>(self: Self, other: A) -> Result<Span, Error>Returns a span representing the elapsed time from this datetime until the given
otherdatetime.When
otheroccurs before this datetime, 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 possible unit is days.
This operation is configured by providing a
DateTimeDifferencevalue. Since this routine accepts anything that implementsInto<DateTimeDifference>, once can pass aDateTimedirectly. One can also pass a(Unit, DateTime), whereUnitis treated asDateTimeDifference::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 requested is at mostUnit::Day, then the original datetime 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 toself.since(other_without_rounding_options).map(|span| -span), followed by a call toSpan::roundwith 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 in some cases when the requested configuration would result in a span that is beyond allowable limits. For example, the nanosecond component of a span cannot the span of time between the minimum and maximum datetime supported by Jiff. Therefore, if one requests a span with its largest unit set to
Unit::Nanosecond, then it's possible for this routine to fail.It is guaranteed that if one provides a datetime with the default
DateTimeDifferenceconfiguration, then this routine will never fail.Example
use ; let earlier = date.at; let later = date.at; assert_eq!; // Flipping the dates is fine, but you'll get a negative span. assert_eq!; # Ok::Example: using bigger units
This example shows how to expand the span returned to bigger units. This makes use of a
From<(Unit, DateTime)> for DateTimeDifferencetrait implementation.use ; let dt1 = date.at; let dt2 = date.at; // The default limits durations to using "days" as the biggest unit. let span = dt1.until?; assert_eq!; // But we can ask for units all the way up to years. let span = dt1.until?; assert_eq!; # Ok::Example: rounding the result
This shows how one might find the difference between two datetimes and have the result rounded such that sub-seconds are removed.
In this case, we need to hand-construct a
DateTimeDifferencein order to gain full configurability.use ; let dt1 = date.at; let dt2 = date.at; let span = dt1.until?; assert_eq!; // We can combine smallest and largest units too! let span = dt1.until?; assert_eq!; # Ok::Example: units biggers than days inhibit reversibility
If you ask for units bigger than days, then subtracting the span returned from the
otherdatetime is not guaranteed to result in the original datetime. For example:use ; let dt1 = date.at; let dt2 = date.at; let span = dt1.until?; assert_eq!; let maybe_original = dt2.checked_sub?; // Not the same as the original datetime! assert_eq!; // But in the default configuration, days are always the biggest unit // and reversibility is guaranteed. let span = dt1.until?; assert_eq!; let is_original = dt2.checked_sub?; assert_eq!; # Ok::This occurs because span 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-02corresponds to 31 days, but subtracting one month from2024-05-01corresponds to 30 days.fn since<A: Into<DateTimeDifference>>(self: Self, other: A) -> Result<Span, Error>This routine is identical to
DateTime::until, but the order of the parameters is flipped.Errors
This has the same error conditions as
DateTime::until.Example
This routine can be used via the
-operator. Since the default configuration is used and because aSpancan represent the difference between any two possible datetimes, it will never panic.use ; let earlier = date.at; let later = date.at; assert_eq!;fn duration_until(self: Self, other: DateTime) -> SignedDurationReturns an absolute duration representing the elapsed time from this datetime until the given
otherdatetime.When
otheroccurs before this datetime, then the duration returned will be negative.Unlike
DateTime::until, this returns a duration corresponding to a 96-bit integer of nanoseconds between two datetimes.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,
DateTime::untilcan return an error in some cases due to misconfiguration. But like this routine,DateTime::untilnever panics or returns an error in its default configuration.When should I use this versus
DateTime::until?See the type documentation for
SignedDurationfor the section on when one should useSpanand when one should useSignedDuration. In short, useSpan(and thereforeDateTime::until) unless you have a specific reason to do otherwise.Example
use ; let earlier = date.at; let later = date.at; assert_eq!; // Flipping the datetimes is fine, but you'll get a negative duration. assert_eq!;Example: difference with
DateTime::untilThe main difference between this routine and
DateTime::untilis 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 or months.use ; let dt1 = date.at; let dt2 = date.at; let span = dt1.until?; assert_eq!; let duration = dt1.duration_until; assert_eq!; // 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 = new.largest.relative; let span = try_from?.round?; assert_eq!; # Ok::Example: getting an unsigned duration
If you're looking to find the duration between two datetimes as a
std::time::Duration, you'll need to use this method to get aSignedDurationand then convert it to astd::time::Duration:use Duration; use date; let dt1 = date.at; let dt2 = date.at; let duration = try_from?; assert_eq!; // Note that unsigned durations cannot represent all // possible differences! If the duration would be negative, // then the conversion fails: assert!; # Ok::fn duration_since(self: Self, other: DateTime) -> SignedDurationThis routine is identical to
DateTime::duration_until, but the order of the parameters is flipped.Example
use ; let earlier = date.at; let later = date.at; assert_eq!;fn round<R: Into<DateTimeRound>>(self: Self, options: R) -> Result<DateTime, Error>Rounds this datetime according to the
DateTimeRoundconfiguration given.The principal option is
DateTimeRound::smallest, which allows one to configure the smallest units in the returned datetime. Rounding is what determines whether that unit should keep its current value or whether it should be incremented. Moreover, the amount it should be incremented can be configured viaDateTimeRound::increment. Finally, the rounding strategy itself can be configured viaDateTimeRound::mode.Note that this routine is generic and accepts anything that implements
Into<DateTimeRound>. Some notable implementations are:From<Unit> for DateTimeRound, which will automatically create aDateTimeRound::new().smallest(unit)from the unit provided.From<(Unit, i64)> for DateTimeRound, which will automatically create aDateTimeRound::new().smallest(unit).increment(number)from the unit and increment provided.
Errors
This returns an error if the smallest unit configured on the given
DateTimeRoundis bigger than days. An error is also returned if the rounding increment is greater than 1 when the units are days. (Currently, rounding to the nearest week, month or year is not supported.)When the smallest unit is less than days, the rounding increment must divide evenly into the next highest unit after the smallest unit configured (and must not be equivalent to it). For example, if the smallest unit is
Unit::Nanosecond, then some of the valid values for the rounding increment are1,2,4,5,100and500. Namely, any integer that divides evenly into1,000nanoseconds since there are1,000nanoseconds in the next highest unit (microseconds).This can also return an error in some cases where rounding would require arithmetic that exceeds the maximum datetime value.
Example
This is a basic example that demonstrates rounding a datetime to the nearest day. This also demonstrates calling this method with the smallest unit directly, instead of constructing a
DateTimeRoundmanually.use ; let dt = date.at; assert_eq!; let dt = date.at; assert_eq!; # Ok::Example: changing the rounding mode
The default rounding mode is
RoundMode::HalfExpand, which breaks ties by rounding away from zero. But other modes likeRoundMode::Trunccan be used too:use ; let dt = date.at; assert_eq!; // The default will round up to the next day for any time past noon, // but using truncation rounding will always round down. assert_eq!; # Ok::Example: rounding to the nearest 5 minute increment
use ; // rounds down let dt = date.at; assert_eq!; // rounds up let dt = date.at; assert_eq!; # Ok::Example: overflow error
This example demonstrates that it's possible for this operation to result in an error from datetime arithmetic overflow.
use ; let dt = MAX; assert!;This occurs because rounding to the nearest day for the maximum datetime would result in rounding up to the next day. But the next day is greater than the maximum, and so this returns an error.
If one were to use a rounding mode like
RoundMode::Trunc(which will never round up), always set a correct increment and always used units less than or equal to days, then this routine is guaranteed to never fail:use ; let round = new .smallest .mode; assert_eq!; assert_eq!; # Ok::fn series(self: Self, period: Span) -> DateTimeSeriesReturn an iterator of periodic datetimes 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
DateTimevalue.Example: when to check a glucose monitor
When my cat had diabetes, my veterinarian installed a glucose monitor and instructed me to scan it about every 5 hours. This example lists all of the times I need to scan it for the 2 days following its installation:
use ; let start = datetime; let end = start.checked_add?; let mut scan_times = vec!; for dt in start.series.take_while assert_eq!; # Ok::
impl Add for DateTime
fn add(self: Self, rhs: Span) -> DateTime
impl Add for DateTime
fn add(self: Self, rhs: SignedDuration) -> DateTime
impl Add for DateTime
fn add(self: Self, rhs: UnsignedDuration) -> DateTime
impl AddAssign for DateTime
fn add_assign(self: &mut Self, rhs: SignedDuration)
impl AddAssign for DateTime
fn add_assign(self: &mut Self, rhs: UnsignedDuration)
impl AddAssign for DateTime
fn add_assign(self: &mut Self, rhs: Span)
impl Clone for DateTime
fn clone(self: &Self) -> DateTime
impl Copy for DateTime
impl Debug for DateTime
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result
impl Default for DateTime
fn default() -> DateTime
impl Display for DateTime
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result
impl Eq for DateTime
impl Freeze for DateTime
impl From for DateTime
fn from(zdt: Zoned) -> DateTime
impl From for DateTime
fn from(date: Date) -> DateTime
impl FromStr for DateTime
fn from_str(string: &str) -> Result<DateTime, Error>
impl Hash for DateTime
fn hash<__H: $crate::hash::Hasher>(self: &Self, state: &mut __H)
impl Ord for DateTime
fn cmp(self: &Self, other: &DateTime) -> Ordering
impl PartialEq for DateTime
fn eq(self: &Self, other: &DateTime) -> bool
impl PartialOrd for DateTime
fn partial_cmp(self: &Self, other: &DateTime) -> Option<Ordering>
impl RefUnwindSafe for DateTime
impl Send for DateTime
impl Serialize for DateTime
fn serialize<S: serde::Serializer>(self: &Self, serializer: S) -> Result<<S as >::Ok, <S as >::Error>
impl StructuralPartialEq for DateTime
impl Sub for DateTime
fn sub(self: Self, rhs: Span) -> DateTime
impl Sub for DateTime
fn sub(self: Self, rhs: DateTime) -> Span
impl Sub for DateTime
fn sub(self: Self, rhs: SignedDuration) -> DateTime
impl Sub for DateTime
fn sub(self: Self, rhs: UnsignedDuration) -> DateTime
impl SubAssign for DateTime
fn sub_assign(self: &mut Self, rhs: SignedDuration)
impl SubAssign for DateTime
fn sub_assign(self: &mut Self, rhs: UnsignedDuration)
impl SubAssign for DateTime
fn sub_assign(self: &mut Self, rhs: Span)
impl Sync for DateTime
impl Unpin for DateTime
impl UnsafeUnpin for DateTime
impl UnwindSafe for DateTime
impl<'a> From for DateTime
fn from(zdt: &'a Zoned) -> DateTime
impl<'de> Deserialize for DateTime
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<DateTime, <D as >::Error>
impl<T> Any for DateTime
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for DateTime
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for DateTime
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> CloneToUninit for DateTime
unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)
impl<T> DeserializeOwned for DateTime
impl<T> From for DateTime
fn from(t: T) -> TReturns the argument unchanged.
impl<T> ToOwned for DateTime
fn to_owned(self: &Self) -> Tfn clone_into(self: &Self, target: &mut T)
impl<T> ToString for DateTime
fn to_string(self: &Self) -> String
impl<T, U> Into for DateTime
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for DateTime
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for DateTime
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>