pub struct Span { /* private fields */ }
Expand description
A span of time represented via a mixture of calendar and clock units.
A span represents a duration of time in units of years, months, weeks,
days, hours, minutes, seconds, milliseconds, microseconds and nanoseconds.
Spans are used to as inputs to routines like
Zoned::checked_add
and Date::saturating_sub
,
and are also outputs from routines like
Timestamp::since
and DateTime::until
.
§Range of spans
Except for nanoseconds, each unit can represent the full span of time expressible via any combination of datetime supported by Jiff. For example:
use jiff::{civil::{DateTime, DateTimeDifference}, ToSpan, Unit};
let options = DateTimeDifference::new(DateTime::MAX).largest(Unit::Year);
assert_eq!(DateTime::MIN.until(options)?.get_years(), 19_998);
let options = options.largest(Unit::Day);
assert_eq!(DateTime::MIN.until(options)?.get_days(), 7_304_483);
let options = options.largest(Unit::Microsecond);
assert_eq!(
DateTime::MIN.until(options)?.get_microseconds(),
631_107_417_599_999_999i64,
);
let options = options.largest(Unit::Nanosecond);
// Span is too big, overflow!
assert!(DateTime::MIN.until(options).is_err());
§Building spans
A default or empty span corresponds to a duration of zero time:
use jiff::Span;
assert!(Span::new().is_zero());
assert!(Span::default().is_zero());
Spans are Copy
types that have mutator methods on them for creating new
spans:
use jiff::Span;
let span = Span::new().days(5).hours(8).minutes(1);
assert_eq!(span.to_string(), "P5DT8H1M");
But Jiff provides a ToSpan
trait that defines extension methods on
primitive signed integers to make span creation terser:
use jiff::ToSpan;
let span = 5.days().hours(8).minutes(1);
assert_eq!(span.to_string(), "P5DT8H1M");
// singular units on integers can be used too:
let span = 1.day().hours(8).minutes(1);
assert_eq!(span.to_string(), "P1DT8H1M");
§Negative spans
A span may be negative. All of these are equivalent:
use jiff::{Span, ToSpan};
let span = -Span::new().days(5);
assert_eq!(span.to_string(), "-P5D");
let span = Span::new().days(5).negate();
assert_eq!(span.to_string(), "-P5D");
let span = Span::new().days(-5);
assert_eq!(span.to_string(), "-P5D");
let span = -Span::new().days(-5).negate();
assert_eq!(span.to_string(), "-P5D");
let span = -5.days();
assert_eq!(span.to_string(), "-P5D");
let span = (-5).days();
assert_eq!(span.to_string(), "-P5D");
let span = -(5.days());
assert_eq!(span.to_string(), "-P5D");
The sign of a span applies to the entire span. When a span is negative, then all of its units are negative:
use jiff::ToSpan;
let span = -5.days().hours(10).minutes(1);
assert_eq!(span.get_days(), -5);
assert_eq!(span.get_hours(), -10);
assert_eq!(span.get_minutes(), -1);
And if any of a span’s units are negative, then the entire span is regarded as negative:
use jiff::ToSpan;
// It's the same thing.
let span = (-5).days().hours(-10).minutes(-1);
assert_eq!(span.get_days(), -5);
assert_eq!(span.get_hours(), -10);
assert_eq!(span.get_minutes(), -1);
// Still the same. All negative.
let span = 5.days().hours(-10).minutes(1);
assert_eq!(span.get_days(), -5);
assert_eq!(span.get_hours(), -10);
assert_eq!(span.get_minutes(), -1);
// But this is not! The negation in front applies
// to the entire span, which was already negative
// by virtue of at least one of its units being
// negative. So the negation operator in front turns
// the span positive.
let span = -5.days().hours(-10).minutes(-1);
assert_eq!(span.get_days(), 5);
assert_eq!(span.get_hours(), 10);
assert_eq!(span.get_minutes(), 1);
You can also ask for the absolute value of a span:
use jiff::Span;
let span = Span::new().days(5).hours(10).minutes(1).negate().abs();
assert_eq!(span.get_days(), 5);
assert_eq!(span.get_hours(), 10);
assert_eq!(span.get_minutes(), 1);
§Parsing and printing
The Span
type provides convenient trait implementations of
std::str::FromStr
and std::fmt::Display
:
use jiff::{Span, ToSpan};
let span: Span = "P2m10dT2h30m".parse()?;
// By default, capital unit designator labels are used.
// This can be changed with `jiff::fmt::temporal::SpanPrinter::lowercase`.
assert_eq!(span.to_string(), "P2M10DT2H30M");
// Or use the "friendly" format by invoking the `Display` alternate:
assert_eq!(format!("{span:#}"), "2mo 10d 2h 30m");
// Parsing automatically supports both the ISO 8601 and "friendly"
// formats. Note that we use `Span::fieldwise` to create a `Span` that
// compares based on each field. To compare based on total duration, use
// `Span::compare` or `Span::total`.
let span: Span = "2mo 10d 2h 30m".parse()?;
assert_eq!(span, 2.months().days(10).hours(2).minutes(30).fieldwise());
let span: Span = "2 months, 10 days, 2 hours, 30 minutes".parse()?;
assert_eq!(span, 2.months().days(10).hours(2).minutes(30).fieldwise());
The format supported is a variation (nearly a subset) of the duration format specified in ISO 8601 and a Jiff-specific “friendly” format. Here are more examples:
use jiff::{Span, ToSpan};
let spans = [
// ISO 8601
("P40D", 40.days()),
("P1y1d", 1.year().days(1)),
("P3dT4h59m", 3.days().hours(4).minutes(59)),
("PT2H30M", 2.hours().minutes(30)),
("P1m", 1.month()),
("P1w", 1.week()),
("P1w4d", 1.week().days(4)),
("PT1m", 1.minute()),
("PT0.0021s", 2.milliseconds().microseconds(100)),
("PT0s", 0.seconds()),
("P0d", 0.seconds()),
(
"P1y1m1dT1h1m1.1s",
1.year().months(1).days(1).hours(1).minutes(1).seconds(1).milliseconds(100),
),
// Jiff's "friendly" format
("40d", 40.days()),
("40 days", 40.days()),
("1y1d", 1.year().days(1)),
("1yr 1d", 1.year().days(1)),
("3d4h59m", 3.days().hours(4).minutes(59)),
("3 days, 4 hours, 59 minutes", 3.days().hours(4).minutes(59)),
("3d 4h 59m", 3.days().hours(4).minutes(59)),
("2h30m", 2.hours().minutes(30)),
("2h 30m", 2.hours().minutes(30)),
("1mo", 1.month()),
("1w", 1.week()),
("1 week", 1.week()),
("1w4d", 1.week().days(4)),
("1 wk 4 days", 1.week().days(4)),
("1m", 1.minute()),
("0.0021s", 2.milliseconds().microseconds(100)),
("0s", 0.seconds()),
("0d", 0.seconds()),
("0 days", 0.seconds()),
(
"1y1mo1d1h1m1.1s",
1.year().months(1).days(1).hours(1).minutes(1).seconds(1).milliseconds(100),
),
(
"1yr 1mo 1day 1hr 1min 1.1sec",
1.year().months(1).days(1).hours(1).minutes(1).seconds(1).milliseconds(100),
),
(
"1 year, 1 month, 1 day, 1 hour, 1 minute 1.1 seconds",
1.year().months(1).days(1).hours(1).minutes(1).seconds(1).milliseconds(100),
),
(
"1 year, 1 month, 1 day, 01:01:01.1",
1.year().months(1).days(1).hours(1).minutes(1).seconds(1).milliseconds(100),
),
];
for (string, span) in spans {
let parsed: Span = string.parse()?;
assert_eq!(
span.fieldwise(),
parsed.fieldwise(),
"result of parsing {string:?}",
);
}
For more details, see the fmt::temporal
and
fmt::friendly
modules.
§Comparisons
A Span
does not implement the PartialEq
or Eq
traits. These traits
were implemented in an earlier version of Jiff, but they made it too
easy to introduce bugs. For example, 120.minutes()
and 2.hours()
always correspond to the same total duration, but they have different
representations in memory and so didn’t compare equivalent.
The reason why the PartialEq
and Eq
trait implementations do not do
comparisons with total duration is because it is fundamentally impossible
to do such comparisons without a reference date in all cases.
However, it is undeniably occasionally useful to do comparisons based
on the component fields, so long as such use cases can tolerate two
different spans comparing unequal even when their total durations are
equivalent. For example, many of the tests in Jiff (including the tests in
the documentation) work by comparing a Span
to an expected result. This
is a good demonstration of when fieldwise comparisons are appropriate.
To do fieldwise comparisons with a span, use the Span::fieldwise
method. This method creates a SpanFieldwise
, which is just a Span
that implements PartialEq
and Eq
in a fieldwise manner. In other words,
it’s a speed bump to ensure this is the kind of comparison you actually
want. For example:
use jiff::ToSpan;
assert_ne!(1.hour().fieldwise(), 60.minutes().fieldwise());
// These also work since you only need one fieldwise span to do a compare:
assert_ne!(1.hour(), 60.minutes().fieldwise());
assert_ne!(1.hour().fieldwise(), 60.minutes());
This is because doing true comparisons requires arithmetic and a relative
datetime in the general case, and which can fail due to overflow. This
operation is provided via Span::compare
:
use jiff::{civil::date, ToSpan};
// This doesn't need a reference date since it's only using time units.
assert_eq!(1.hour().compare(60.minutes())?, std::cmp::Ordering::Equal);
// But if you have calendar units, then you need a
// reference date at minimum:
assert!(1.month().compare(30.days()).is_err());
assert_eq!(
1.month().compare((30.days(), date(2025, 6, 1)))?,
std::cmp::Ordering::Equal,
);
// A month can be a differing number of days!
assert_eq!(
1.month().compare((30.days(), date(2025, 7, 1)))?,
std::cmp::Ordering::Greater,
);
§Arithmetic
Spans can be added or subtracted via Span::checked_add
and
Span::checked_sub
:
use jiff::{Span, ToSpan};
let span1 = 2.hours().minutes(20);
let span2: Span = "PT89400s".parse()?;
assert_eq!(span1.checked_add(span2)?, 27.hours().minutes(10).fieldwise());
When your spans involve calendar units, a relative datetime must be provided. (Because, for example, 1 month from March 1 is 31 days, but 1 month from April 1 is 30 days.)
use jiff::{civil::date, Span, ToSpan};
let span1 = 2.years().months(6).days(20);
let span2 = 400.days();
assert_eq!(
span1.checked_add((span2, date(2023, 1, 1)))?,
3.years().months(7).days(24).fieldwise(),
);
// The span changes when a leap year isn't included!
assert_eq!(
span1.checked_add((span2, date(2025, 1, 1)))?,
3.years().months(7).days(23).fieldwise(),
);
§Rounding and balancing
Unlike datetimes, multiple distinct Span
values can actually correspond
to the same duration of time. For example, all of the following correspond
to the same duration:
- 2 hours, 30 minutes
- 150 minutes
- 1 hour, 90 minutes
The first is said to be balanced. That is, its biggest non-zero unit cannot
be expressed in an integer number of units bigger than hours. But the
second is unbalanced because 150 minutes can be split up into hours and
minutes. We call this sort of span a “top-heavy” unbalanced span. The third
span is also unbalanced, but it’s “bottom-heavy” and rarely used. Jiff
will generally only produce spans of the first two types. In particular,
most Span
producing APIs accept a “largest” Unit
parameter, and the
result can be said to be a span “balanced up to the largest unit provided.”
Balanced and unbalanced spans can be switched between as needed via
the Span::round
API by providing a rounding configuration with
SpanRound::largest
` set:
use jiff::{SpanRound, ToSpan, Unit};
let span = 2.hours().minutes(30);
let unbalanced = span.round(SpanRound::new().largest(Unit::Minute))?;
assert_eq!(unbalanced, 150.minutes().fieldwise());
let balanced = unbalanced.round(SpanRound::new().largest(Unit::Hour))?;
assert_eq!(balanced, 2.hours().minutes(30).fieldwise());
Balancing can also be done as part of computing spans from two datetimes:
use jiff::{civil::date, ToSpan, Unit};
let zdt1 = date(2024, 7, 7).at(15, 23, 0, 0).in_tz("America/New_York")?;
let zdt2 = date(2024, 11, 5).at(8, 0, 0, 0).in_tz("America/New_York")?;
// To make arithmetic reversible, the default largest unit for spans of
// time computed from zoned datetimes is hours:
assert_eq!(zdt1.until(&zdt2)?, 2_897.hour().minutes(37).fieldwise());
// But we can ask for the span to be balanced up to years:
assert_eq!(
zdt1.until((Unit::Year, &zdt2))?,
3.months().days(28).hours(16).minutes(37).fieldwise(),
);
While the Span::round
API does balancing, it also, of course, does
rounding as well. Rounding occurs when the smallest unit is set to
something bigger than Unit::Nanosecond
:
use jiff::{ToSpan, Unit};
let span = 2.hours().minutes(30);
assert_eq!(span.round(Unit::Hour)?, 3.hours().fieldwise());
When rounding spans with calendar units (years, months or weeks), then a relative datetime is required:
use jiff::{civil::date, SpanRound, ToSpan, Unit};
let span = 10.years().months(11);
let options = SpanRound::new()
.smallest(Unit::Year)
.relative(date(2024, 1, 1));
assert_eq!(span.round(options)?, 11.years().fieldwise());
§Days are not always 24 hours!
That is, a Span
is made up of uniform and non-uniform units.
A uniform unit is a unit whose elapsed duration is always the same. A non-uniform unit is a unit whose elapsed duration is not always the same. There are two things that can impact the length of a non-uniform unit: the calendar date and the time zone.
Years and months are always considered non-uniform units. For example,
1 month from 2024-04-01
is 30 days, while 1 month from 2024-05-01
is
31 days. Similarly for years because of leap years.
Hours, minutes, seconds, milliseconds, microseconds and nanoseconds are always considered uniform units.
Days are only considered non-uniform when in the presence of a zone aware datetime. A day can be more or less than 24 hours, and it can be balanced up and down, but only when a relative zoned datetime is given. This typically happens because of DST (daylight saving time), but can also occur because of other time zone transitions too.
use jiff::{civil::date, SpanRound, ToSpan, Unit};
// 2024-03-10 in New York was 23 hours long,
// because of a jump to DST at 2am.
let zdt = date(2024, 3, 9).at(21, 0, 0, 0).in_tz("America/New_York")?;
// Goes from days to hours:
assert_eq!(
1.day().round(SpanRound::new().largest(Unit::Hour).relative(&zdt))?,
23.hours().fieldwise(),
);
// Goes from hours to days:
assert_eq!(
23.hours().round(SpanRound::new().largest(Unit::Day).relative(&zdt))?,
1.day().fieldwise(),
);
// 24 hours is more than 1 day starting at this time:
assert_eq!(
24.hours().round(SpanRound::new().largest(Unit::Day).relative(&zdt))?,
1.day().hours(1).fieldwise(),
);
And similarly, days can be longer than 24 hours:
use jiff::{civil::date, SpanRound, ToSpan, Unit};
// 2024-11-03 in New York was 25 hours long,
// because of a repetition of the 1 o'clock AM hour.
let zdt = date(2024, 11, 2).at(21, 0, 0, 0).in_tz("America/New_York")?;
// Goes from days to hours:
assert_eq!(
1.day().round(SpanRound::new().largest(Unit::Hour).relative(&zdt))?,
25.hours().fieldwise(),
);
// Goes from hours to days:
assert_eq!(
25.hours().round(SpanRound::new().largest(Unit::Day).relative(&zdt))?,
1.day().fieldwise(),
);
// 24 hours is less than 1 day starting at this time,
// so it stays in units of hours even though we ask
// for days (because 24 isn't enough hours to make
// 1 day):
assert_eq!(
24.hours().round(SpanRound::new().largest(Unit::Day).relative(&zdt))?,
24.hours().fieldwise(),
);
The APIs on Span
will otherwise treat days as non-uniform unless a
relative civil date is given, or there is an explicit opt-in to invariant
24-hour days. For example:
use jiff::{civil, SpanRelativeTo, ToSpan, Unit};
let span = 1.day();
// An error because days aren't always 24 hours:
assert_eq!(
span.total(Unit::Hour).unwrap_err().to_string(),
"using unit 'day' in a span or configuration requires that either \
a relative reference time be given or \
`SpanRelativeTo::days_are_24_hours()` is used to indicate \
invariant 24-hour days, but neither were provided",
);
// Opt into invariant 24 hour days without a relative date:
let marker = SpanRelativeTo::days_are_24_hours();
let hours = span.total((Unit::Hour, marker))?;
// Or use a relative civil date, and all days are 24 hours:
let date = civil::date(2020, 1, 1);
let hours = span.total((Unit::Hour, date))?;
assert_eq!(hours, 24.0);
In Jiff, all weeks are 7 days. And generally speaking, weeks only appear in
a Span
if they were explicitly put there by the caller or if they were
explicitly requested by the caller in an API. For example:
use jiff::{civil::date, ToSpan, Unit};
let dt1 = date(2024, 1, 1).at(0, 0, 0, 0);
let dt2 = date(2024, 7, 16).at(0, 0, 0, 0);
// Default units go up to days.
assert_eq!(dt1.until(dt2)?, 197.days().fieldwise());
// No weeks, even though we requested up to year.
assert_eq!(dt1.until((Unit::Year, dt2))?, 6.months().days(15).fieldwise());
// We get weeks only when we ask for them.
assert_eq!(dt1.until((Unit::Week, dt2))?, 28.weeks().days(1).fieldwise());
§Integration with std::time::Duration
and SignedDuration
While Jiff primarily uses a Span
for doing arithmetic on datetimes,
one can convert between a Span
and a std::time::Duration
or a
SignedDuration
. The main difference between them is that a Span
always keeps tracks of its individual units, and a Span
can represent
non-uniform units like months. In contrast, Duration
and SignedDuration
are always an exact elapsed amount of time. They don’t distinguish between
120 seconds
and 2 minutes
. And they can’t represent the concept of
“months” because a month doesn’t have a single fixed amount of time.
However, an exact duration is still useful in certain contexts. Beyond
that, it serves as an interoperability point due to the presence of an
unsigned exact duration type in the standard library. Because of that,
Jiff provides TryFrom
trait implementations for converting to and from a
std::time::Duration
(and, of course, a SignedDuration
). For example, to
convert from a std::time::Duration
to a Span
:
use std::time::Duration;
use jiff::{Span, ToSpan};
let duration = Duration::new(86_400, 123_456_789);
let span = Span::try_from(duration)?;
// A duration-to-span conversion always results in a span with
// non-zero units no bigger than seconds.
assert_eq!(
span.fieldwise(),
86_400.seconds().milliseconds(123).microseconds(456).nanoseconds(789),
);
// Note that the conversion is fallible! For example:
assert!(Span::try_from(Duration::from_secs(u64::MAX)).is_err());
// At present, a Jiff `Span` can only represent a range of time equal to
// the range of time expressible via minimum and maximum Jiff timestamps.
// Which is roughly -9999-01-01 to 9999-12-31, or ~20,000 years.
assert!(Span::try_from(Duration::from_secs(999_999_999_999)).is_err());
And to convert from a Span
to a std::time::Duration
:
use std::time::Duration;
use jiff::{Span, ToSpan};
let span = 86_400.seconds()
.milliseconds(123)
.microseconds(456)
.nanoseconds(789);
let duration = Duration::try_from(span)?;
assert_eq!(duration, Duration::new(86_400, 123_456_789));
Note that an error will occur when converting a Span
to a
std::time::Duration
using the TryFrom
trait implementation with units
bigger than hours:
use std::time::Duration;
use jiff::ToSpan;
let span = 2.days().hours(10);
assert_eq!(
Duration::try_from(span).unwrap_err().to_string(),
"failed to convert span to duration without relative datetime \
(must use `Span::to_duration` instead): using unit 'day' in a \
span or configuration requires that either a relative reference \
time be given or `SpanRelativeTo::days_are_24_hours()` is used \
to indicate invariant 24-hour days, but neither were provided",
);
Similar code can be written for SignedDuration
as well.
If you need to convert such spans, then as the error suggests, you’ll need
to use Span::to_duration
with a relative date.
And note that since a Span
is signed and a std::time::Duration
is unsigned,
converting a negative Span
to std::time::Duration
will always fail. One can use
Span::signum
to get the sign of the span and Span::abs
to make the
span positive before converting it to a Duration
:
use std::time::Duration;
use jiff::{Span, ToSpan};
let span = -86_400.seconds().nanoseconds(1);
let (sign, duration) = (span.signum(), Duration::try_from(span.abs())?);
assert_eq!((sign, duration), (-1, Duration::new(86_400, 1)));
Or, consider using Jiff’s own SignedDuration
instead:
use jiff::{SignedDuration, Span, ToSpan};
let span = -86_400.seconds().nanoseconds(1);
let duration = SignedDuration::try_from(span)?;
assert_eq!(duration, SignedDuration::new(-86_400, -1));
Implementations§
Source§impl Span
impl Span
Infallible routines for setting units on a Span
.
These are useful when the units are determined by the programmer or when
they have been validated elsewhere. In general, use these routines when
constructing an invalid Span
should be considered a bug in the program.
Sourcepub fn new() -> Span
pub fn new() -> Span
Creates a new span representing a zero duration. That is, a duration in which no time has passed.
Sourcepub fn years<I>(self, years: I) -> Span
pub fn years<I>(self, years: I) -> Span
Set the number of years on this span. The value may be negative.
The fallible version of this method is Span::try_years
.
§Panics
This panics when the number of years is too small or too big.
The minimum value is -19,998
.
The maximum value is 19,998
.
Sourcepub fn months<I>(self, months: I) -> Span
pub fn months<I>(self, months: I) -> Span
Set the number of months on this span. The value may be negative.
The fallible version of this method is Span::try_months
.
§Panics
This panics when the number of months is too small or too big.
The minimum value is -239,976
.
The maximum value is 239,976
.
Sourcepub fn weeks<I>(self, weeks: I) -> Span
pub fn weeks<I>(self, weeks: I) -> Span
Set the number of weeks on this span. The value may be negative.
The fallible version of this method is Span::try_weeks
.
§Panics
This panics when the number of weeks is too small or too big.
The minimum value is -1,043,497
.
The maximum value is 1_043_497
.
Sourcepub fn days<I>(self, days: I) -> Span
pub fn days<I>(self, days: I) -> Span
Set the number of days on this span. The value may be negative.
The fallible version of this method is Span::try_days
.
§Panics
This panics when the number of days is too small or too big.
The minimum value is -7,304,484
.
The maximum value is 7,304,484
.
Sourcepub fn hours<I>(self, hours: I) -> Span
pub fn hours<I>(self, hours: I) -> Span
Set the number of hours on this span. The value may be negative.
The fallible version of this method is Span::try_hours
.
§Panics
This panics when the number of hours is too small or too big.
The minimum value is -175,307,616
.
The maximum value is 175,307,616
.
Sourcepub fn minutes<I>(self, minutes: I) -> Span
pub fn minutes<I>(self, minutes: I) -> Span
Set the number of minutes on this span. The value may be negative.
The fallible version of this method is Span::try_minutes
.
§Panics
This panics when the number of minutes is too small or too big.
The minimum value is -10,518,456,960
.
The maximum value is 10,518,456,960
.
Sourcepub fn seconds<I>(self, seconds: I) -> Span
pub fn seconds<I>(self, seconds: I) -> Span
Set the number of seconds on this span. The value may be negative.
The fallible version of this method is Span::try_seconds
.
§Panics
This panics when the number of seconds is too small or too big.
The minimum value is -631,107,417,600
.
The maximum value is 631,107,417,600
.
Sourcepub fn milliseconds<I>(self, milliseconds: I) -> Span
pub fn milliseconds<I>(self, milliseconds: I) -> Span
Set the number of milliseconds on this span. The value may be negative.
The fallible version of this method is Span::try_milliseconds
.
§Panics
This panics when the number of milliseconds is too small or too big.
The minimum value is -631,107,417,600,000
.
The maximum value is 631,107,417,600,000
.
Sourcepub fn microseconds<I>(self, microseconds: I) -> Span
pub fn microseconds<I>(self, microseconds: I) -> Span
Set the number of microseconds on this span. The value may be negative.
The fallible version of this method is Span::try_microseconds
.
§Panics
This panics when the number of microseconds is too small or too big.
The minimum value is -631,107,417,600,000,000
.
The maximum value is 631,107,417,600,000,000
.
Sourcepub fn nanoseconds<I>(self, nanoseconds: I) -> Span
pub fn nanoseconds<I>(self, nanoseconds: I) -> Span
Set the number of nanoseconds on this span. The value may be negative.
Note that unlike all other units, a 64-bit integer number of
nanoseconds is not big enough to represent all possible spans between
all possible datetimes supported by Jiff. This means, for example, that
computing a span between two datetimes that are far enough apart and
requesting a largest unit of Unit::Nanosecond
, might return an
error due to lack of precision.
The fallible version of this method is Span::try_nanoseconds
.
§Panics
This panics when the number of nanoseconds is too small or too big.
The minimum value is -9,223,372,036,854,775,807
.
The maximum value is 9,223,372,036,854,775,807
.
Source§impl Span
impl Span
Fallible methods for setting units on a Span
.
These methods are useful when the span is made up of user provided values that may not be in range.
Sourcepub fn try_years<I>(self, years: I) -> Result<Span, Error>
pub fn try_years<I>(self, years: I) -> Result<Span, Error>
Set the number of years on this span. The value may be negative.
The panicking version of this method is Span::years
.
§Errors
This returns an error when the number of years is too small or too big.
The minimum value is -19,998
.
The maximum value is 19,998
.
Sourcepub fn try_months<I>(self, months: I) -> Result<Span, Error>
pub fn try_months<I>(self, months: I) -> Result<Span, Error>
Set the number of months on this span. The value may be negative.
The panicking version of this method is Span::months
.
§Errors
This returns an error when the number of months is too small or too big.
The minimum value is -239,976
.
The maximum value is 239,976
.
Sourcepub fn try_weeks<I>(self, weeks: I) -> Result<Span, Error>
pub fn try_weeks<I>(self, weeks: I) -> Result<Span, Error>
Set the number of weeks on this span. The value may be negative.
The panicking version of this method is Span::weeks
.
§Errors
This returns an error when the number of weeks is too small or too big.
The minimum value is -1,043,497
.
The maximum value is 1_043_497
.
Sourcepub fn try_days<I>(self, days: I) -> Result<Span, Error>
pub fn try_days<I>(self, days: I) -> Result<Span, Error>
Set the number of days on this span. The value may be negative.
The panicking version of this method is Span::days
.
§Errors
This returns an error when the number of days is too small or too big.
The minimum value is -7,304,484
.
The maximum value is 7,304,484
.
Sourcepub fn try_hours<I>(self, hours: I) -> Result<Span, Error>
pub fn try_hours<I>(self, hours: I) -> Result<Span, Error>
Set the number of hours on this span. The value may be negative.
The panicking version of this method is Span::hours
.
§Errors
This returns an error when the number of hours is too small or too big.
The minimum value is -175,307,616
.
The maximum value is 175,307,616
.
Sourcepub fn try_minutes<I>(self, minutes: I) -> Result<Span, Error>
pub fn try_minutes<I>(self, minutes: I) -> Result<Span, Error>
Set the number of minutes on this span. The value may be negative.
The panicking version of this method is Span::minutes
.
§Errors
This returns an error when the number of minutes is too small or too big.
The minimum value is -10,518,456,960
.
The maximum value is 10,518,456,960
.
Sourcepub fn try_seconds<I>(self, seconds: I) -> Result<Span, Error>
pub fn try_seconds<I>(self, seconds: I) -> Result<Span, Error>
Set the number of seconds on this span. The value may be negative.
The panicking version of this method is Span::seconds
.
§Errors
This returns an error when the number of seconds is too small or too big.
The minimum value is -631,107,417,600
.
The maximum value is 631,107,417,600
.
Sourcepub fn try_milliseconds<I>(self, milliseconds: I) -> Result<Span, Error>
pub fn try_milliseconds<I>(self, milliseconds: I) -> Result<Span, Error>
Set the number of milliseconds on this span. The value may be negative.
The panicking version of this method is Span::milliseconds
.
§Errors
This returns an error when the number of milliseconds is too small or
too big.
The minimum value is -631,107,417,600,000
.
The maximum value is 631,107,417,600,000
.
Sourcepub fn try_microseconds<I>(self, microseconds: I) -> Result<Span, Error>
pub fn try_microseconds<I>(self, microseconds: I) -> Result<Span, Error>
Set the number of microseconds on this span. The value may be negative.
The panicking version of this method is Span::microseconds
.
§Errors
This returns an error when the number of microseconds is too small or
too big.
The minimum value is -631,107,417,600,000,000
.
The maximum value is 631,107,417,600,000,000
.
Sourcepub fn try_nanoseconds<I>(self, nanoseconds: I) -> Result<Span, Error>
pub fn try_nanoseconds<I>(self, nanoseconds: I) -> Result<Span, Error>
Set the number of nanoseconds on this span. The value may be negative.
Note that unlike all other units, a 64-bit integer number of
nanoseconds is not big enough to represent all possible spans between
all possible datetimes supported by Jiff. This means, for example, that
computing a span between two datetimes that are far enough apart and
requesting a largest unit of Unit::Nanosecond
, might return an
error due to lack of precision.
The panicking version of this method is Span::nanoseconds
.
§Errors
This returns an error when the number of nanoseconds is too small or
too big.
The minimum value is -9,223,372,036,854,775,807
.
The maximum value is 9,223,372,036,854,775,807
.
Source§impl Span
impl Span
Routines for accessing the individual units in a Span
.
Sourcepub fn get_years(&self) -> i16
pub fn get_years(&self) -> i16
Returns the number of year units in this span.
Note that this is not the same as the total number of years in the
span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{civil::date, ToSpan, Unit};
let span = 3.years().months(24);
assert_eq!(3, span.get_years());
assert_eq!(5.0, span.total((Unit::Year, date(2024, 1, 1)))?);
Sourcepub fn get_months(&self) -> i32
pub fn get_months(&self) -> i32
Returns the number of month units in this span.
Note that this is not the same as the total number of months in the
span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{civil::date, ToSpan, Unit};
let span = 7.months().days(59);
assert_eq!(7, span.get_months());
assert_eq!(9.0, span.total((Unit::Month, date(2022, 6, 1)))?);
Sourcepub fn get_weeks(&self) -> i32
pub fn get_weeks(&self) -> i32
Returns the number of week units in this span.
Note that this is not the same as the total number of weeks in the
span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{civil::date, ToSpan, Unit};
let span = 3.weeks().days(14);
assert_eq!(3, span.get_weeks());
assert_eq!(5.0, span.total((Unit::Week, date(2024, 1, 1)))?);
Sourcepub fn get_days(&self) -> i32
pub fn get_days(&self) -> i32
Returns the number of day units in this span.
Note that this is not the same as the total number of days in the
span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{ToSpan, Unit, Zoned};
let span = 3.days().hours(47);
assert_eq!(3, span.get_days());
let zdt: Zoned = "2024-03-07[America/New_York]".parse()?;
assert_eq!(5.0, span.total((Unit::Day, &zdt))?);
Sourcepub fn get_hours(&self) -> i32
pub fn get_hours(&self) -> i32
Returns the number of hour units in this span.
Note that this is not the same as the total number of hours in the
span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{ToSpan, Unit};
let span = 3.hours().minutes(120);
assert_eq!(3, span.get_hours());
assert_eq!(5.0, span.total(Unit::Hour)?);
Sourcepub fn get_minutes(&self) -> i64
pub fn get_minutes(&self) -> i64
Returns the number of minute units in this span.
Note that this is not the same as the total number of minutes in the
span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{ToSpan, Unit};
let span = 3.minutes().seconds(120);
assert_eq!(3, span.get_minutes());
assert_eq!(5.0, span.total(Unit::Minute)?);
Sourcepub fn get_seconds(&self) -> i64
pub fn get_seconds(&self) -> i64
Returns the number of second units in this span.
Note that this is not the same as the total number of seconds in the
span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{ToSpan, Unit};
let span = 3.seconds().milliseconds(2_000);
assert_eq!(3, span.get_seconds());
assert_eq!(5.0, span.total(Unit::Second)?);
Sourcepub fn get_milliseconds(&self) -> i64
pub fn get_milliseconds(&self) -> i64
Returns the number of millisecond units in this span.
Note that this is not the same as the total number of milliseconds in
the span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{ToSpan, Unit};
let span = 3.milliseconds().microseconds(2_000);
assert_eq!(3, span.get_milliseconds());
assert_eq!(5.0, span.total(Unit::Millisecond)?);
Sourcepub fn get_microseconds(&self) -> i64
pub fn get_microseconds(&self) -> i64
Returns the number of microsecond units in this span.
Note that this is not the same as the total number of microseconds in
the span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{ToSpan, Unit};
let span = 3.microseconds().nanoseconds(2_000);
assert_eq!(3, span.get_microseconds());
assert_eq!(5.0, span.total(Unit::Microsecond)?);
Sourcepub fn get_nanoseconds(&self) -> i64
pub fn get_nanoseconds(&self) -> i64
Returns the number of nanosecond units in this span.
Note that this is not the same as the total number of nanoseconds in
the span. To get that, you’ll need to use either Span::round
or
Span::total
.
§Example
use jiff::{ToSpan, Unit};
let span = 3.microseconds().nanoseconds(2_000);
assert_eq!(2_000, span.get_nanoseconds());
assert_eq!(5_000.0, span.total(Unit::Nanosecond)?);
Source§impl Span
impl Span
Routines for manipulating, comparing and inspecting Span
values.
Sourcepub fn abs(self) -> Span
pub fn abs(self) -> Span
Returns a new span that is the absolute value of this span.
If this span is zero or positive, then this is a no-op.
§Example
use jiff::ToSpan;
let span = -100.seconds();
assert_eq!(span.to_string(), "-PT100S");
let span = span.abs();
assert_eq!(span.to_string(), "PT100S");
Sourcepub fn negate(self) -> Span
pub fn negate(self) -> Span
Returns a new span that negates this span.
If this span is zero, then this is a no-op. If this span is negative, then the returned span is positive. If this span is positive, then the returned span is negative.
§Example
use jiff::ToSpan;
let span = 100.days();
assert_eq!(span.to_string(), "P100D");
let span = span.negate();
assert_eq!(span.to_string(), "-P100D");
§Example: available via the negation operator
This routine can also be used via -
:
use jiff::ToSpan;
let span = 100.days();
assert_eq!(span.to_string(), "P100D");
let span = -span;
assert_eq!(span.to_string(), "-P100D");
Sourcepub fn signum(self) -> i8
pub fn signum(self) -> i8
Returns the “sign number” or “signum” of this span.
The number returned is -1
when this span is negative,
0
when this span is zero and 1
when this span is positive.
Sourcepub fn is_positive(self) -> bool
pub fn is_positive(self) -> bool
Returns true if and only if this span is positive.
This returns false when the span is zero or negative.
§Example
use jiff::ToSpan;
assert!(!2.months().is_negative());
assert!((-2.months()).is_negative());
Sourcepub fn is_negative(self) -> bool
pub fn is_negative(self) -> bool
Returns true if and only if this span is negative.
This returns false when the span is zero or positive.
§Example
use jiff::ToSpan;
assert!(!2.months().is_negative());
assert!((-2.months()).is_negative());
Sourcepub fn is_zero(self) -> bool
pub fn is_zero(self) -> bool
Returns true if and only if every field in this span is set to 0
.
§Example
use jiff::{Span, ToSpan};
assert!(Span::new().is_zero());
assert!(Span::default().is_zero());
assert!(0.seconds().is_zero());
assert!(!0.seconds().seconds(1).is_zero());
assert!(0.seconds().seconds(1).seconds(0).is_zero());
Sourcepub fn fieldwise(self) -> SpanFieldwise
pub fn fieldwise(self) -> SpanFieldwise
Returns this Span
as a value with a type that implements the
Hash
, Eq
and PartialEq
traits in a fieldwise fashion.
A SpanFieldwise
is meant to make it easy to compare two spans in a
“dumb” way based purely on its unit values. This is distinct from
something like Span::compare
that performs a comparison on the
actual elapsed time of two spans.
It is generally discouraged to use SpanFieldwise
since spans that
represent an equivalent elapsed amount of time may compare unequal.
However, in some cases, it is useful to be able to assert precise
field values. For example, Jiff itself makes heavy use of fieldwise
comparisons for tests.
§Example: the difference between SpanFieldwise
and Span::compare
In short, SpanFieldwise
considers 2 hours
and 120 minutes
to be
distinct values, but Span::compare
considers them to be equivalent:
use std::cmp::Ordering;
use jiff::ToSpan;
assert_ne!(120.minutes().fieldwise(), 2.hours().fieldwise());
assert_eq!(120.minutes().compare(2.hours())?, Ordering::Equal);
Sourcepub fn checked_mul(self, rhs: i64) -> Result<Span, Error>
pub fn checked_mul(self, rhs: i64) -> Result<Span, Error>
Multiplies each field in this span by a given integer.
If this would cause any individual field in this span to overflow, then this returns an error.
§Example
use jiff::ToSpan;
let span = 4.days().seconds(8);
assert_eq!(span.checked_mul(2)?, 8.days().seconds(16).fieldwise());
assert_eq!(span.checked_mul(-3)?, -12.days().seconds(24).fieldwise());
// Notice that no re-balancing is done. It's "just" multiplication.
assert_eq!(span.checked_mul(10)?, 40.days().seconds(80).fieldwise());
let span = 10_000.years();
// too big!
assert!(span.checked_mul(3).is_err());
§Example: available via the multiplication operator
This method can be used via the *
operator. Note though that a panic
happens on overflow.
use jiff::ToSpan;
let span = 4.days().seconds(8);
assert_eq!(span * 2, 8.days().seconds(16).fieldwise());
assert_eq!(2 * span, 8.days().seconds(16).fieldwise());
assert_eq!(span * -3, -12.days().seconds(24).fieldwise());
assert_eq!(-3 * span, -12.days().seconds(24).fieldwise());
Sourcepub fn checked_add<'a, A>(&self, options: A) -> Result<Span, Error>where
A: Into<SpanArithmetic<'a>>,
pub fn checked_add<'a, A>(&self, options: A) -> Result<Span, Error>where
A: Into<SpanArithmetic<'a>>,
Adds a span to this one and returns the sum as a new span.
When adding a span with units greater than hours, callers must provide a relative datetime to anchor the spans.
Arithmetic proceeds as specified in RFC 5545. Bigger units are added together before smaller units.
This routine accepts anything that implements Into<SpanArithmetic>
.
There are some trait implementations that make using this routine
ergonomic:
From<Span> for SpanArithmetic
adds the given span to this one.From<(Span, civil::Date)> for SpanArithmetic
adds the given span to this one relative to the given date. There are alsoFrom
implementations forcivil::DateTime
andZoned
.
This also works with different duration types, such as
SignedDuration
and std::time::Duration
, via additional trait
implementations:
From<SignedDuration> for SpanArithmetic
adds the given duration to this one.From<(SignedDuration, civil::Date)> for SpanArithmetic
adds the given duration to this one relative to the given date. There are alsoFrom
implementations forcivil::DateTime
andZoned
.
And similarly for std::time::Duration
.
Adding a negative span is equivalent to subtracting its absolute value.
The largest non-zero unit in the span returned is at most the largest non-zero unit among the two spans being added. For an absolute duration, its “largest” unit is considered to be nanoseconds.
The sum returned is automatically re-balanced so that the span is not “bottom heavy.”
§Errors
This returns an error when adding the two spans would overflow any individual field of a span. This will also return an error if either of the spans have non-zero units of days or greater and no relative reference time is provided.
Callers may use SpanArithmetic::days_are_24_hours
as a special
marker instead of providing a relative civil date to indicate that
all days should be 24 hours long. This also results in treating all
weeks as seven 24 hour days (168 hours).
§Example
use jiff::ToSpan;
assert_eq!(
1.hour().checked_add(30.minutes())?,
1.hour().minutes(30).fieldwise(),
);
§Example: re-balancing
This example shows how units are automatically rebalanced into bigger units when appropriate.
use jiff::ToSpan;
let span1 = 2.hours().minutes(59);
let span2 = 2.minutes();
assert_eq!(span1.checked_add(span2)?, 3.hours().minutes(1).fieldwise());
§Example: days are not assumed to be 24 hours by default
When dealing with units involving days or weeks, one must either provide a relative datetime (shown in the following examples) or opt into invariant 24 hour days:
use jiff::{SpanRelativeTo, ToSpan};
let span1 = 2.days().hours(23);
let span2 = 2.hours();
assert_eq!(
span1.checked_add((span2, SpanRelativeTo::days_are_24_hours()))?,
3.days().hours(1).fieldwise(),
);
§Example: adding spans with calendar units
If you try to add two spans with calendar units without specifying a relative datetime, you’ll get an error:
use jiff::ToSpan;
let span1 = 1.month().days(15);
let span2 = 15.days();
assert!(span1.checked_add(span2).is_err());
A relative datetime is needed because calendar spans may correspond to different actual durations depending on where the span begins:
use jiff::{civil::date, ToSpan};
let span1 = 1.month().days(15);
let span2 = 15.days();
// 1 month from March 1 is 31 days...
assert_eq!(
span1.checked_add((span2, date(2008, 3, 1)))?,
2.months().fieldwise(),
);
// ... but 1 month from April 1 is 30 days!
assert_eq!(
span1.checked_add((span2, date(2008, 4, 1)))?,
1.month().days(30).fieldwise(),
);
§Example: error on overflow
Adding two spans can overflow, and this will result in an error:
use jiff::ToSpan;
assert!(19_998.years().checked_add(1.year()).is_err());
§Example: adding an absolute duration to a span
This shows how one isn’t limited to just adding two spans together. One can also add absolute durations to a span.
use std::time::Duration;
use jiff::{SignedDuration, ToSpan};
assert_eq!(
1.hour().checked_add(SignedDuration::from_mins(30))?,
1.hour().minutes(30).fieldwise(),
);
assert_eq!(
1.hour().checked_add(Duration::from_secs(30 * 60))?,
1.hour().minutes(30).fieldwise(),
);
Note that even when adding an absolute duration, if the span contains non-uniform units, you still need to provide a relative datetime:
use jiff::{civil::date, SignedDuration, ToSpan};
// Might be 1 month or less than 1 month!
let dur = SignedDuration::from_hours(30 * 24);
// No relative datetime provided even when the span
// contains non-uniform units results in an error.
assert!(1.month().checked_add(dur).is_err());
// In this case, 30 days is one month (April).
assert_eq!(
1.month().checked_add((dur, date(2024, 3, 1)))?,
2.months().fieldwise(),
);
// In this case, 30 days is less than one month (May).
assert_eq!(
1.month().checked_add((dur, date(2024, 4, 1)))?,
1.month().days(30).fieldwise(),
);
Sourcepub fn checked_sub<'a, A>(&self, options: A) -> Result<Span, Error>where
A: Into<SpanArithmetic<'a>>,
pub fn checked_sub<'a, A>(&self, options: A) -> Result<Span, Error>where
A: Into<SpanArithmetic<'a>>,
This routine is identical to Span::checked_add
with the given
duration negated.
§Errors
This has the same error conditions as Span::checked_add
.
§Example
use std::time::Duration;
use jiff::{SignedDuration, ToSpan};
assert_eq!(
1.hour().checked_sub(30.minutes())?,
30.minutes().fieldwise(),
);
assert_eq!(
1.hour().checked_sub(SignedDuration::from_mins(30))?,
30.minutes().fieldwise(),
);
assert_eq!(
1.hour().checked_sub(Duration::from_secs(30 * 60))?,
30.minutes().fieldwise(),
);
Sourcepub fn compare<'a, C>(&self, options: C) -> Result<Ordering, Error>where
C: Into<SpanCompare<'a>>,
pub fn compare<'a, C>(&self, options: C) -> Result<Ordering, Error>where
C: Into<SpanCompare<'a>>,
Compares two spans in terms of how long they are. Negative spans are considered shorter than the zero span.
Two spans compare equal when they correspond to the same duration
of time, even if their individual fields are different. This is in
contrast to the Eq
trait implementation of Span
, which performs
exact field-wise comparisons. This split exists because the comparison
provided by this routine is “heavy” in that it may need to do
datetime arithmetic to return an answer. In contrast, the Eq
trait
implementation is “cheap.”
This routine accepts anything that implements Into<SpanCompare>
.
There are some trait implementations that make using this routine
ergonomic:
From<Span> for SpanCompare
compares the given span to this one.From<(Span, civil::Date)> for SpanArithmetic
compares the given span to this one relative to the given date. There are alsoFrom
implementations forcivil::DateTime
andZoned
.
§Errors
If either of the spans being compared have a non-zero calendar unit (units bigger than hours), then this routine requires a relative datetime. If one is not provided, then an error is returned.
An error can also occur when adding either span to the relative datetime given results in overflow.
Callers may use SpanArithmetic::days_are_24_hours
as a special
marker instead of providing a relative civil date to indicate that
all days should be 24 hours long. This also results in treating all
weeks as seven 24 hour days (168 hours).
§Example
use jiff::ToSpan;
let span1 = 3.hours();
let span2 = 180.minutes();
assert_eq!(span1.compare(span2)?, std::cmp::Ordering::Equal);
// But notice that the two spans are not equal via `Eq`:
assert_ne!(span1.fieldwise(), span2.fieldwise());
§Example: negative spans are less than zero
use jiff::ToSpan;
let span1 = -1.second();
let span2 = 0.seconds();
assert_eq!(span1.compare(span2)?, std::cmp::Ordering::Less);
§Example: comparisons take DST into account
When a relative datetime is time zone aware, then DST is taken into account when comparing spans:
use jiff::{civil, ToSpan, Zoned};
let span1 = 79.hours().minutes(10);
let span2 = 3.days().hours(7).seconds(630);
let span3 = 3.days().hours(6).minutes(50);
let relative: Zoned = "2020-11-01T00-07[America/Los_Angeles]".parse()?;
let mut spans = [span1, span2, span3];
spans.sort_by(|s1, s2| s1.compare((s2, &relative)).unwrap());
assert_eq!(
spans.map(|sp| sp.fieldwise()),
[span1.fieldwise(), span3.fieldwise(), span2.fieldwise()],
);
// Compare with the result of sorting without taking DST into account.
// We can that by providing a relative civil date:
let relative = civil::date(2020, 11, 1);
spans.sort_by(|s1, s2| s1.compare((s2, relative)).unwrap());
assert_eq!(
spans.map(|sp| sp.fieldwise()),
[span3.fieldwise(), span1.fieldwise(), span2.fieldwise()],
);
See the examples for Span::total
if you want to sort spans without
an unwrap()
call.
Sourcepub fn total<'a, T>(&self, options: T) -> Result<f64, Error>
pub fn total<'a, T>(&self, options: T) -> Result<f64, Error>
Returns a floating point number representing the total number of a specific unit (as given) in this span. If the span is not evenly divisible by the requested units, then the number returned may have a fractional component.
This routine accepts anything that implements Into<SpanTotal>
. There
are some trait implementations that make using this routine ergonomic:
From<Unit> for SpanTotal
computes a total for the given unit in this span.From<(Unit, civil::Date)> for SpanTotal
computes a total for the given unit in this span, relative to the given date. There are alsoFrom
implementations forcivil::DateTime
andZoned
.
§Errors
If this span has any non-zero calendar unit (units bigger than hours), then this routine requires a relative datetime. If one is not provided, then an error is returned.
An error can also occur when adding the span to the relative datetime given results in overflow.
Callers may use SpanArithmetic::days_are_24_hours
as a special
marker instead of providing a relative civil date to indicate that
all days should be 24 hours long. This also results in treating all
weeks as seven 24 hour days (168 hours).
§Example
This example shows how to find the number of seconds in a particular span:
use jiff::{ToSpan, Unit};
let span = 3.hours().minutes(10);
assert_eq!(span.total(Unit::Second)?, 11_400.0);
§Example: 24 hour days
This shows how to find the total number of 24 hour days in
123,456,789
seconds.
use jiff::{SpanTotal, ToSpan, Unit};
let span = 123_456_789.seconds();
assert_eq!(
span.total(SpanTotal::from(Unit::Day).days_are_24_hours())?,
1428.8980208333332,
);
§Example: DST is taken into account
The month of March 2024 in America/New_York
had 31 days, but one of
those days was 23 hours long due a transition into daylight saving
time:
use jiff::{civil::date, ToSpan, Unit};
let span = 744.hours();
let relative = date(2024, 3, 1).in_tz("America/New_York")?;
// Because of the short day, 744 hours is actually a little *more* than
// 1 month starting from 2024-03-01.
assert_eq!(span.total((Unit::Month, &relative))?, 1.0013888888888889);
Now compare what happens when the relative datetime is civil and not time zone aware:
use jiff::{civil::date, ToSpan, Unit};
let span = 744.hours();
let relative = date(2024, 3, 1);
assert_eq!(span.total((Unit::Month, relative))?, 1.0);
§Example: infallible sorting
The sorting example in Span::compare
has to use unwrap()
in
its sort_by(..)
call because Span::compare
may fail and there
is no “fallible” sorting routine in Rust’s standard library (as of
2024-07-07). While the ways in which Span::compare
can fail for
a valid configuration are limited to overflow for “extreme” values, it
is possible to sort spans infallibly by computing floating point
representations for each span up-front:
use jiff::{civil::Date, ToSpan, Unit, Zoned};
let span1 = 79.hours().minutes(10);
let span2 = 3.days().hours(7).seconds(630);
let span3 = 3.days().hours(6).minutes(50);
let relative: Zoned = "2020-11-01T00-07[America/Los_Angeles]".parse()?;
let mut spans = [
(span1, span1.total((Unit::Day, &relative))?),
(span2, span2.total((Unit::Day, &relative))?),
(span3, span3.total((Unit::Day, &relative))?),
];
spans.sort_by(|&(_, total1), &(_, total2)| total1.total_cmp(&total2));
assert_eq!(
spans.map(|(sp, _)| sp.fieldwise()),
[span1.fieldwise(), span3.fieldwise(), span2.fieldwise()],
);
// Compare with the result of sorting without taking DST into account.
// We do that here by providing a relative civil date.
let relative: Date = "2020-11-01".parse()?;
let mut spans = [
(span1, span1.total((Unit::Day, relative))?),
(span2, span2.total((Unit::Day, relative))?),
(span3, span3.total((Unit::Day, relative))?),
];
spans.sort_by(|&(_, total1), &(_, total2)| total1.total_cmp(&total2));
assert_eq!(
spans.map(|(sp, _)| sp.fieldwise()),
[span3.fieldwise(), span1.fieldwise(), span2.fieldwise()],
);
Sourcepub fn round<'a, R>(self, options: R) -> Result<Span, Error>
pub fn round<'a, R>(self, options: R) -> Result<Span, Error>
Returns a new span that is balanced and rounded.
Rounding a span has a number of parameters, all of which are optional. When no parameters are given, then no rounding or balancing is done, and the span as given is returned. That is, it’s a no-op.
The parameters are, in brief:
SpanRound::largest
sets the largestUnit
that is allowed to be non-zero in the span returned. When only the largest unit is set, rounding itself doesn’t occur and instead the span is merely balanced.SpanRound::smallest
sets the smallestUnit
that is allowed to be non-zero in the span returned. By default, it is set toUnit::Nanosecond
, i.e., no rounding occurs. When the smallest unit is set to something bigger than nanoseconds, then the non-zero units in the span smaller than the smallest unit are used to determine how the span should be rounded. For example, rounding1 hour 59 minutes
to the nearest hour using the default rounding mode would produce2 hours
.SpanRound::mode
determines how to handle the remainder when rounding. The default isRoundMode::HalfExpand
, which corresponds to how you were taught to round in school. Alternative modes, likeRoundMode::Trunc
, exist too. For example, a truncating rounding of1 hour 59 minutes
to the nearest hour would produce1 hour
.SpanRound::increment
sets the rounding granularity to use for the configured smallest unit. For example, if the smallest unit is minutes and the increment is 5, then the span returned will always have its minute units set to a multiple of5
.SpanRound::relative
sets the datetime from which to interpret the span. This is required when rounding spans with calendar units (years, months or weeks). When a relative datetime is time zone aware, then rounding accounts for the fact that not all days are 24 hours long. When a relative datetime is omitted or is civil (not time zone aware), then days are always 24 hours long.
§Constructing a SpanRound
This routine accepts anything that implements Into<SpanRound>
. There
are a few key trait implementations that make this convenient:
From<Unit> for SpanRound
will construct a rounding configuration where the smallest unit is set to the one given.From<(Unit, i64)> for SpanRound
will construct a rounding configuration where the smallest unit and the rounding increment are set to the ones given.
To set other options (like the largest unit, the rounding mode and the
relative datetime), one must explicitly create a SpanRound
and pass
it to this routine.
§Errors
In general, there are two main ways for rounding to fail: an improper
configuration like trying to round a span with calendar units but
without a relative datetime, or when overflow occurs. Overflow can
occur when the span, added to the relative datetime if given, would
exceed the minimum or maximum datetime values. Overflow can also occur
if the span is too big to fit into the requested unit configuration.
For example, a span like 19_998.years()
cannot be represented with a
64-bit integer number of nanoseconds.
Callers may use SpanArithmetic::days_are_24_hours
as a special
marker instead of providing a relative civil date to indicate that
all days should be 24 hours long. This also results in treating all
weeks as seven 24 hour days (168 hours).
§Example: balancing
This example demonstrates balancing, not rounding. And in particular, this example shows how to balance a span as much as possible (i.e., with units of hours or smaller) without needing to specify a relative datetime:
use jiff::{SpanRound, ToSpan, Unit};
let span = 123_456_789_123_456_789i64.nanoseconds();
assert_eq!(
span.round(SpanRound::new().largest(Unit::Hour))?.fieldwise(),
34_293.hours().minutes(33).seconds(9)
.milliseconds(123).microseconds(456).nanoseconds(789),
);
Or you can opt into invariant 24-hour days (and 7-day weeks) without a
relative date with SpanRound::days_are_24_hours
:
use jiff::{SpanRound, ToSpan, Unit};
let span = 123_456_789_123_456_789i64.nanoseconds();
assert_eq!(
span.round(
SpanRound::new().largest(Unit::Day).days_are_24_hours(),
)?.fieldwise(),
1_428.days()
.hours(21).minutes(33).seconds(9)
.milliseconds(123).microseconds(456).nanoseconds(789),
);
§Example: balancing and rounding
This example is like the one before it, but where we round to the nearest second:
use jiff::{SpanRound, ToSpan, Unit};
let span = 123_456_789_123_456_789i64.nanoseconds();
assert_eq!(
span.round(SpanRound::new().largest(Unit::Hour).smallest(Unit::Second))?,
34_293.hours().minutes(33).seconds(9).fieldwise(),
);
Or, just rounding to the nearest hour can make use of the
From<Unit> for SpanRound
trait implementation:
use jiff::{ToSpan, Unit};
let span = 123_456_789_123_456_789i64.nanoseconds();
assert_eq!(span.round(Unit::Hour)?, 34_294.hours().fieldwise());
§Example: balancing with a relative datetime
Even with calendar units, so long as a relative datetime is provided, it’s easy to turn days into bigger units:
use jiff::{civil::date, SpanRound, ToSpan, Unit};
let span = 1_000.days();
let relative = date(2000, 1, 1);
let options = SpanRound::new().largest(Unit::Year).relative(relative);
assert_eq!(span.round(options)?, 2.years().months(8).days(26).fieldwise());
§Example: round to the nearest half-hour
use jiff::{Span, ToSpan, Unit};
let span: Span = "PT23h50m3.123s".parse()?;
assert_eq!(span.round((Unit::Minute, 30))?, 24.hours().fieldwise());
§Example: yearly quarters in a span
This example shows how to find how many full 3 month quarters are in a particular span of time.
use jiff::{civil::date, RoundMode, SpanRound, ToSpan, Unit};
let span1 = 10.months().days(15);
let round = SpanRound::new()
.smallest(Unit::Month)
.increment(3)
.mode(RoundMode::Trunc)
// A relative datetime must be provided when
// rounding involves calendar units.
.relative(date(2024, 1, 1));
let span2 = span1.round(round)?;
assert_eq!(span2.get_months() / 3, 3);
Sourcepub fn to_duration<'a, R>(&self, relative: R) -> Result<SignedDuration, Error>where
R: Into<SpanRelativeTo<'a>>,
pub fn to_duration<'a, R>(&self, relative: R) -> Result<SignedDuration, Error>where
R: Into<SpanRelativeTo<'a>>,
Converts a Span
to a SignedDuration
relative to the date given.
In most cases, it is unlikely that you’ll need to use this routine to
convert a Span
to a SignedDuration
. Namely, by default:
Zoned::until
guarantees that the biggest non-zero unit is hours.Timestamp::until
guarantees that the biggest non-zero unit is seconds.DateTime::until
guarantees that the biggest non-zero unit is days.Date::until
guarantees that the biggest non-zero unit is days.Time::until
guarantees that the biggest non-zero unit is hours.
In the above, only DateTime::until
and Date::until
return
calendar units by default. In which case, one may pass
SpanRelativeTo::days_are_24_hours
or an actual relative date to
resolve the length of a day.
Of course, any of the above can be changed by asking, for example,
Zoned::until
to return units up to years.
§Errors
This returns an error if adding this span to the date given results in
overflow. This can also return an error if one uses
SpanRelativeTo::days_are_24_hours
with a Span
that has non-zero
units greater than weeks.
§Example: converting a span with calendar units to a SignedDuration
This compares the number of seconds in a non-leap year with a leap year:
use jiff::{civil::date, SignedDuration, ToSpan};
let span = 1.year();
let duration = span.to_duration(date(2024, 1, 1))?;
assert_eq!(duration, SignedDuration::from_secs(31_622_400));
let duration = span.to_duration(date(2023, 1, 1))?;
assert_eq!(duration, SignedDuration::from_secs(31_536_000));
§Example: converting a span without a relative datetime
If for some reason it doesn’t make sense to include a
relative datetime, you can use this routine to convert a
Span
with units up to weeks to a SignedDuration
via the
SpanRelativeTo::days_are_24_hours
marker:
use jiff::{civil::date, SignedDuration, SpanRelativeTo, ToSpan};
let span = 1.week().days(1);
let duration = span.to_duration(SpanRelativeTo::days_are_24_hours())?;
assert_eq!(duration, SignedDuration::from_hours(192));
impl Span
Crate internal APIs that operate on ranged integer types.
impl Span
Crate internal helper routines.
Trait Implementations§
Source§impl<'a> Add<Span> for &'a Zoned
impl<'a> Add<Span> for &'a Zoned
Adds a span of time to a zoned datetime.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Zoned::checked_add
.
Source§impl Add<Span> for Date
impl Add<Span> for Date
Adds a span of time to a date.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Date::checked_add
.
Source§impl Add<Span> for DateTime
impl Add<Span> for DateTime
Adds a span of time to a datetime.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use DateTime::checked_add
.
Source§impl Add<Span> for Offset
impl Add<Span> for Offset
Adds a span of time to an offset. This panics on overflow.
For checked arithmetic, see Offset::checked_add
.
Source§impl Add<Span> for Time
impl Add<Span> for Time
Adds a span of time. This uses wrapping arithmetic.
For checked arithmetic, see Time::checked_add
.
Source§impl Add<Span> for Timestamp
impl Add<Span> for Timestamp
Adds a span of time to a timestamp.
This uses checked arithmetic and panics when it fails. To handle arithmetic
without panics, use Timestamp::checked_add
. Note that the failure
condition includes overflow and using a Span
with non-zero units greater
than hours.
Source§impl AddAssign<Span> for Date
impl AddAssign<Span> for Date
Adds a span of time to a date in place.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Date::checked_add
.
Source§fn add_assign(&mut self, rhs: Span)
fn add_assign(&mut self, rhs: Span)
+=
operation. Read moreSource§impl AddAssign<Span> for DateTime
impl AddAssign<Span> for DateTime
Adds a span of time to a datetime in place.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use DateTime::checked_add
.
Source§fn add_assign(&mut self, rhs: Span)
fn add_assign(&mut self, rhs: Span)
+=
operation. Read moreSource§impl AddAssign<Span> for Offset
impl AddAssign<Span> for Offset
Adds a span of time to an offset in place. This panics on overflow.
For checked arithmetic, see Offset::checked_add
.
Source§fn add_assign(&mut self, rhs: Span)
fn add_assign(&mut self, rhs: Span)
+=
operation. Read moreSource§impl AddAssign<Span> for Time
impl AddAssign<Span> for Time
Adds a span of time in place. This uses wrapping arithmetic.
For checked arithmetic, see Time::checked_add
.
Source§fn add_assign(&mut self, rhs: Span)
fn add_assign(&mut self, rhs: Span)
+=
operation. Read moreSource§impl AddAssign<Span> for Timestamp
impl AddAssign<Span> for Timestamp
Adds a span of time to a timestamp in place.
This uses checked arithmetic and panics when it fails. To handle arithmetic
without panics, use Timestamp::checked_add
. Note that the failure
condition includes overflow and using a Span
with non-zero units greater
than hours.
Source§fn add_assign(&mut self, rhs: Span)
fn add_assign(&mut self, rhs: Span)
+=
operation. Read moreSource§impl AddAssign<Span> for Zoned
impl AddAssign<Span> for Zoned
Adds a span of time to a zoned datetime in place.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Zoned::checked_add
.
Source§fn add_assign(&mut self, rhs: Span)
fn add_assign(&mut self, rhs: Span)
+=
operation. Read moreSource§impl<'de> Deserialize<'de> for Span
impl<'de> Deserialize<'de> for Span
Source§fn deserialize<D>(
deserializer: D,
) -> Result<Span, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<Span, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl<'a> From<&'a Span> for DateArithmetic
impl<'a> From<&'a Span> for DateArithmetic
Source§fn from(span: &'a Span) -> DateArithmetic
fn from(span: &'a Span) -> DateArithmetic
Source§impl<'a> From<&'a Span> for DateTimeArithmetic
impl<'a> From<&'a Span> for DateTimeArithmetic
Source§fn from(span: &'a Span) -> DateTimeArithmetic
fn from(span: &'a Span) -> DateTimeArithmetic
Source§impl<'a> From<&'a Span> for OffsetArithmetic
impl<'a> From<&'a Span> for OffsetArithmetic
Source§fn from(span: &'a Span) -> OffsetArithmetic
fn from(span: &'a Span) -> OffsetArithmetic
Source§impl<'a> From<&'a Span> for SpanArithmetic<'static>
impl<'a> From<&'a Span> for SpanArithmetic<'static>
Source§fn from(span: &'a Span) -> SpanArithmetic<'static>
fn from(span: &'a Span) -> SpanArithmetic<'static>
Source§impl<'a> From<&'a Span> for SpanCompare<'static>
impl<'a> From<&'a Span> for SpanCompare<'static>
Source§fn from(span: &'a Span) -> SpanCompare<'static>
fn from(span: &'a Span) -> SpanCompare<'static>
Source§impl<'a> From<&'a Span> for TimeArithmetic
impl<'a> From<&'a Span> for TimeArithmetic
Source§fn from(span: &'a Span) -> TimeArithmetic
fn from(span: &'a Span) -> TimeArithmetic
Source§impl<'a> From<&'a Span> for TimestampArithmetic
impl<'a> From<&'a Span> for TimestampArithmetic
Source§fn from(span: &'a Span) -> TimestampArithmetic
fn from(span: &'a Span) -> TimestampArithmetic
Source§impl<'a> From<&'a Span> for ZonedArithmetic
impl<'a> From<&'a Span> for ZonedArithmetic
Source§fn from(span: &'a Span) -> ZonedArithmetic
fn from(span: &'a Span) -> ZonedArithmetic
Source§impl From<Span> for DateArithmetic
impl From<Span> for DateArithmetic
Source§fn from(span: Span) -> DateArithmetic
fn from(span: Span) -> DateArithmetic
Source§impl From<Span> for DateTimeArithmetic
impl From<Span> for DateTimeArithmetic
Source§fn from(span: Span) -> DateTimeArithmetic
fn from(span: Span) -> DateTimeArithmetic
Source§impl From<Span> for OffsetArithmetic
impl From<Span> for OffsetArithmetic
Source§fn from(span: Span) -> OffsetArithmetic
fn from(span: Span) -> OffsetArithmetic
Source§impl From<Span> for SpanArithmetic<'static>
impl From<Span> for SpanArithmetic<'static>
Source§fn from(span: Span) -> SpanArithmetic<'static>
fn from(span: Span) -> SpanArithmetic<'static>
Source§impl From<Span> for SpanCompare<'static>
impl From<Span> for SpanCompare<'static>
Source§fn from(span: Span) -> SpanCompare<'static>
fn from(span: Span) -> SpanCompare<'static>
Source§impl From<Span> for SpanFieldwise
impl From<Span> for SpanFieldwise
Source§fn from(span: Span) -> SpanFieldwise
fn from(span: Span) -> SpanFieldwise
Source§impl From<Span> for TimeArithmetic
impl From<Span> for TimeArithmetic
Source§fn from(span: Span) -> TimeArithmetic
fn from(span: Span) -> TimeArithmetic
Source§impl From<Span> for TimestampArithmetic
impl From<Span> for TimestampArithmetic
Source§fn from(span: Span) -> TimestampArithmetic
fn from(span: Span) -> TimestampArithmetic
Source§impl From<Span> for ZonedArithmetic
impl From<Span> for ZonedArithmetic
Source§fn from(span: Span) -> ZonedArithmetic
fn from(span: Span) -> ZonedArithmetic
Source§impl From<SpanFieldwise> for Span
impl From<SpanFieldwise> for Span
Source§fn from(span: SpanFieldwise) -> Span
fn from(span: SpanFieldwise) -> Span
Source§impl Mul<Span> for i64
impl Mul<Span> for i64
This multiplies each unit in a span by an integer.
This panics on overflow. For checked arithmetic, use Span::checked_mul
.
Source§impl Mul<i64> for Span
impl Mul<i64> for Span
This multiplies each unit in a span by an integer.
This panics on overflow. For checked arithmetic, use Span::checked_mul
.
Source§impl PartialEq<Span> for SpanFieldwise
impl PartialEq<Span> for SpanFieldwise
Source§impl<'a> PartialEq<SpanFieldwise> for &'a Span
impl<'a> PartialEq<SpanFieldwise> for &'a Span
Source§impl PartialEq<SpanFieldwise> for Span
impl PartialEq<SpanFieldwise> for Span
Source§impl Serialize for Span
impl Serialize for Span
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
Source§impl<'a> Sub<Span> for &'a Zoned
impl<'a> Sub<Span> for &'a Zoned
Subtracts a span of time from a zoned datetime.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Zoned::checked_sub
.
Source§impl Sub<Span> for Date
impl Sub<Span> for Date
Subtracts a span of time from a date.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Date::checked_sub
.
Source§impl Sub<Span> for DateTime
impl Sub<Span> for DateTime
Subtracts a span of time from a datetime.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use DateTime::checked_sub
.
Source§impl Sub<Span> for Offset
impl Sub<Span> for Offset
Subtracts a span of time from an offset. This panics on overflow.
For checked arithmetic, see Offset::checked_sub
.
Source§impl Sub<Span> for Time
impl Sub<Span> for Time
Subtracts a span of time. This uses wrapping arithmetic.
For checked arithmetic, see Time::checked_sub
.
Source§impl Sub<Span> for Timestamp
impl Sub<Span> for Timestamp
Subtracts a span of time from a timestamp.
This uses checked arithmetic and panics when it fails. To handle arithmetic
without panics, use Timestamp::checked_sub
. Note that the failure
condition includes overflow and using a Span
with non-zero units greater
than hours.
Source§impl SubAssign<Span> for Date
impl SubAssign<Span> for Date
Subtracts a span of time from a date in place.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Date::checked_sub
.
Source§fn sub_assign(&mut self, rhs: Span)
fn sub_assign(&mut self, rhs: Span)
-=
operation. Read moreSource§impl SubAssign<Span> for DateTime
impl SubAssign<Span> for DateTime
Subtracts a span of time from a datetime in place.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use DateTime::checked_sub
.
Source§fn sub_assign(&mut self, rhs: Span)
fn sub_assign(&mut self, rhs: Span)
-=
operation. Read moreSource§impl SubAssign<Span> for Offset
impl SubAssign<Span> for Offset
Subtracts a span of time from an offset in place. This panics on overflow.
For checked arithmetic, see Offset::checked_sub
.
Source§fn sub_assign(&mut self, rhs: Span)
fn sub_assign(&mut self, rhs: Span)
-=
operation. Read moreSource§impl SubAssign<Span> for Time
impl SubAssign<Span> for Time
Subtracts a span of time in place. This uses wrapping arithmetic.
For checked arithmetic, see Time::checked_sub
.
Source§fn sub_assign(&mut self, rhs: Span)
fn sub_assign(&mut self, rhs: Span)
-=
operation. Read moreSource§impl SubAssign<Span> for Timestamp
impl SubAssign<Span> for Timestamp
Subtracts a span of time from a timestamp in place.
This uses checked arithmetic and panics when it fails. To handle arithmetic
without panics, use Timestamp::checked_sub
. Note that the failure
condition includes overflow and using a Span
with non-zero units greater
than hours.
Source§fn sub_assign(&mut self, rhs: Span)
fn sub_assign(&mut self, rhs: Span)
-=
operation. Read moreSource§impl SubAssign<Span> for Zoned
impl SubAssign<Span> for Zoned
Subtracts a span of time from a zoned datetime in place.
This uses checked arithmetic and panics on overflow. To handle overflow
without panics, use Zoned::checked_sub
.
Source§fn sub_assign(&mut self, rhs: Span)
fn sub_assign(&mut self, rhs: Span)
-=
operation. Read moreSource§impl TryFrom<Duration> for Span
impl TryFrom<Duration> for Span
Converts a std::time::Duration
to a Span
.
The span returned from this conversion will only ever have non-zero units of seconds or smaller.
§Errors
This only fails when the given Duration
overflows the maximum number of
seconds representable by a Span
.
§Example
This shows a basic conversion:
use std::time::Duration;
use jiff::{Span, ToSpan};
let duration = Duration::new(86_400, 123_456_789);
let span = Span::try_from(duration)?;
// A duration-to-span conversion always results in a span with
// non-zero units no bigger than seconds.
assert_eq!(
span.fieldwise(),
86_400.seconds().milliseconds(123).microseconds(456).nanoseconds(789),
);
§Example: rounding
This example shows how to convert a Duration
to a Span
, and then round
it up to bigger units given a relative date:
use std::time::Duration;
use jiff::{civil::date, Span, SpanRound, ToSpan, Unit};
let duration = Duration::new(450 * 86_401, 0);
let span = Span::try_from(duration)?;
// We get back a simple span of just seconds:
assert_eq!(span.fieldwise(), Span::new().seconds(450 * 86_401));
// But we can balance it up to bigger units:
let options = SpanRound::new()
.largest(Unit::Year)
.relative(date(2024, 1, 1));
assert_eq!(
span.round(options)?,
1.year().months(2).days(25).minutes(7).seconds(30).fieldwise(),
);
Source§impl TryFrom<SignedDuration> for Span
impl TryFrom<SignedDuration> for Span
Converts a SignedDuration
to a Span
.
The span returned from this conversion will only ever have non-zero units of seconds or smaller.
§Errors
This only fails when the given SignedDuration
overflows the maximum
number of seconds representable by a Span
.
§Example
This shows a basic conversion:
use jiff::{SignedDuration, Span, ToSpan};
let duration = SignedDuration::new(86_400, 123_456_789);
let span = Span::try_from(duration)?;
// A duration-to-span conversion always results in a span with
// non-zero units no bigger than seconds.
assert_eq!(
span.fieldwise(),
86_400.seconds().milliseconds(123).microseconds(456).nanoseconds(789),
);
§Example: rounding
This example shows how to convert a SignedDuration
to a Span
, and then
round it up to bigger units given a relative date:
use jiff::{civil::date, SignedDuration, Span, SpanRound, ToSpan, Unit};
let duration = SignedDuration::new(450 * 86_401, 0);
let span = Span::try_from(duration)?;
// We get back a simple span of just seconds:
assert_eq!(span.fieldwise(), Span::new().seconds(450 * 86_401));
// But we can balance it up to bigger units:
let options = SpanRound::new()
.largest(Unit::Year)
.relative(date(2024, 1, 1));
assert_eq!(
span.round(options)?,
1.year().months(2).days(25).minutes(7).seconds(30).fieldwise(),
);
Source§impl TryFrom<Span> for Duration
impl TryFrom<Span> for Duration
Converts a Span
to a std::time::Duration
.
Note that this assumes that days are always 24 hours long.
§Errors
This can fail for only two reasons:
- The span is negative. This is an error because a
std::time::Duration
is unsigned.) - The span has any non-zero units greater than hours. This is an error because it’s impossible to determine the length of, e.g., a month without a reference date.
This can never result in overflow because a Duration
can represent a
bigger span of time than Span
when limited to units of hours or lower.
If you need to convert a Span
to a Duration
that has non-zero
units bigger than hours, then please use Span::to_duration
with a
corresponding relative date.
§Example: maximal span
This example shows the maximum possible span using units of hours or
smaller, and the corresponding Duration
value:
use std::time::Duration;
use jiff::Span;
let sp = Span::new()
.hours(175_307_616)
.minutes(10_518_456_960i64)
.seconds(631_107_417_600i64)
.milliseconds(631_107_417_600_000i64)
.microseconds(631_107_417_600_000_000i64)
.nanoseconds(9_223_372_036_854_775_807i64);
let duration = Duration::try_from(sp)?;
assert_eq!(duration, Duration::new(3_164_760_460_036, 854_775_807));
§Example: converting a negative span
Since a Span
is signed and a Duration
is unsigned, converting
a negative Span
to Duration
will always fail. One can use
Span::signum
to get the sign of the span and Span::abs
to make the
span positive before converting it to a Duration
:
use std::time::Duration;
use jiff::{Span, ToSpan};
let span = -86_400.seconds().nanoseconds(1);
let (sign, duration) = (span.signum(), Duration::try_from(span.abs())?);
assert_eq!((sign, duration), (-1, Duration::new(86_400, 1)));
Source§impl TryFrom<Span> for SignedDuration
impl TryFrom<Span> for SignedDuration
Converts a Span
to a SignedDuration
.
Note that this assumes that days are always 24 hours long.
§Errors
This can fail for only when the span has any non-zero units greater than hours. This is an error because it’s impossible to determine the length of, e.g., a month without a reference date.
This can never result in overflow because a SignedDuration
can represent
a bigger span of time than Span
when limited to units of hours or lower.
If you need to convert a Span
to a SignedDuration
that has non-zero
units bigger than hours, then please use Span::to_duration
with a
corresponding relative date.
§Example: maximal span
This example shows the maximum possible span using units of hours or
smaller, and the corresponding SignedDuration
value:
use jiff::{SignedDuration, Span};
let sp = Span::new()
.hours(175_307_616)
.minutes(10_518_456_960i64)
.seconds(631_107_417_600i64)
.milliseconds(631_107_417_600_000i64)
.microseconds(631_107_417_600_000_000i64)
.nanoseconds(9_223_372_036_854_775_807i64);
let duration = SignedDuration::try_from(sp)?;
assert_eq!(duration, SignedDuration::new(3_164_760_460_036, 854_775_807));
impl Copy for Span
Auto Trait Implementations§
impl Freeze for Span
impl RefUnwindSafe for Span
impl Send for Span
impl Sync for Span
impl Unpin for Span
impl UnwindSafe for Span
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more