Struct Timestamp

struct Timestamp { ... }

An instant in time represented as the number of nanoseconds since the Unix epoch.

A timestamp is always in the Unix timescale with a UTC offset of zero.

To obtain civil or "local" datetime units like year, month, day or hour, a timestamp needs to be combined with a TimeZone to create a Zoned. That can be done with Timestamp::in_tz or Timestamp::to_zoned.

The integer count of nanoseconds since the Unix epoch is signed, where the Unix epoch is 1970-01-01 00:00:00Z. A positive timestamp indicates a point in time after the Unix epoch. A negative timestamp indicates a point in time before the Unix epoch.

Parsing and printing

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

use jiff::Timestamp;

let ts: Timestamp = "2024-06-19 15:22:45-04".parse()?;
assert_eq!(ts.to_string(), "2024-06-19T19:22:45Z");

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

A Timestamp can also be parsed from something that contains a timestamp, but with perhaps other data (such as a time zone):

use jiff::Timestamp;

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

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

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

Default value

For convenience, this type implements the Default trait. Its default value corresponds to 1970-01-01T00:00:00.000000000. That is, it is the Unix epoch. One can also access this value via the Timestamp::UNIX_EPOCH 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 timestamp with a second component of 60, then it is automatically constrained to 59:

use jiff::Timestamp;

let ts: Timestamp = "2016-12-31 23:59:60Z".parse()?;
assert_eq!(ts.to_string(), "2016-12-31T23:59:59Z");

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

Comparisons

The Timestamp type provides both Eq and Ord trait implementations to facilitate easy comparisons. When a timestamp ts1 occurs before a timestamp ts2, then dt1 < dt2. For example:

use jiff::Timestamp;

let ts1 = Timestamp::from_second(123_456_789)?;
let ts2 = Timestamp::from_second(123_456_790)?;
assert!(ts1 < ts2);

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

Arithmetic

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

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

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

use jiff::{Timestamp, ToSpan};

let ts1: Timestamp = "2024-02-25T15:45Z".parse()?;
let ts2 = ts1 - 24.hours();
assert_eq!(ts2.to_string(), "2024-02-24T15:45:00Z");

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

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

use jiff::{Timestamp, ToSpan};

let ts1: Timestamp = "2024-05-03 23:30:00.123Z".parse()?;
let ts2: Timestamp = "2024-02-25 07Z".parse()?;
// The default is to return spans with units no bigger than seconds.
assert_eq!(ts1 - ts2, 5934600.seconds().milliseconds(123).fieldwise());

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

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

use jiff::{Timestamp, ToSpan, Unit};

let ts1: Timestamp = "2024-05-03 23:30:00.123Z".parse()?;
let ts2: Timestamp = "2024-02-25 07Z".parse()?;
assert_eq!(
    // If you want to deal in units bigger than hours, then you'll have to
    // convert your timestamp to a [`Zoned`](Zoned) first.
    ts1.since((Unit::Hour, ts2))?,
    1648.hours().minutes(30).milliseconds(123).fieldwise(),
);

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

You can also round the span returned:

use jiff::{RoundMode, Timestamp, TimestampDifference, ToSpan, Unit};

let ts1: Timestamp = "2024-05-03 23:30:59.123Z".parse()?;
let ts2: Timestamp = "2024-05-02 07Z".parse()?;
assert_eq!(
    ts1.since(
        TimestampDifference::new(ts2)
            .smallest(Unit::Minute)
            .largest(Unit::Hour),
    )?,
    40.hours().minutes(30).fieldwise(),
);
// `TimestampDifference` uses truncation as a rounding mode by default,
// but you can set the rounding mode to break ties away from zero:
assert_eq!(
    ts1.since(
        TimestampDifference::new(ts2)
            .smallest(Unit::Minute)
            .largest(Unit::Hour)
            .mode(RoundMode::HalfExpand),
    )?,
    // Rounds up to 31 minutes.
    40.hours().minutes(31).fieldwise(),
);

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

Rounding timestamps

A Timestamp can be rounded based on a TimestampRound configuration of smallest units, rounding increment and rounding mode. Here's an example showing how to round to the nearest third hour:

use jiff::{Timestamp, TimestampRound, Unit};

let ts: Timestamp = "2024-06-19 16:27:29.999999999Z".parse()?;
assert_eq!(
    ts.round(TimestampRound::new().smallest(Unit::Hour).increment(3))?,
    "2024-06-19 15Z".parse::<Timestamp>()?,
);
// Or alternatively, make use of the `From<(Unit, i64)> for TimestampRound`
// trait implementation:
assert_eq!(
    ts.round((Unit::Hour, 3))?.to_string(),
    "2024-06-19T15:00:00Z",
);

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

See Timestamp::round for more details.

An instant in time

Unlike a civil::DateTime, a Timestamp always corresponds, unambiguously, to a precise instant in time (to nanosecond precision). This means that attaching a time zone to a timestamp is always unambiguous because there's never any question as to which instant it refers to. This is true even for gaps in civil time.

For example, in America/New_York, clocks were moved ahead one hour at clock time 2024-03-10 02:00:00. That is, the 2 o'clock hour never appeared on clocks in the America/New_York region. Since parsing a timestamp always requires an offset, the time it refers to is unambiguous. We can see this by writing a clock time, 02:30, that never existed but with two different offsets:

use jiff::Timestamp;

// All we're doing here is attaching an offset to a civil datetime.
// There is no time zone information here, and thus there is no
// accounting for ambiguity due to daylight saving time transitions.
let before_hour_jump: Timestamp = "2024-03-10 02:30-04".parse()?;
let after_hour_jump: Timestamp = "2024-03-10 02:30-05".parse()?;
// This shows the instant in time in UTC.
assert_eq!(before_hour_jump.to_string(), "2024-03-10T06:30:00Z");
assert_eq!(after_hour_jump.to_string(), "2024-03-10T07:30:00Z");

// Now let's attach each instant to an `America/New_York` time zone.
let zdt_before = before_hour_jump.in_tz("America/New_York")?;
let zdt_after = after_hour_jump.in_tz("America/New_York")?;
// And now we can see that even though the original instant refers to
// the 2 o'clock hour, since that hour never existed on the clocks in
// `America/New_York`, an instant with a time zone correctly adjusts.
assert_eq!(
    zdt_before.to_string(),
    "2024-03-10T01:30:00-05:00[America/New_York]",
);
assert_eq!(
    zdt_after.to_string(),
    "2024-03-10T03:30:00-04:00[America/New_York]",
);

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

In the example above, there is never a step that is incorrect or has an alternative answer. Every step is unambiguous because we never involve any civil datetimes.

But note that if the datetime string you're parsing from lacks an offset, then it could be ambiguous even if a time zone is specified. In this case, parsing will always fail:

use jiff::Timestamp;

let result = "2024-06-30 08:30[America/New_York]".parse::<Timestamp>();
assert_eq!(
    result.unwrap_err().to_string(),
    "failed to find offset component in \
     \"2024-06-30 08:30[America/New_York]\", \
     which is required for parsing a timestamp",
);

Converting a civil datetime to a timestamp

Sometimes you want to convert the "time on the clock" to a precise instant in time. One way to do this was demonstrated in the previous section, but it only works if you know your current time zone offset:

use jiff::Timestamp;

let ts: Timestamp = "2024-06-30 08:36-04".parse()?;
assert_eq!(ts.to_string(), "2024-06-30T12:36:00Z");

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

The above happened to be the precise instant in time I wrote the example. Since I happened to know the offset, this worked okay. But what if I didn't? We could instead construct a civil datetime and attach a time zone to it. This will create a Zoned value, from which we can access the timestamp:

use jiff::civil::date;

let clock = date(2024, 6, 30).at(8, 36, 0, 0).in_tz("America/New_York")?;
assert_eq!(clock.timestamp().to_string(), "2024-06-30T12:36:00Z");

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

Implementations

impl Timestamp

fn now() -> Timestamp

Returns the current system time as a timestamp.

Panics

This panics if the system clock is set to a time value outside of the range -009999-01-01T00:00:00Z..=9999-12-31T11:59:59.999999999Z. The justification here is that it is reasonable to expect the system clock to be set to a somewhat sane, if imprecise, value.

If you want to get the current Unix time fallibly, use Timestamp::try_from with a std::time::SystemTime as input.

This may also panic when SystemTime::now() itself panics. The most common context in which this happens is on the wasm32-unknown-unknown target. If you're using that target in the context of the web (for example, via wasm-pack), and you're an application, then you should enable Jiff's js feature. This will automatically instruct Jiff in this very specific circumstance to execute JavaScript code to determine the current time from the web browser.

Example

use jiff::Timestamp;

assert!(Timestamp::now() > Timestamp::UNIX_EPOCH);
fn new(second: i64, nanosecond: i32) -> Result<Timestamp, Error>

Creates a new instant in time represented as a timestamp.

While a timestamp is logically a count of nanoseconds since the Unix epoch, this constructor provides a convenience way of constructing the timestamp from two components: seconds and fractional seconds expressed as nanoseconds.

The signs of second and nanosecond need not be the same.

Errors

This returns an error if the given components would correspond to an instant outside the supported range. Also, nanosecond is limited to the range -999,999,999..=999,999,999.

Example

This example shows the instant in time 123,456,789 seconds after the Unix epoch:

use jiff::Timestamp;

assert_eq!(
    Timestamp::new(123_456_789, 0)?.to_string(),
    "1973-11-29T21:33:09Z",
);

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

Example: normalized sign

This example shows how second and nanosecond are resolved when their signs differ.

use jiff::Timestamp;

let ts = Timestamp::new(2, -999_999_999)?;
assert_eq!(ts.as_second(), 1);
assert_eq!(ts.subsec_nanosecond(), 1);

let ts = Timestamp::new(-2, 999_999_999)?;
assert_eq!(ts.as_second(), -1);
assert_eq!(ts.subsec_nanosecond(), -1);

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

Example: limits

The minimum timestamp has nanoseconds set to zero, while the maximum timestamp has nanoseconds set to 999,999,999:

use jiff::Timestamp;

assert_eq!(Timestamp::MIN.subsec_nanosecond(), 0);
assert_eq!(Timestamp::MAX.subsec_nanosecond(), 999_999_999);

As a consequence, nanoseconds cannot be negative when a timestamp has minimal seconds:

use jiff::Timestamp;

assert!(Timestamp::new(Timestamp::MIN.as_second(), -1).is_err());
// But they can be positive!
let one_ns_more = Timestamp::new(Timestamp::MIN.as_second(), 1)?;
assert_eq!(
    one_ns_more.to_string(),
    "-009999-01-02T01:59:59.000000001Z",
);
// Or, when combined with a minimal offset:
assert_eq!(
    jiff::tz::Offset::MIN.to_datetime(one_ns_more).to_string(),
    "-009999-01-01T00:00:00.000000001",
);

# Ok::<(), Box<dyn std::error::Error>>(())
const fn constant(second: i64, nanosecond: i32) -> Timestamp

Creates a new Timestamp value in a const context.

Panics

This routine panics when Timestamp::new would return an error. That is, when the given components would correspond to an instant outside the supported range. Also, nanosecond is limited to the range -999,999,999..=999,999,999.

Example

This example shows the instant in time 123,456,789 seconds after the Unix epoch:

use jiff::Timestamp;

assert_eq!(
    Timestamp::constant(123_456_789, 0).to_string(),
    "1973-11-29T21:33:09Z",
);
fn from_second(second: i64) -> Result<Timestamp, Error>

Creates a new instant in time from the number of seconds elapsed since the Unix epoch.

When second is negative, it corresponds to an instant in time before the Unix epoch. A smaller number corresponds to an instant in time further into the past.

Errors

This returns an error if the given second corresponds to a timestamp outside of the Timestamp::MIN and Timestamp::MAX boundaries.

Example

This example shows the instants in time 1 second immediately after and before the Unix epoch:

use jiff::Timestamp;

assert_eq!(
    Timestamp::from_second(1)?.to_string(),
    "1970-01-01T00:00:01Z",
);
assert_eq!(
    Timestamp::from_second(-1)?.to_string(),
    "1969-12-31T23:59:59Z",
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn from_millisecond(millisecond: i64) -> Result<Timestamp, Error>

Creates a new instant in time from the number of milliseconds elapsed since the Unix epoch.

When millisecond is negative, it corresponds to an instant in time before the Unix epoch. A smaller number corresponds to an instant in time further into the past.

Errors

This returns an error if the given millisecond corresponds to a timestamp outside of the Timestamp::MIN and Timestamp::MAX boundaries.

Example

This example shows the instants in time 1 millisecond immediately after and before the Unix epoch:

use jiff::Timestamp;

assert_eq!(
    Timestamp::from_millisecond(1)?.to_string(),
    "1970-01-01T00:00:00.001Z",
);
assert_eq!(
    Timestamp::from_millisecond(-1)?.to_string(),
    "1969-12-31T23:59:59.999Z",
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn from_microsecond(microsecond: i64) -> Result<Timestamp, Error>

Creates a new instant in time from the number of microseconds elapsed since the Unix epoch.

When microsecond is negative, it corresponds to an instant in time before the Unix epoch. A smaller number corresponds to an instant in time further into the past.

Errors

This returns an error if the given microsecond corresponds to a timestamp outside of the Timestamp::MIN and Timestamp::MAX boundaries.

Example

This example shows the instants in time 1 microsecond immediately after and before the Unix epoch:

use jiff::Timestamp;

assert_eq!(
    Timestamp::from_microsecond(1)?.to_string(),
    "1970-01-01T00:00:00.000001Z",
);
assert_eq!(
    Timestamp::from_microsecond(-1)?.to_string(),
    "1969-12-31T23:59:59.999999Z",
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn from_nanosecond(nanosecond: i128) -> Result<Timestamp, Error>

Creates a new instant in time from the number of nanoseconds elapsed since the Unix epoch.

When nanosecond is negative, it corresponds to an instant in time before the Unix epoch. A smaller number corresponds to an instant in time further into the past.

Errors

This returns an error if the given nanosecond corresponds to a timestamp outside of the Timestamp::MIN and Timestamp::MAX boundaries.

Example

This example shows the instants in time 1 nanosecond immediately after and before the Unix epoch:

use jiff::Timestamp;

assert_eq!(
    Timestamp::from_nanosecond(1)?.to_string(),
    "1970-01-01T00:00:00.000000001Z",
);
assert_eq!(
    Timestamp::from_nanosecond(-1)?.to_string(),
    "1969-12-31T23:59:59.999999999Z",
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn from_duration(duration: SignedDuration) -> Result<Timestamp, Error>

Creates a new timestamp from a Duration with the given sign since the Unix epoch.

Positive durations result in a timestamp after the Unix epoch. Negative durations result in a timestamp before the Unix epoch.

Errors

This returns an error if the given duration corresponds to a timestamp outside of the Timestamp::MIN and Timestamp::MAX boundaries.

Example

How one might construct a Timestamp from a SystemTime:

use std::time::SystemTime;
use jiff::{SignedDuration, Timestamp};

let unix_epoch = SystemTime::UNIX_EPOCH;
let now = SystemTime::now();
let duration = SignedDuration::system_until(unix_epoch, now)?;
let ts = Timestamp::from_duration(duration)?;
assert!(ts > Timestamp::UNIX_EPOCH);

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

Of course, one should just use Timestamp::try_from for this instead. Indeed, the above example is copied almost exactly from the TryFrom implementation.

Example: out of bounds

This example shows how some of the boundary conditions are dealt with.

use jiff::{SignedDuration, Timestamp};

// OK, we get the minimum timestamp supported by Jiff:
let duration = SignedDuration::new(-377705023201, 0);
let ts = Timestamp::from_duration(duration)?;
assert_eq!(ts, Timestamp::MIN);

// We use the minimum number of seconds, but even subtracting
// one more nanosecond after it will result in an error.
let duration = SignedDuration::new(-377705023201, -1);
assert_eq!(
    Timestamp::from_duration(duration).unwrap_err().to_string(),
    "parameter 'seconds and nanoseconds' with value -1 is not \
     in the required range of 0..=1000000000",
);

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

Returns this timestamp as a number of seconds since the Unix epoch.

This only returns the number of whole seconds. That is, if there are any fractional seconds in this timestamp, then they are truncated.

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, 123_456_789)?;
assert_eq!(ts.as_second(), 5);
let ts = Timestamp::new(5, 999_999_999)?;
assert_eq!(ts.as_second(), 5);

let ts = Timestamp::new(-5, -123_456_789)?;
assert_eq!(ts.as_second(), -5);
let ts = Timestamp::new(-5, -999_999_999)?;
assert_eq!(ts.as_second(), -5);

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

Returns this timestamp as a number of milliseconds since the Unix epoch.

This only returns the number of whole milliseconds. That is, if there are any fractional milliseconds in this timestamp, then they are truncated.

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, 123_456_789)?;
assert_eq!(ts.as_millisecond(), 5_123);
let ts = Timestamp::new(5, 999_999_999)?;
assert_eq!(ts.as_millisecond(), 5_999);

let ts = Timestamp::new(-5, -123_456_789)?;
assert_eq!(ts.as_millisecond(), -5_123);
let ts = Timestamp::new(-5, -999_999_999)?;
assert_eq!(ts.as_millisecond(), -5_999);

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

Returns this timestamp as a number of microseconds since the Unix epoch.

This only returns the number of whole microseconds. That is, if there are any fractional microseconds in this timestamp, then they are truncated.

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, 123_456_789)?;
assert_eq!(ts.as_microsecond(), 5_123_456);
let ts = Timestamp::new(5, 999_999_999)?;
assert_eq!(ts.as_microsecond(), 5_999_999);

let ts = Timestamp::new(-5, -123_456_789)?;
assert_eq!(ts.as_microsecond(), -5_123_456);
let ts = Timestamp::new(-5, -999_999_999)?;
assert_eq!(ts.as_microsecond(), -5_999_999);

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

Returns this timestamp as a number of nanoseconds since the Unix epoch.

Since a Timestamp has a nanosecond precision, the nanoseconds returned here represent this timestamp losslessly. That is, the nanoseconds returned can be used with Timestamp::from_nanosecond to create an identical timestamp with no loss of precision.

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, 123_456_789)?;
assert_eq!(ts.as_nanosecond(), 5_123_456_789);
let ts = Timestamp::new(5, 999_999_999)?;
assert_eq!(ts.as_nanosecond(), 5_999_999_999);

let ts = Timestamp::new(-5, -123_456_789)?;
assert_eq!(ts.as_nanosecond(), -5_123_456_789);
let ts = Timestamp::new(-5, -999_999_999)?;
assert_eq!(ts.as_nanosecond(), -5_999_999_999);

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

Returns the fractional second component of this timestamp in units of milliseconds.

It is guaranteed that this will never return a value that is greater than 1 second (or less than -1 second).

This only returns the number of whole milliseconds. That is, if there are any fractional milliseconds in this timestamp, then they are truncated.

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, 123_456_789)?;
assert_eq!(ts.subsec_millisecond(), 123);
let ts = Timestamp::new(5, 999_999_999)?;
assert_eq!(ts.subsec_millisecond(), 999);

let ts = Timestamp::new(-5, -123_456_789)?;
assert_eq!(ts.subsec_millisecond(), -123);
let ts = Timestamp::new(-5, -999_999_999)?;
assert_eq!(ts.subsec_millisecond(), -999);

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

Returns the fractional second component of this timestamp in units of microseconds.

It is guaranteed that this will never return a value that is greater than 1 second (or less than -1 second).

This only returns the number of whole microseconds. That is, if there are any fractional microseconds in this timestamp, then they are truncated.

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, 123_456_789)?;
assert_eq!(ts.subsec_microsecond(), 123_456);
let ts = Timestamp::new(5, 999_999_999)?;
assert_eq!(ts.subsec_microsecond(), 999_999);

let ts = Timestamp::new(-5, -123_456_789)?;
assert_eq!(ts.subsec_microsecond(), -123_456);
let ts = Timestamp::new(-5, -999_999_999)?;
assert_eq!(ts.subsec_microsecond(), -999_999);

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

Returns the fractional second component of this timestamp in units of nanoseconds.

It is guaranteed that this will never return a value that is greater than 1 second (or less than -1 second).

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, 123_456_789)?;
assert_eq!(ts.subsec_nanosecond(), 123_456_789);
let ts = Timestamp::new(5, 999_999_999)?;
assert_eq!(ts.subsec_nanosecond(), 999_999_999);

let ts = Timestamp::new(-5, -123_456_789)?;
assert_eq!(ts.subsec_nanosecond(), -123_456_789);
let ts = Timestamp::new(-5, -999_999_999)?;
assert_eq!(ts.subsec_nanosecond(), -999_999_999);

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

Returns this timestamp as a SignedDuration since the Unix epoch.

Example

use jiff::{SignedDuration, Timestamp};

assert_eq!(
    Timestamp::UNIX_EPOCH.as_duration(),
    SignedDuration::ZERO,
);
assert_eq!(
    Timestamp::new(5, 123_456_789)?.as_duration(),
    SignedDuration::new(5, 123_456_789),
);
assert_eq!(
    Timestamp::new(-5, -123_456_789)?.as_duration(),
    SignedDuration::new(-5, -123_456_789),
);

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

Returns the sign of this timestamp.

This can return one of three possible values:

  • 0 when this timestamp is precisely equivalent to Timestamp::UNIX_EPOCH.
  • 1 when this timestamp occurs after the Unix epoch.
  • -1 when this timestamp occurs before the Unix epoch.

The sign returned is guaranteed to match the sign of all "getter" methods on Timestamp. For example, Timestamp::as_second and Timestamp::subsec_nanosecond. This is true even if the signs of the second and nanosecond components were mixed when given to the Timestamp::new constructor.

Example

use jiff::Timestamp;

let ts = Timestamp::new(5, -999_999_999)?;
assert_eq!(ts.signum(), 1);
// The mixed signs were normalized away!
assert_eq!(ts.as_second(), 4);
assert_eq!(ts.subsec_nanosecond(), 1);

// The same applies for negative timestamps.
let ts = Timestamp::new(-5, 999_999_999)?;
assert_eq!(ts.signum(), -1);
assert_eq!(ts.as_second(), -4);
assert_eq!(ts.subsec_nanosecond(), -1);

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

Returns true if and only if this timestamp corresponds to the instant in time known as the Unix epoch.

Example

use jiff::Timestamp;

assert!(Timestamp::UNIX_EPOCH.is_zero());
fn in_tz(self: Self, time_zone_name: &str) -> Result<Zoned, Error>

Creates a Zoned value by attaching a time zone for the given name to this instant in time.

The name given is resolved to a TimeZone by using the default TimeZoneDatabase created by tz::db. Indeed, this is a convenience function for Timestamp::to_zoned where the time zone database lookup is done automatically.

Assuming the time zone name could be resolved to a TimeZone, this routine is otherwise infallible and never results in any ambiguity since both a Timestamp and a Zoned correspond to precise instant in time. This is unlike civil::DateTime::to_zoned, where a civil datetime might correspond to more than one instant in time (i.e., a fold, typically DST ending) or no instants in time (i.e., a gap, typically DST starting).

Errors

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

Example

This is a simple example of converting the instant that is 123,456,789 seconds after the Unix epoch to an instant that is aware of its time zone:

use jiff::Timestamp;

let ts = Timestamp::new(123_456_789, 0).unwrap();
let zdt = ts.in_tz("America/New_York")?;
assert_eq!(zdt.to_string(), "1973-11-29T16:33:09-05:00[America/New_York]");

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

This can be used to answer questions like, "What time was it at the Unix epoch in Tasmania?"

use jiff::Timestamp;

// Time zone database lookups are case insensitive!
let zdt = Timestamp::UNIX_EPOCH.in_tz("australia/tasmania")?;
assert_eq!(zdt.to_string(), "1970-01-01T11:00:00+11:00[Australia/Tasmania]");

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

Example: errors

This routine can return an error when the time zone is unrecognized:

use jiff::Timestamp;

assert!(Timestamp::UNIX_EPOCH.in_tz("does not exist").is_err());
fn to_zoned(self: Self, tz: TimeZone) -> Zoned

Creates a Zoned value by attaching the given time zone to this instant in time.

This is infallible and never results in any ambiguity since both a Timestamp and a Zoned correspond to precise instant in time. This is unlike civil::DateTime::to_zoned, where a civil datetime might correspond to more than one instant in time (i.e., a fold, typically DST ending) or no instants in time (i.e., a gap, typically DST starting).

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

Example

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

use jiff::{tz::{self, TimeZone}, Timestamp};

let ts = Timestamp::new(123_456_789, 0).unwrap();
let tz = TimeZone::fixed(tz::offset(-4));
let zdt = ts.to_zoned(tz);
// A time zone annotation is still included in the printable version
// of the Zoned value, but it is fixed to a particular offset.
assert_eq!(zdt.to_string(), "1973-11-29T17:33:09-04:00[-04:00]");

Example: POSIX time zone strings

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 jiff::{tz::TimeZone, Timestamp};

let ts = Timestamp::new(123_456_789, 0)?;
let tz = TimeZone::posix("NST3:30NDT,M3.2.0,M11.1.0")?;
let zdt = ts.to_zoned(tz);
// 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!(zdt.to_string(), "1973-11-29T18:03:09-03:30[-03:30]");

# Ok::<(), Box<dyn std::error::Error>>(())
fn checked_add<A: Into<TimestampArithmetic>>(self: Self, duration: A) -> Result<Timestamp, Error>

Add the given span of time to this timestamp.

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

Properties

Given a timestamp ts1 and a span s, and assuming ts2 = ts1 + s exists, it follows then that ts1 = ts2 - s for all values of ts1 and s that sum to a valid ts2.

In short, subtracting the given span from the sum returned by this function is guaranteed to result in precisely the original timestamp.

Errors

If the sum would overflow the minimum or maximum timestamp values, then an error is returned.

This also returns an error if the given duration is a Span with any non-zero units greater than hours. If you want to use bigger units, convert this timestamp to a Zoned and use Zoned::checked_add. This error occurs because a Timestamp has no time zone attached to it, and thus cannot unambiguously resolve the length of a single day.

Example

This shows how to add 5 hours to the Unix epoch:

use jiff::{Timestamp, ToSpan};

let ts = Timestamp::UNIX_EPOCH.checked_add(5.hours())?;
assert_eq!(ts.to_string(), "1970-01-01T05:00:00Z");

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

Example: negative spans are supported

This shows how to add -5 hours to the Unix epoch. This is the same as subtracting 5 hours from the Unix epoch.

use jiff::{Timestamp, ToSpan};

let ts = Timestamp::UNIX_EPOCH.checked_add(-5.hours())?;
assert_eq!(ts.to_string(), "1969-12-31T19:00:00Z");

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

Example: available via addition operator

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

use jiff::{Timestamp, ToSpan};

let ts1 = Timestamp::new(2_999_999_999, 0)?;
assert_eq!(ts1.to_string(), "2065-01-24T05:19:59Z");

let ts2 = ts1 + 1.hour().minutes(30).nanoseconds(123);
assert_eq!(ts2.to_string(), "2065-01-24T06:49:59.000000123Z");

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

Example: error on overflow

use jiff::{Timestamp, ToSpan};

let ts = Timestamp::MAX;
assert_eq!(ts.to_string(), "9999-12-30T22:00:00.999999999Z");
assert!(ts.checked_add(1.nanosecond()).is_err());

let ts = Timestamp::MIN;
assert_eq!(ts.to_string(), "-009999-01-02T01:59:59Z");
assert!(ts.checked_add(-1.nanosecond()).is_err());

Example: adding absolute durations

This shows how to add signed and unsigned absolute durations to a Timestamp.

use std::time::Duration;

use jiff::{SignedDuration, Timestamp};

let ts1 = Timestamp::new(2_999_999_999, 0)?;
assert_eq!(ts1.to_string(), "2065-01-24T05:19:59Z");

let dur = SignedDuration::new(60 * 60 + 30 * 60, 123);
assert_eq!(
    ts1.checked_add(dur)?.to_string(),
    "2065-01-24T06:49:59.000000123Z",
);

let dur = Duration::new(60 * 60 + 30 * 60, 123);
assert_eq!(
    ts1.checked_add(dur)?.to_string(),
    "2065-01-24T06:49:59.000000123Z",
);

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

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

Errors

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

Example

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

use jiff::{SignedDuration, Timestamp, ToSpan};

let ts1 = Timestamp::new(2_999_999_999, 0)?;
assert_eq!(ts1.to_string(), "2065-01-24T05:19:59Z");

let ts2 = ts1 - 1.hour().minutes(30).nanoseconds(123);
assert_eq!(ts2.to_string(), "2065-01-24T03:49:58.999999877Z");

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

Example: use with SignedDuration and std::time::Duration

use std::time::Duration;

use jiff::{SignedDuration, Timestamp};

let ts1 = Timestamp::new(2_999_999_999, 0)?;
assert_eq!(ts1.to_string(), "2065-01-24T05:19:59Z");

let dur = SignedDuration::new(60 * 60 + 30 * 60, 123);
assert_eq!(
    ts1.checked_sub(dur)?.to_string(),
    "2065-01-24T03:49:58.999999877Z",
);

let dur = Duration::new(60 * 60 + 30 * 60, 123);
assert_eq!(
    ts1.checked_sub(dur)?.to_string(),
    "2065-01-24T03:49:58.999999877Z",
);

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

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

Errors

This returns an error if the given Span contains any non-zero units greater than hours.

Example

This example shows that arithmetic saturates on overflow.

use jiff::{SignedDuration, Timestamp, ToSpan};

assert_eq!(
    Timestamp::MAX,
    Timestamp::MAX.saturating_add(1.nanosecond())?,
);
assert_eq!(
    Timestamp::MIN,
    Timestamp::MIN.saturating_add(-1.nanosecond())?,
);
assert_eq!(
    Timestamp::MAX,
    Timestamp::UNIX_EPOCH.saturating_add(SignedDuration::MAX)?,
);
assert_eq!(
    Timestamp::MIN,
    Timestamp::UNIX_EPOCH.saturating_add(SignedDuration::MIN)?,
);
assert_eq!(
    Timestamp::MAX,
    Timestamp::UNIX_EPOCH.saturating_add(std::time::Duration::MAX)?,
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn saturating_sub<A: Into<TimestampArithmetic>>(self: Self, duration: A) -> Result<Timestamp, Error>

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

Errors

This returns an error if the given Span contains any non-zero units greater than hours.

Example

This example shows that arithmetic saturates on overflow.

use jiff::{SignedDuration, Timestamp, ToSpan};

assert_eq!(
    Timestamp::MIN,
    Timestamp::MIN.saturating_sub(1.nanosecond())?,
);
assert_eq!(
    Timestamp::MAX,
    Timestamp::MAX.saturating_sub(-1.nanosecond())?,
);
assert_eq!(
    Timestamp::MIN,
    Timestamp::UNIX_EPOCH.saturating_sub(SignedDuration::MAX)?,
);
assert_eq!(
    Timestamp::MAX,
    Timestamp::UNIX_EPOCH.saturating_sub(SignedDuration::MIN)?,
);
assert_eq!(
    Timestamp::MIN,
    Timestamp::UNIX_EPOCH.saturating_sub(std::time::Duration::MAX)?,
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn until<A: Into<TimestampDifference>>(self: Self, other: A) -> Result<Span, Error>

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

When other occurs before this timestamp, 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 seconds.

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

Properties

It is guaranteed that if the returned span is subtracted from other, and if no rounding is requested, then the original timestamp will be returned.

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

Errors

An error can occur 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 represent the span of time between the minimum and maximum timestamps 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.

An error can also occur if TimestampDifference is misconfigured. For example, if the smallest unit provided is bigger than the largest unit, or if the largest unit provided is bigger than hours. (To use bigger units with an instant in time, use Zoned::until instead.)

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

Example

use jiff::{Timestamp, ToSpan};

let earlier: Timestamp = "2006-08-24T22:30:00Z".parse()?;
let later: Timestamp = "2019-01-31 21:00:00Z".parse()?;
assert_eq!(earlier.until(later)?, 392509800.seconds().fieldwise());

// Flipping the timestamps is fine, but you'll get a negative span.
assert_eq!(later.until(earlier)?, -392509800.seconds().fieldwise());

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

Example: using bigger units

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

use jiff::{Timestamp, ToSpan, Unit};

let ts1: Timestamp = "1995-12-07T03:24:30.000003500Z".parse()?;
let ts2: Timestamp = "2019-01-31 15:30:00Z".parse()?;

// The default limits durations to using "seconds" as the biggest unit.
let span = ts1.until(ts2)?;
assert_eq!(span.to_string(), "PT730641929.9999965S");

// But we can ask for units all the way up to hours.
let span = ts1.until((Unit::Hour, ts2))?;
assert_eq!(span.to_string(), "PT202956H5M29.9999965S");

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

Example: rounding the result

This shows how one might find the difference between two timestamps and have the result rounded such that sub-seconds are removed.

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

use jiff::{Timestamp, TimestampDifference, ToSpan, Unit};

let ts1: Timestamp = "1995-12-07 03:24:30.000003500Z".parse()?;
let ts2: Timestamp = "2019-01-31 15:30:00Z".parse()?;

let span = ts1.until(
    TimestampDifference::from(ts2).smallest(Unit::Second),
)?;
assert_eq!(span.to_string(), "PT730641929S");

// We can combine smallest and largest units too!
let span = ts1.until(
    TimestampDifference::from(ts2)
        .smallest(Unit::Second)
        .largest(Unit::Hour),
)?;
assert_eq!(span.to_string(), "PT202956H5M29S");
# Ok::<(), Box<dyn std::error::Error>>(())
fn since<A: Into<TimestampDifference>>(self: Self, other: A) -> Result<Span, Error>

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

Errors

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

Example

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

use jiff::{Timestamp, ToSpan};

let earlier: Timestamp = "2006-08-24T22:30:00Z".parse()?;
let later: Timestamp = "2019-01-31 21:00:00Z".parse()?;
assert_eq!(later - earlier, 392509800.seconds().fieldwise());

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

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

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

Unlike Timestamp::until, this always returns a duration corresponding to a 96-bit integer of nanoseconds between two timestamps.

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, Timestamp::until can return an error in some cases due to misconfiguration. But like this routine, Timestamp::until never panics or returns an error in its default configuration.

When should I use this versus Timestamp::until?

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

Example

use jiff::{Timestamp, SignedDuration};

let earlier: Timestamp = "2006-08-24T22:30:00Z".parse()?;
let later: Timestamp = "2019-01-31 21:00:00Z".parse()?;
assert_eq!(
    earlier.duration_until(later),
    SignedDuration::from_secs(392509800),
);

// Flipping the timestamps is fine, but you'll get a negative span.
assert_eq!(
    later.duration_until(earlier),
    SignedDuration::from_secs(-392509800),
);

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

Example: difference with Timestamp::until

The primary difference between this routine and Timestamp::until, other than the return type, is that this routine is likely to be faster. Namely, it does simple 96-bit integer math, where as Timestamp::until has to do a bit more work to deal with the different types of units on a Span.

Additionally, since the difference between two timestamps is always expressed in units of hours or smaller, and units of hours or smaller are always uniform, there is no "expressive" difference between this routine and Timestamp::until. Because of this, one can always convert between Span and SignedDuration as returned by methods on Timestamp without a relative datetime:

use jiff::{SignedDuration, Span, Timestamp};

let ts1: Timestamp = "2024-02-28T00:00:00Z".parse()?;
let ts2: Timestamp = "2024-03-01T00:00:00Z".parse()?;
let dur = ts1.duration_until(ts2);
// Guaranteed to never fail because the duration
// between two civil times never exceeds the limits
// of a `Span`.
let span = Span::try_from(dur).unwrap();
assert_eq!(format!("{span:#}"), "172800s");
// Guaranteed to succeed and always return the original
// duration because the units are always hours or smaller,
// and thus uniform. This means a relative datetime is
// never required to do this conversion.
let dur = SignedDuration::try_from(span).unwrap();
assert_eq!(dur, SignedDuration::from_secs(172_800));

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

This conversion guarantee also applies to Timestamp::until since it always returns a balanced span. That is, it never returns spans like 1 second 1000 milliseconds. (Those cannot be losslessly converted to a SignedDuration since a SignedDuration is only represented as a single 96-bit integer of nanoseconds.)

fn duration_since(self: Self, other: Timestamp) -> SignedDuration

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

Example

use jiff::{SignedDuration, Timestamp};

let earlier: Timestamp = "2006-08-24T22:30:00Z".parse()?;
let later: Timestamp = "2019-01-31 21:00:00Z".parse()?;
assert_eq!(
    later.duration_since(earlier),
    SignedDuration::from_secs(392509800),
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn round<R: Into<TimestampRound>>(self: Self, options: R) -> Result<Timestamp, Error>

Rounds this timestamp according to the TimestampRound configuration given.

The principal option is TimestampRound::smallest, which allows one to configure the smallest units in the returned timestamp. Rounding is what determines whether the specified smallest unit should keep its current value or whether it should be incremented. Moreover, the amount it should be incremented can be configured via TimestampRound::increment. Finally, the rounding strategy itself can be configured via TimestampRound::mode.

Note that this routine is generic and accepts anything that implements Into<TimestampRound>. Some notable implementations are:

  • From<Unit> for TimestampRound, which will automatically create a TimestampRound::new().smallest(unit) from the unit provided.
  • From<(Unit, i64)> for TimestampRound, which will automatically create a TimestampRound::new().smallest(unit).increment(number) from the unit and increment provided.

Errors

This returns an error if the smallest unit configured on the given TimestampRound is bigger than hours.

The rounding increment, when combined with the smallest unit (which defaults to Unit::Nanosecond), must divide evenly into 86,400 seconds (one 24-hour civil day). For example, increments of both 45 seconds and 15 minutes are allowed, but 7 seconds and 25 minutes are both not allowed.

Example

This is a basic example that demonstrates rounding a timestamp to the nearest hour. This also demonstrates calling this method with the smallest unit directly, instead of constructing a TimestampRound manually.

use jiff::{Timestamp, Unit};

let ts: Timestamp = "2024-06-19 15:30:00Z".parse()?;
assert_eq!(
    ts.round(Unit::Hour)?.to_string(),
    "2024-06-19T16:00:00Z",
);
let ts: Timestamp = "2024-06-19 15:29:59Z".parse()?;
assert_eq!(
    ts.round(Unit::Hour)?.to_string(),
    "2024-06-19T15:00:00Z",
);

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

Example: changing the rounding mode

The default rounding mode is RoundMode::HalfExpand, which breaks ties by rounding away from zero. But other modes like RoundMode::Trunc can be used too:

use jiff::{RoundMode, Timestamp, TimestampRound, Unit};

// The default will round up to the next hour for any time past the
// 30 minute mark, but using truncation rounding will always round
// down.
let ts: Timestamp = "2024-06-19 15:30:00Z".parse()?;
assert_eq!(
    ts.round(
        TimestampRound::new()
            .smallest(Unit::Hour)
            .mode(RoundMode::Trunc),
    )?.to_string(),
    "2024-06-19T15:00:00Z",
);

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

Example: rounding to the nearest 5 minute increment

use jiff::{Timestamp, Unit};

// rounds down
let ts: Timestamp = "2024-06-19T15:27:29.999999999Z".parse()?;
assert_eq!(
    ts.round((Unit::Minute, 5))?.to_string(),
    "2024-06-19T15:25:00Z",
);
// rounds up
let ts: Timestamp = "2024-06-19T15:27:30Z".parse()?;
assert_eq!(
    ts.round((Unit::Minute, 5))?.to_string(),
    "2024-06-19T15:30:00Z",
);

# Ok::<(), Box<dyn std::error::Error>>(())
fn series(self: Self, period: Span) -> TimestampSeries

Return an iterator of periodic timestamps 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 Timestamp value.

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 jiff::{Timestamp, ToSpan};

let start: Timestamp = "2023-07-15 16:30:00-04".parse()?;
let end = start.checked_add(48.hours())?;
let mut scan_times = vec![];
for ts in start.series(5.hours()).take_while(|&ts| ts <= end) {
    scan_times.push(ts);
}
assert_eq!(scan_times, vec![
    "2023-07-15 16:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-15 21:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-16 02:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-16 07:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-16 12:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-16 17:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-16 22:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-17 03:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-17 08:30:00-04:00".parse::<Timestamp>()?,
    "2023-07-17 13:30:00-04:00".parse::<Timestamp>()?,
]);

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

impl Timestamp

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

Parses a timestamp (expressed as broken down time) in input matching the given format.

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

Errors

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

This also returns an error if there wasn't sufficient information to construct a timestamp. For example, if an offset wasn't parsed. (The offset is needed to turn the civil time parsed into a precise instant in time.)

Example

This example shows how to parse a datetime string into a timestamp:

use jiff::Timestamp;

let ts = Timestamp::strptime("%F %H:%M %:z", "2024-07-14 21:14 -04:00")?;
assert_eq!(ts.to_string(), "2024-07-15T01:14:00Z");

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

Formats this timestamp according to the given format.

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

Errors and panics

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

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

Example

This shows how to format a timestamp into a human readable datetime in UTC:

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

let ts = Timestamp::from_second(86_400)?;
let string = ts.strftime("%a %b %e %I:%M:%S %p UTC %Y").to_string();
assert_eq!(string, "Fri Jan  2 12:00:00 AM UTC 1970");

# Ok::<(), Box<dyn std::error::Error>>(())
fn display_with_offset(self: &Self, offset: Offset) -> TimestampDisplayWithOffset

Format a Timestamp datetime into a string with the given offset.

This will format to an RFC 3339 compatible string with an offset.

This will never use either Z (for Zulu time) or -00:00 as an offset. This is because Zulu time (and -00:00) mean "the time in UTC is known, but the offset to local time is unknown." Since this routine accepts an explicit offset, the offset is known. For example, Offset::UTC will be formatted as +00:00.

To format an RFC 3339 string in Zulu time, use the default std::fmt::Display trait implementation on Timestamp.

Example

use jiff::{tz, Timestamp};

let ts = Timestamp::from_second(1)?;
assert_eq!(
    ts.display_with_offset(tz::offset(-5)).to_string(),
    "1969-12-31T19:00:01-05:00",
);

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

impl Add for Timestamp

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

impl Add for Timestamp

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

impl Add for Timestamp

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

impl AddAssign for Timestamp

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

impl AddAssign for Timestamp

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

impl AddAssign for Timestamp

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

impl Clone for Timestamp

fn clone(self: &Self) -> Timestamp

impl Copy for Timestamp

impl Debug for Timestamp

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

impl Default for Timestamp

fn default() -> Timestamp

impl Display for Timestamp

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

impl Eq for Timestamp

impl Freeze for Timestamp

impl From for Timestamp

fn from(zdt: Zoned) -> Timestamp

impl FromStr for Timestamp

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

impl Hash for Timestamp

fn hash<H: core::hash::Hasher>(self: &Self, state: &mut H)

impl Ord for Timestamp

fn cmp(self: &Self, rhs: &Timestamp) -> Ordering

impl PartialEq for Timestamp

fn eq(self: &Self, rhs: &Timestamp) -> bool

impl PartialOrd for Timestamp

fn partial_cmp(self: &Self, rhs: &Timestamp) -> Option<Ordering>

impl RefUnwindSafe for Timestamp

impl Send for Timestamp

impl Serialize for Timestamp

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

impl Sub for Timestamp

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

impl Sub for Timestamp

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

impl Sub for Timestamp

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

impl Sub for Timestamp

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

impl SubAssign for Timestamp

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

impl SubAssign for Timestamp

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

impl SubAssign for Timestamp

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

impl Sync for Timestamp

impl TryFrom for Timestamp

fn try_from(system_time: SystemTime) -> Result<Timestamp, Error>

impl Unpin for Timestamp

impl UnsafeUnpin for Timestamp

impl UnwindSafe for Timestamp

impl<'a> From for Timestamp

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

impl<'de> Deserialize for Timestamp

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

impl<T> Any for Timestamp

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for Timestamp

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

impl<T> BorrowMut for Timestamp

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

impl<T> CloneToUninit for Timestamp

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

impl<T> DeserializeOwned for Timestamp

impl<T> From for Timestamp

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> ToOwned for Timestamp

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

impl<T> ToString for Timestamp

fn to_string(self: &Self) -> String

impl<T, U> Into for Timestamp

fn into(self: Self) -> U

Calls U::from(self).

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

impl<T, U> TryFrom for Timestamp

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

impl<T, U> TryInto for Timestamp

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