Skip to main content

Dt

Struct Dt 

Source
pub struct Dt {
    pub attos: i128,
    pub scale: Scale,
    pub target: Scale,
}
Expand description

The library’s central time type. A high-precision instant/duration with attosecond resolution.

Fields:

  • pub attos: i128 - total time in attoseconds since the reference epoch (2000-01-01 noon), as a signed integer. Negative values represent times before the epoch.
  • pub scale: Scale - the current time scale of the object.
  • pub target: Scale - a target time scale used by many output functions such as Dt::to_ymd and Dt::to_unix. The functions convert to the target time scale before producing an output.

Notes:

  • In theory it supports a range of roughly ±5.39 trillion years but many of the to and from functions cap at i64 seconds, which can mean a range of ±292 billion years in practice. Additionally, when parsing dates with a timezone the Rust library jiff is used which has a limit of -9999 - 9999 years.
  • Implements Copy and Clone. Optional derives for serde and tsify are available behind the corresponding features.
  • A wide range of math is available for this type, including basic calendar aware math and, with the jiff-tz feature enabled, timezone and DST aware math. Behavior greatly differs between functions.

§Reference epoch and scales

  • The librarys epoch for nearly all functionality such as the conversion functions is 2000-01-01 noon. See also: Scale.
  • Leap-second handling follows the chosen Scale (UTC, UtcSpice, UtcHist).

§See also (non-exhaustive list)

§From and to calendar dates

§From and to str and bytes

Some of these require the alloc feature, they’re marked with *

§From and to julian dates

§Conversions, time scales etc.

§Conversions from and to types from other libraries

§Examples

§Parsing a date

use deep_time::{Dt, Scale};

// uses impl FromStr but Dt::parse provides the same functionality
let x: Dt = "2000-01-01 12:00:00".parse().unwrap();

let ymd = x.to_ymd();
assert_eq!(ymd.yr(), 2000);
assert_eq!(ymd.mo(), 1);
assert_eq!(ymd.day(), 1);
assert_eq!(ymd.hr(), 12);
assert_eq!(ymd.min(), 0);
assert_eq!(ymd.sec(), 0);
assert_eq!(ymd.attos(), 0);

§Outputting a date to string / bytes

use deep_time::{Dt, Lang, Scale};

let x: Dt = "2000-01-01 12:00:00".parse().unwrap();

let s = x
 .to_str_in_tz("%A, %B %d, %Y %H:%M:%S %Q", "America/New_York", Lang::En)
 .unwrap();
let b = x
 .to_str_lite_in_tz("%A, %B %d, %Y %H:%M:%S %Q", "America/New_York", Lang::En)
 .unwrap();

assert_eq!(s, "Saturday, January 01, 2000 07:00:00 America/New_York");
assert_eq!(b.as_str(), "Saturday, January 01, 2000 07:00:00 America/New_York");

§Creating a unix timestamp in milliseconds

use deep_time::{Dt, Scale};

// this fn converts from UTC and creates a TAI Dt
let dt = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);

// dt is internally TAI but has a UTC tag
let unix_ms = dt.to_unix().to_ms();

// unix timestamp in ms for 2000-01-01 noon UTC
assert_eq!(unix_ms, 946728000000);

§Converting time scales

Many functions such as Dt::to_ymd will convert to TAI from the Dts current scale then to the Dts target Scale prior to producing an output.

So you don’t necessarily have to convert time scales prior to using many of the output functions. You just have to change the target time scale.

§Using the target field
use deep_time::{Dt, Lang, Scale};

// Leap seconds were added to the secounds count
// This Dt has attos that are now on the TAI timescale
let dt = Dt::from_ymd(2025, 1, 1, Scale::UTC, 0, 0, 0, 0);

// The internal target is currently UTC so we don't need to do
// anything to output back to UTC and round trip
let bytes = dt.to_str_lite("%d %m %Y %H:%M:%S", Lang::En).unwrap();

assert_eq!(bytes.as_str(), "01 01 2025 00:00:00");

// Perhaps we want to make a GPS timestamp out of our Dt
// If we want it to be on the GPS time scale we have to set the
// target prior to calling to_gps()
let gps = dt.target(Scale::GPS).to_gps().to_sec_f();
§Converting the internal attos to a new time scale
use deep_time::{Dt, Scale};

// this fn converts from UTC and creates a TAI Dt
let dt = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);

// to tdb
let tdb = dt.to(Scale::TDB);

// then to tt, the current scale is TDB
let tt = tdb.to(Scale::TT);

// then back to TAI
let tai = tt.to(Scale::TAI);

// round trip equality
assert_eq!(dt, tai);

§Performing some basic calendar aware math

use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2000, 2, 29, Scale::UTC, 0, 0, 0, 0).to_ymd();
let x = x.add_yr(1);

assert_eq!(x.day(), 28);

§Changing a dates format

use deep_time::{Dt, Lang, StrPTimeFmt};

let fmt = Dt::parse_fmt("%Y-%m-%dT%H:%M:%S").unwrap();

let s = fmt.to_str("2000-01-01T12:00:00", "%d %m %Y %H:%M:%S", false, false, false, Lang::En).unwrap();

assert_eq!(s, "01 01 2000 12:00:00", "expected: {}, got: {}", "01 01 2000 12:00:00", s);

Fields§

§attos: i128§scale: Scale§target: Scale

Implementations§

Source§

impl Dt

Source

pub fn from_str_parse(s: &str, opts: &ParseCfg) -> Result<Dt, DtErr>

Automatically parses datetime str into a Dt by guessing and generating the format. Supports the vast majority of date formats.

  • Requires the "parse" feature (which enables alloc).
  • The returned Dt is internally on the TAI time scale. The attos field is an i128 attosecond count since TAI 2000-01-01 noon. See [Scale] for more information.
  • The returned Dt is not in local time, if a timezone is parsed then it’s used to find the offset to return non-local instant.
§Parameters
  • s: The string to parse. Must be non-empty and no longer than 255 bytes. Empty strings or overly long inputs return an error.
  • opts: The ParseCfg to use. Pass &ParseCfg::DEFAULT (or &ParseCfg::default()) to use the standard smart defaults. You can create a ParseCfg once and pass &cfg on every call for consistent behavior and to avoid repeated construction.
§Configuration Options

These are the fields of the configuration options struct ParseCfg, their types and defaults.

See ParseCfg for more information.

FieldType and DefaultEffect
langLang::EnLanguage, scroll down to see currently supported languages
orderOrder::SmartHow to resolve ambiguous numeric dates like 01/02/03
modeMode::AutoSpecial handling for purely numeric inputs
parseOption<Vec<String>> - NoneAn explicit list of formats to try, if the Mode is Explicit then only these formats are tried
relativebool - trueEnable phrases like “tomorrow”, “in 3 days”
ref_timeOption<Dt> - NoneReference time for relative dates and syslog-style “no-year” dates
to_lowerbool - trueAutomatically lowercase the input, only set to false if it’s already lowercase
§Purely Numeric Inputs

When the input consists only of digits (and optionally a decimal point), the parser uses a fast, mode-aware path before trying any other strategies. The exact interpretation depends on the number of digits and the selected mode.

DigitsExample(s)ModeInterpreted asNotes
1–42024, 24, 5Auto/LegacyYear (2-digit uses 2000/1900 pivot)1- and 3-digit years only work in Scientific
524123, 60400LegacyOrdinal date (YYDDD)
560400, 60400.75ScientificModified Julian Date (MJD)Fractional days supported
524123, 60400.75AutoOrdinal (non-decimal) or MJD (decimal)Smart default
6240315, 202403AutoYYYYMM if plausible year, else YYMMDDMost common compact form
6240315LegacyYYMMDD preferred
6202403ScientificYYYYMM preferred
72024123LegacyOrdinal date (YYYYDDD)
72460123, 2460123.5ScientificJulian Day (JD)Fractional days supported
72024123AutoOrdinal (integer) or JD (decimal)Smart default
10–111735689600anyUnix seconds
12–151735689600123anyUnix millisecondsMost common high-precision case
16–181735689600123456anyUnix microseconds
19+1735689600123456789anyUnix nanosecondsFull precision

Use Mode::UnixTimestamp when you know the input is always a Unix timestamp.

§Ambiguous Numeric Dates

Dates where the components could map to different orders (e.g. 01/02/03, 3-4-5, 15.03.24, 2024.03.15) are resolved via the order field:

  • Order::Smart (default) — Applies the fast heuristic described in Order::Smart. It strongly prefers modern/tech conventions (Year-first for compact/ISO-like data) while handling the majority of international and US-style dates.

  • Order::Year, Order::Day, or Order::Month force a specific interpretation and bypass the heuristic entirely.

§Supported Formats

The parser tokenizes known words (month/day names, relative phrases, timezones, etc.), generates candidate formats from the token pattern, and tries them until one matches. Thousands of layouts are supported.

Separators generally don’t matter, they could be spaces, slashes, or hyphens, but not colons - colons are reserved for the time connector, times, and offsets.

Generally speaking the date part must come first, and stuff like time components, offsets and iana timezone names must come afterwards.

  • ISO 8601 and variants: 2024-03-15, 2024-03-15T14:30:00Z, 2024-03-15T14:30:00+01:00[Europe/Paris]
  • Named dates (in supported languages): 15 March 2024, 15 mars 2024, 15. März 2024, 15 de marzo de 2024
  • Week dates: 2024-W15, 2024-W15-3, 2024W153 (missing weekday defaults to Monday)
  • Syslog-style (no year): Mar 5 10:23:45 (year inferred from ref_time)
  • Relative expressions: tomorrow, in 3 days, 2 weeks ago
  • 12-hour time: 2:30 PM, 14:30:45.123
  • Offsets and timezones: +0100, -05:30, Z, IANA timezone names (with the jiff-tz feature enabled)
  • Library time scales: TAI, TT, etc. are detected and parsed, must come after the date part of the input

Relative dates are also automatically supported, except for bare numbers with no colons like 0900, as these are differently interpreted.

§Examples
use deep_time::{Dt, ParseCfg, Order, Mode, Scale};

// Default smart parsing
let dt = Dt::from_str_parse("2024-03-15 14:30:00", &ParseCfg::DEFAULT).unwrap();

// German named date (requires the `de` feature)
let cfg = ParseCfg { lang: Lang::De, ..Default::default() };
let dt = Dt::from_str_parse("15. März 2024 um 14:30", &cfg).unwrap();

// Pure numeric compact form
let dt = Dt::from_str_parse("20240315", &ParseCfg::DEFAULT).unwrap(); // March 15, 2024

// Unix timestamp (milliseconds)
let cfg = ParseCfg { mode: Mode::UnixTimestamp, ..Default::default() };
let dt = Dt::from_str_parse("1735689600123", &cfg).unwrap();

// Explicit formats only (no fallback)
let cfg = ParseCfg {
    parse: Some(vec!["%d/%m/%Y".into(), "%Y-%m-%d".into()]),
    mode: Mode::Explicit,
    ..Default::default()
};
let dt = Dt::from_str_parse("15/03/2024", &cfg).unwrap();

// Relative dates — build config once, borrow repeatedly
let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
let cfg = ParseCfg {
    ref_time: Some(ref_time),
    ..Default::default()
};
let dt = Dt::from_str_parse("next Monday at 14:00", &cfg).unwrap();

assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
§Notes
  • The Smart + Auto combination gives the best real-world success rate for mixed data.
  • Relative expressions and syslog-style no-year dates need a reference time. If ref_time is None and the std feature is enabled, system time is used; without std, set ref_time explicitly or parsing will fail.
  • All successfully parsed Dt values are stored with attosecond precision on the internal TAI timescale.
  • Timezone handling (IANA names and fixed offsets) is fully supported when the jiff-tz feature is enabled.
§Supported Languages:

Language support here basically means supporting abbreviated and full day and month names. Non-Ascii types of numeric characters are also supported such as full width digits.

Some day/month names in non-English languages are not supported due to clashes, any such missing support is noted below.

  • En
  • De
    • Won’t parse “t” as short form for day.
  • Es
    • English word “ago” won’t be detected as relative date word.
    • Won’t parse “mar” as tuesday, will instead parse as march.
  • Fr
    • Won’t parse “mar” as tuesday, will instead parse as march.
§See also
Examples found in repository?
examples/readme.rs (line 13)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn str_to_attos(s: &str, opts: &ParseCfg) -> Option<i128>

Same parsing logic as Dt::from_str_parse, but returns attoseconds since the library epoch: 2000-01-01 12:00:00 UTC (on the UTC scale).

Returns Some(attos) on success (negative for pre-2000 dates) or None on any parse error.

Source

pub fn str_to_ms(s: &str, opts: &ParseCfg) -> Option<i128>

Same parsing logic as Dt::from_str_parse, but returns milliseconds since the library epoch: 2000-01-01 12:00:00 UTC (on the UTC scale).

Returns Some(millis) on success (negative for pre-2000 dates) or None on any parse error.

Source

pub fn str_to_ns(s: &str, opts: &ParseCfg) -> Option<i128>

Same parsing logic as Dt::from_str_parse, but returns nanoseconds since the library epoch: 2000-01-01 12:00:00 UTC (on the UTC scale).

Returns Some(nanos) on success (negative for pre-2000 dates) or None on any parse error.

Source

pub fn str_to_unix_ms(s: &str, opts: &ParseCfg) -> Option<i128>

Same parsing logic as Dt::from_str_parse, but returns milliseconds since the UNIX epoch: (1970-01-01 00:00:00 UTC).

Returns Some(millis) on success (negative for pre-2000 dates) or None on any parse error.

Source

pub fn str_to_unix_ns(s: &str, opts: &ParseCfg) -> Option<i128>

Same parsing logic as Dt::from_str_parse, but returns nanoseconds since the UNIX epoch: (1970-01-01 00:00:00 UTC).

Returns Some(nanos) on success (negative for pre-2000 dates) or None on any parse error.

Source§

impl Dt

Source

pub fn from_str_duration(s: &str, lang: Lang) -> Result<Dt, DtErr>

Parses duration strings, tries formats in the following order:

  1. Strict ISO 8601 e.g. P1DT2H30M
  2. Common natural-language formats e.g. 2 wks, 3 days, and 2 mins
  3. Media duration format e.g. 1:07:54:30
  4. Numerical milliseconds, decimals counted as fractional milliseconds

Returns a Dt.

Examples found in repository?
examples/readme.rs (line 57)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn natural_to_iso(s: &str, lang: Lang) -> Result<String, DtErr>

Converts a natural language duration into an ISO duration.

Source§

impl Dt

Source

pub const WIRE_VERSION: u8 = 1

Current wire format version.

Source

pub const WIRE_SIZE: usize = 19

Size of the canonical wire representation in bytes.

Source

pub fn to_wire_bytes(&self) -> [u8; 19]

Serializes this Dt into a fixed 18-byte little-endian buffer using the attos: i128 + scale: Scale representation.

§Wire Format
  • Byte 0: Version (WIRE_VERSION)
  • Bytes [1..17]: total attoseconds as little-endian i128
  • Byte 17: scale as u8 (enum discriminant)
  • Byte 18: target as u8 (enum discriminant)
Source

pub fn from_wire_bytes(bytes: &[u8]) -> Option<Self>

Deserializes a Dt from exactly 18 bytes of wire data.

Returns None if the version byte is unknown, the length is wrong, or the scale byte is not a valid Scale variant.

§Wire Format
  • Byte 0: Version (WIRE_VERSION)
  • Bytes [1..17]: total attoseconds as little-endian i128
  • Byte 17: scale as u8 (enum discriminant)
  • Byte 18: target as u8 (enum discriminant)
§Security

Safe to call with completely untrusted input. Fixed-size format, no allocation, no unsafe, and no possibility of code execution.

Source§

impl Dt

Source

pub const fn add(&self, dt: Dt) -> Dt

Saturating add, keeps self’s scale and target.

Source

pub const fn sub(&self, dt: Dt) -> Dt

Saturating sub, keeps self’s scale and target.

Source

pub const fn to_sec_trunc(&self) -> i128

Returns the whole seconds portion of this Dt using truncation towards zero (i.e., the integer part obtained via truncating division, without rounding).

This is equivalent to self.attos / ATTOS_PER_SEC_I128.

Unlike to_sec (which uses Euclidean division, flooring towards negative infinity for negative values to keep the fractional part non-negative), this version truncates towards zero.

Consequently, for values in (-1, 0) seconds (e.g. -0.3 s or -0.8 s), both return 0.

§Examples
use deep_time::Dt;

// -0.3 seconds → truncates to 0
let dt = Dt::span(-300_000_000_000_000_000);
assert_eq!(dt.to_sec_trunc(), 0);

// -0.8 seconds → truncates to 0
let dt = Dt::span(-800_000_000_000_000_000);
assert_eq!(dt.to_sec_trunc(), 0);

// -1.3 seconds → truncates to -1 (while to_sec gives -2)
let dt = Dt::span(-1_300_000_000_000_000_000);
assert_eq!(dt.to_sec_trunc(), -1);
assert_eq!(dt.to_sec(), -2);

// Positive values behave the same as `to_sec`
let dt = Dt::span(1_300_000_000_000_000_000);
assert_eq!(dt.to_sec_trunc(), 1);
assert_eq!(dt.to_sec(), 1);
Source

pub const fn to_sec64_trunc(&self) -> i64

Returns the whole seconds portion of this Dt using truncation towards zero, then clamped to an i64.

If the truncated seconds value lies outside the i64 range, the result saturates to i64::MAX or i64::MIN.

See to_sec_trunc for the truncation semantics (towards zero, no rounding).

§Examples
use deep_time::Dt;

let dt = Dt::span(-1_300_000_000_000_000_000);
assert_eq!(dt.to_sec64_trunc(), -1);

let dt = Dt::span(1_300_000_000_000_000_000);
assert_eq!(dt.to_sec64_trunc(), 1);
Source

pub const fn to_sec(&self) -> i128

If this time were turned into i128 seconds and u64 (always pushing to the positive) fractional attoseconds, this returns the whole seconds part.

To just get seconds rounded to the nearest second use Dt::to_sec_rounded instead.

§Examples
use deep_time::{Dt, Scale};

// negative 1.3 seconds
let dt = Dt::span(-1_300_000_000_000_000_000);

// becomes positive 700ms
let frac = dt.to_sec_ufrac();
assert_eq!(frac, 700_000_000_000_000_000);

// becomes negative 2 seconds
let sec = dt.to_sec();
assert_eq!(sec, -2);

let dt = Dt::span(1_300_000_000_000_000_000);

assert_eq!(dt.to_sec(), 1);
assert_eq!(dt.to_sec_ufrac(), 300_000_000_000_000_000);

// if you just want rounded seconds
// use to_sec_rounded() instead
let dt = Dt::span(-1_300_000_000_000_000_000);
let sec = dt.to_sec_rounded();
assert_eq!(sec, -1);
Source

pub const fn to_sec_rounded(&self) -> i128

Returns this Dt rounded to the nearest whole second, then converted to an i128 number of seconds.

  • Exactly halfway cases (e.g. 0.5 s, -0.5 s) round as follows: 0.5 becomes 1 and -0.5 becomes -1.
  • Matches the behavior of Dt::round.
§Examples
use deep_time::Dt;

// 1.3 seconds → rounds to 1
assert_eq!(Dt::span(1_300_000_000_000_000_000).to_sec_rounded(), 1);

// -1.3 seconds → rounds to -1
assert_eq!(Dt::span(-1_300_000_000_000_000_000).to_sec_rounded(), -1);

// 1.6 seconds → rounds to 2
assert_eq!(Dt::span(1_600_000_000_000_000_000).to_sec_rounded(), 2);

// Halfway cases
assert_eq!(Dt::span(500_000_000_000_000_000).to_sec_rounded(), 1);
assert_eq!(Dt::span(-500_000_000_000_000_000).to_sec_rounded(), -1);
Source

pub const fn to_sec64_rounded(&self) -> i64

Returns this Dt rounded to the nearest whole second, then converted to an i64 number of seconds.

  • Exactly halfway cases round as follows: 0.5 becomes 1 and -0.5 becomes -1, same as to_sec_rounded.
  • If the rounded value is outside the representable i64 range, it saturates to i64::MAX or i64::MIN.
§Examples
use deep_time::Dt;

let dt = Dt::span(1_300_000_000_000_000_000);
assert_eq!(dt.to_sec64_rounded(), 1);

let dt = Dt::span(-1_300_000_000_000_000_000);
assert_eq!(dt.to_sec64_rounded(), -1);
Source

pub const fn to_sec64(&self) -> i64

If this time were turned into i64 seconds and u64 (always pushing to the positive) fractional attoseconds, this returns the whole seconds part.

To just get seconds rounded to the nearest second use Dt::to_sec_rounded instead.

§Examples
use deep_time::{Dt, Scale};

// negative 1.3 seconds
let dt = Dt::span(-1_300_000_000_000_000_000);

// becomes positive 700ms
let frac = dt.to_sec_ufrac();
assert_eq!(frac, 700_000_000_000_000_000);

// becomes negative 2 seconds
let sec = dt.to_sec64();
assert_eq!(sec, -2);

let dt = Dt::span(1_300_000_000_000_000_000);

assert_eq!(dt.to_sec64(), 1);
assert_eq!(dt.to_sec_ufrac(), 300_000_000_000_000_000);

// if you just want rounded seconds
// use to_sec_rounded() instead
let dt = Dt::span(-1_300_000_000_000_000_000);
let sec = dt.to_sec_rounded();
assert_eq!(sec, -1);
Source

pub const fn to_f64(&self) -> f64

Converts this Dt to an f64 number of seconds since the reference epoch of its associated scale.

  • The conversion is lossy, as f64 provides approximately 15.95 decimal digits of precision.
Source

pub const fn to_sec_f(&self) -> Real

Converts this Dt to a floating-point number of seconds since the reference epoch of its associated scale.

  • The conversion is lossy, as Real provides approximately 15.95 decimal digits of precision.
Examples found in repository?
examples/readme.rs (line 85)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn to_sec_frac(&self) -> i64

If this time were turned into seconds, this returns the fractional attoseconds part.

Source

pub const fn to_sec_ufrac(&self) -> u64

If this time were turned into i64 seconds and u64 (always pushing to the positive) fractional attoseconds, this returns the fractional attoseconds part.

  • Always returns a value in the range 0 ≤ x < ATTOS_PER_SEC.
  • For negative Dts this is not simply the decimal part of the time in seconds.
§Examples
use deep_time::{Dt, Scale};

// negative 1.3 seconds
let dt = Dt::span(-1_300_000_000_000_000_000);

// becomes positive 700ms
let frac = dt.to_sec_ufrac();
assert_eq!(frac, 700_000_000_000_000_000);

// becomes -2 seconds
let sec = dt.to_sec64();
assert_eq!(sec, -2);

let dt = Dt::span(1_300_000_000_000_000_000);

assert_eq!(dt.to_sec64(), 1);
assert_eq!(dt.to_sec_ufrac(), 300_000_000_000_000_000);
Source

pub const fn round_to_sec(&self) -> Dt

Returns a new Dt rounded to the nearest second.

Source

pub const fn to_mins(&self) -> i128

Returns the total time in minutes.

Source

pub const fn to_hrs(&self) -> i128

Returns the total time in hours.

Source

pub const fn to_days(&self) -> i128

Returns the total time in days.

Source

pub const fn to_diff_raw(&self, other: Dt) -> Dt

Computes the signed duration between this Dt and another Dt.

Source

pub const fn to_diff_raw_f(&self, other: Dt) -> Real

Computes the signed duration between this Dt and another Dt as a float.

Source

pub const fn from_diff_raw(attos: i128, epoch: Dt) -> Dt

Low level constructor from total attoseconds since a given epoch.

Simply adds the total attoseconds to the epoch. Does not perform any time scale conversions.

§Examples
use deep_time::{Dt, Scale};

// A leap second from the middle of the table (36 leap seconds accumulated)
let original = Dt::from_ymd(2015, 6, 30, Scale::UTC, 23, 59, 60, 123_456_789_000_000_000);

// Round-trip through canonical attoseconds
let canon = original.to_diff_raw(Dt::UNIX_EPOCH).to_attos();
let roundtrip1 = Dt::from_diff_raw(canon, Dt::UNIX_EPOCH);

assert_eq!(original, roundtrip1, "Canonical round-trip failed");
Source

pub const fn add_attos(&self, n: i128) -> Dt

Adds the specified number of attoseconds to this time value.

Source

pub const fn add_sec(&self, n: i128) -> Dt

Adds the specified number of seconds to this time value using saturating arithmetic.

Source

pub const fn add_ms(&self, n: i128) -> Dt

Adds the specified number of milliseconds to this time value.

Examples found in repository?
examples/readme.rs (line 89)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn add_us(&self, n: i128) -> Dt

Adds the specified number of microseconds to this time value.

Source

pub const fn add_ns(&self, n: i128) -> Dt

Adds the specified number of nanoseconds to this time value.

Source

pub const fn add_ps(&self, n: i128) -> Dt

Adds the specified number of picoseconds to this time value.

Source

pub const fn add_fs(&self, n: i128) -> Dt

Adds the specified number of femtoseconds to this time value.

Source

pub const fn add_min(&self, n: i64) -> Dt

Adds the specified number of minutes to this time value using saturating arithmetic.

Source

pub const fn add_hr(&self, n: i64) -> Dt

Adds the specified number of hours to this time value using saturating arithmetic.

Examples found in repository?
examples/readme.rs (line 111)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn to_attos(&self) -> i128

Returns the total time in attoseconds.

Source

pub const fn to_ms(&self) -> i128

Returns the total time in milliseconds.

Examples found in repository?
examples/readme.rs (line 89)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn to_us(&self) -> i128

Returns the total time in microseconds.

Source

pub const fn to_ns(&self) -> i128

Returns the total time in nanoseconds.

Source

pub const fn to_ps(&self) -> i128

Returns the total time in picoseconds.

Source

pub const fn to_fs(&self) -> i128

Returns the total time in femtoseconds.

Source

pub const fn is_zero(&self) -> bool

Returns true if this time is zero.

Source

pub const fn is_positive(&self) -> bool

Returns true if this time is strictly positive > 0.

Source

pub const fn mul(self, rhs: i64) -> Dt

Multiplies this time by an integer scalar.

Uses 128-bit arithmetic internally.

Source

pub const fn div(self, rhs: i64) -> Dt

Divides this Dt by an integer scalar.

Uses truncating division (rounds toward zero), same as normal integer division. Returns ZERO if rhs == 0.

Source

pub const fn floor(&self, unit: Dt) -> Dt

Returns the largest multiple of unit that is ≤ self. If unit is zero, returns self unchanged (exact, full precision).

Source

pub const fn ceil(&self, unit: Dt) -> Dt

Returns the smallest multiple of unit that is ≥ self. If unit is zero, returns self unchanged (exact, full precision).

Source

pub const fn round(&self, unit: Dt) -> Dt

Returns the nearest multiple of unit.

Halfway cases round away from zero (e.g. 2.5 → 3.0, -2.5 → -3.0), matching the behavior of the old f64::round().

  • If unit is zero, returns self unchanged (preserves full precision).
  • Uses Euclidean division internally for negative values.
  • The result is always a multiple of unit.
Source

pub const fn abs_div_floor(&self, unit: Dt) -> usize

Returns floor(|self| / |unit|) as usize, saturating at usize::MAX.

Fully exact integer arithmetic using 128-bit intermediaries. Used by TimeRange::len.

Source

pub const fn mul_by_f(&self, rhs: Real) -> Dt

Multiplies this Dt by a floating-point scalar using saturating attosecond arithmetic.

§Algorithm
  • rhs is split into an integer part (floor_f) and a fractional part in [0, 1).
  • The integer part is multiplied exactly via i128::checked_mul, saturating to Dt::MAX / Dt::MIN on overflow.
  • The fractional part is applied via a 10¹⁵-scaled decomposition that avoids intermediate i128 overflow.
  • The two parts are combined with i128::saturating_add and clamped to the representable attosecond range.
§Precision
  • Integer scalars (e.g. 2.0, -3.0) use exact integer arithmetic for their whole part.
  • General f64 scalars are limited by IEEE-754 precision (~15 decimal digits) and the 10¹⁵ fractional quantization.
§Special cases
ConditionResult
rhs is NaNDt::ZERO
rhs is ±∞ and self is zeroDt::ZERO
rhs is ±∞ and self is non-zeroDt::MAX or Dt::MIN (sign of product)
rhs == 0.0 or self is zeroDt::ZERO
Product exceeds i128 rangeDt::MAX or Dt::MIN (sign of product)

NaN maps to zero rather than poisoning the result: Dt has no NaN state, and zero is the additive identity (a safe, non-saturating default for invalid scale factors).

Source

pub const fn div_by_f(&self, rhs: Real) -> Dt

Divides by a real number (routes through the high-precision mul_by_f).

Source

pub const fn div_by_2(&self) -> Dt

Divides this Dt by 2 (convenience wrapper).

Source

pub const fn sec_and_attos_to_attos(sec: i64, attos: u64) -> i128

Combines i64 seconds and u64 attoseconds into a total signed i128 attoseconds value.

  • When seconds >= 0, the result is seconds * 10¹⁸ + attoseconds.
  • When seconds < 0, the fractional attoseconds are treated as negative: seconds * 10¹⁸ - attoseconds.
Source

pub const fn sec_to_attos(sec: i128) -> i128

Converts seconds i128 → total attoseconds i128

Source

pub const fn attos_to_sec_i64(attos: i128) -> i64

Converts total attoseconds → whole seconds as i64

Source

pub const fn attos_to_sec_f(attos: u128) -> Real

Lossy conversion of u128 attoseconds to → float seconds (s).

Source

pub const fn attos_to_sec(attos: i128) -> i128

Converts i128 attoseconds → seconds (s)

Source

pub const fn attos_to_ms(attos: i128) -> i128

Converts i128 attoseconds → milliseconds (ms)

Source

pub const fn attos_to_us(attos: i128) -> i128

Converts i128 attoseconds → microseconds (us)

Source

pub const fn attos_to_ns(attos: i128) -> i128

Converts i128 attoseconds → nanoseconds (ns)

Source

pub const fn attos_to_ps(attos: i128) -> i128

Converts i128 attoseconds → picoseconds (ps)

Source

pub const fn attos_to_fs(attos: i128) -> i128

Converts i128 attoseconds → femtoseconds (fs)

Source

pub const fn div_dt(self, rhs: Dt) -> Real

Returns the scalar ratio self / rhs expressed in seconds (as Real).

This is the floating-point equivalent of self.to_sec_f() / rhs.to_sec_f().

§Special cases (chosen for safety and usability in time arithmetic)
  • non-zero / ZERO returns ±Real::INFINITY (sign matches self)
  • ZERO / non-zero returns 0.0
  • ZERO / ZERO returns 1.0 (the two durations are identical)

These rules avoid NaN entirely while remaining predictable and useful in simulations, rate calculations, and control code.

Negative durations are supported (e.g. (-5 s) / (2 s) == -2.5).

This method is const fn and can be used in const contexts.

Source

pub const fn adjusted_advance(&mut self, elapsed: &Dt, spacetime: &Spacetime)

Advances this Dt by the given elapsed duration while applying the relativistic proper-time correction derived from the supplied Spacetime model.

  • This method is intended for simulation of remote clocks (e.g., Earth time as observed from a spacecraft).
  • For a local hardware proper-time clock, use the plain add methods instead.
Source

pub const fn adjusted_advance_using_drift( &mut self, elapsed: &Dt, drift: &Drift, )

Advances this Dt by the given elapsed duration while applying the relativistic proper-time correction from a pre-computed Drift value.

  • This is an optimized variant of Dt::adjusted_advance for callers that already hold a Drift instance.
  • This method is intended for simulation of remote clocks (e.g., Earth time as observed from a spacecraft).
  • For a local hardware proper-time clock, use the plain add methods instead.
Source§

impl Dt

Source

pub const fn add_yr(&self, n: i64) -> Self

Adds (or subtracts) calendar years, preserving month and day-of-month.

  • Uses standard last-day-of-month clamping.
  • Negative values subtract.
Source

pub const fn add_mo(&self, n: i64) -> Self

Adds (or subtracts) calendar months. Negative values subtract.

Examples found in repository?
examples/readme.rs (line 104)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn add_wk(&self, n: i64) -> Self

Adds (or subtracts) calendar weeks. Negative values subtract.

Source

pub const fn add_days(&self, n: i64) -> Self

Adds (or subtracts) calendar days. Negative values subtract.

Source§

impl Dt

Source

pub fn add_yr_tz(&self, n: i64, tz: &str) -> Result<Self, DtErr>

Adds the given number of years in the specified IANA timezone, respecting timezone rules (including DST) and calendar arithmetic.

§Notes
  • Requires the jiff-tz feature.
  • Assumes this Dt is counting seconds from the library’s 2000-01-01 12:00:00 epoch.
§Errors
  • Jiff only supports years in the range -9999..=9999. Years outside this range will return a DtErr.
  • If Jiff cannot find the timezone name or if applying the timezone would cause the jiff::Zoned to be outside the -9999..=9999 year range then a DtErr with [DtErrKind::InvalidTimezoneOffset] is returned.
Source

pub fn add_mo_tz(&self, n: i64, tz: &str) -> Result<Self, DtErr>

Adds the given number of months in the specified IANA timezone, respecting timezone rules and calendar month-end clamping.

§Notes
  • Requires the jiff-tz feature.
  • Assumes this Dt is counting seconds from the library’s 2000-01-01 12:00:00 epoch.
  • Will error if the year is outside of -9999..=9999.
§Errors
  • Jiff only supports years in the range -9999..=9999. Years outside this range will return a DtErr.
  • If Jiff cannot find the timezone name or if applying the timezone would cause the jiff::Zoned to be outside the -9999..=9999 year range then a DtErr with [DtErrKind::InvalidTimezoneOffset] is returned.
Source

pub fn add_wk_tz(&self, n: i64, tz: &str) -> Result<Self, DtErr>

Adds the given number of weeks in the specified IANA timezone, respecting timezone rules (including DST).

§Notes
  • Requires the jiff-tz feature.
  • Assumes this Dt is counting seconds from the library’s 2000-01-01 12:00:00 epoch.
  • Will error if the year is outside of -9999..=9999.
§Errors
  • Jiff only supports years in the range -9999..=9999. Years outside this range will return a DtErr.
  • If Jiff cannot find the timezone name or if applying the timezone would cause the jiff::Zoned to be outside the -9999..=9999 year range then a DtErr with [DtErrKind::InvalidTimezoneOffset] is returned.
Source

pub fn add_days_tz(&self, n: i64, tz: &str) -> Result<Self, DtErr>

Adds the given number of calendar days in the specified IANA timezone, respecting timezone rules (including DST).

§Notes
  • Requires the jiff-tz feature.
  • Assumes this Dt is counting seconds from the library’s 2000-01-01 12:00:00 epoch.
  • Will error if the year is outside of -9999..=9999.
§Errors
  • Jiff only supports years in the range -9999..=9999. Years outside this range will return a DtErr.
  • If Jiff cannot find the timezone name or if applying the timezone would cause the jiff::Zoned to be outside the -9999..=9999 year range then a DtErr with [DtErrKind::InvalidTimezoneOffset] is returned.
Source

pub fn add_hr_tz(&self, n: i64, tz: &str) -> Result<Self, DtErr>

Adds the given number of hours in the specified IANA timezone, respecting timezone rules (including DST).

§Notes
  • Requires the jiff-tz feature.
  • Assumes this Dt is counting seconds from the library’s 2000-01-01 12:00:00 epoch.
  • Will error if the year is outside of -9999..=9999.
§Errors
  • Jiff only supports years in the range -9999..=9999. Years outside this range will return a DtErr.
  • If Jiff cannot find the timezone name or if applying the timezone would cause the jiff::Zoned to be outside the -9999..=9999 year range then a DtErr with [DtErrKind::InvalidTimezoneOffset] is returned.
Examples found in repository?
examples/readme.rs (line 114)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn add_min_tz(&self, n: i64, tz: &str) -> Result<Self, DtErr>

Adds the given number of minutes in the specified IANA timezone, respecting timezone rules (including DST).

§Notes
  • Requires the jiff-tz feature.
  • Assumes this Dt is counting seconds from the library’s 2000-01-01 12:00:00 epoch.
  • Will error if the year is outside of -9999..=9999.
§Errors
  • Jiff only supports years in the range -9999..=9999. Years outside this range will return a DtErr.
  • If Jiff cannot find the timezone name or if applying the timezone would cause the jiff::Zoned to be outside the -9999..=9999 year range then a DtErr with [DtErrKind::InvalidTimezoneOffset] is returned.
Source

pub fn add_sec_tz(&self, n: i64, tz: &str) -> Result<Self, DtErr>

Adds the given number of seconds in the specified IANA timezone, respecting timezone rules (including DST).

§Notes
  • Requires the jiff-tz feature.
  • Assumes this Dt is counting seconds from the library’s 2000-01-01 12:00:00 epoch.
  • Will error if the year is outside of -9999..=9999.
§Errors
  • Jiff only supports years in the range -9999..=9999. Years outside this range will return a DtErr.
  • If Jiff cannot find the timezone name or if applying the timezone would cause the jiff::Zoned to be outside the -9999..=9999 year range then a DtErr with [DtErrKind::InvalidTimezoneOffset] is returned.
Source§

impl Dt

Source

pub const ZERO: Self

The library’s internal reference epoch.

  • 2000-01-01 12:00:00 TAI.
  • 0 attoseconds
  • The vast majority of conversion functions in the library expect the given Dt to be an attoseconds count since this epoch.
Source

pub const UNIX_EPOCH: Self

UNIX epoch.

  • 1970-01-01 00:00:00 TAI.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • -946_728_000_000_000_000_000_000_000 attoseconds
  • Does not take into account historical UTC offsets from the “rubber time” era.
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const NTP_EPOCH: Self

NTP epoch.

  • 1900-01-01 00:00:00 UTC.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • -3_155_716_800_000_000_000_000_000_000 attoseconds
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const TAI_1977_EPOCH: Self

TT/TCG/TCB/TDB epoch.

  • 1977-01-01 00:00:00 TAI.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • -725_803_200_000_000_000_000_000_000 attoseconds
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const CXC_EPOCH: Self

Chandra X-ray Center (CXC) Time epoch.

  • 1998-01-01 00:00:00 TT.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • -63_115_232_184_000_000_000_000_000_000 attoseconds
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const GPS_EPOCH: Self

GPS/Galileo Experiment (GALEX) Time epoch.

  • 1980-01-06 00:00:00 UTC.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • -630_763_181_000_000_000_000_000_000 attoseconds
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const GALILEO_EPOCH: Self

Galileo System Time (GST) epoch.

  • 1999-08-22 00:00:00 GST.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • -11_447_981_000_000_000_000_000_000 attoseconds
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const BDT_EPOCH: Self

BeiDou Time (BDT) epoch.

  • 2006-01-01 00:00:00 UTC.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • 189_345_633_000_000_000_000_000_000 attoseconds
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const CCSDS_EPOCH: Self

CCSDS epoch (used in CCSDS time codes such as CUC).

  • 1958-01-01 00:00:00 TAI.
  • Stored here on the TAI timescale as an offset from Self::ZERO.
  • -1_325_419_200_000_000_000_000_000_000 attoseconds
  • The library’s epoch for time scales during conversions is 2000-01-01 12:00:00.
Source

pub const MAX: Self

Maximum representable duration.

Source

pub const MIN: Self

Minimum (most negative) representable duration.

Source

pub const SEC_19: Self

19 seconds.

Source

pub const SEC_33: Self

33 seconds.

Source

pub const SEC_37: Self

37 seconds.

Source

pub const ONE_DAY: Self

One days worth of attoseconds.

Source

pub const fn new(attos: i128, scale: Scale, target: Scale) -> Dt

Creates a new Dt from a total number of attoseconds since the librarys epoch 2000-01-01 12:00:00 TAI.

Does not perform any time scale conversions.

§Examples
use deep_time::{Dt, Scale};

// current scale TAI, target scale UTC
let a = Dt::new(0, Scale::TAI, Scale::UTC);

// equivalent to direct construction
let b = Dt { attos: 0, scale: Scale::TAI, target: Scale::UTC };

assert_eq!(a, b);
Source

pub const fn new_sec(sec: i128, scale: Scale, target: Scale) -> Dt

Creates a new Dt from a total number of seconds since the librarys epoch 2000-01-01 12:00:00 TAI.

Does not perform any time scale conversions.

Source

pub const fn new_f(sec: Real, scale: Scale, target: Scale) -> Dt

Creates a new Dt from a total number of seconds as a float since the librarys epoch 2000-01-01 12:00:00 TAI.

  • Does not perform any time scale conversions.
  • Fractional seconds represented by any decimals.
Source

pub const fn span(attos: i128) -> Dt

Creates a new Dt from a total number of attoseconds (signed i128) without performing any time scale conversions.

  • This is an easy way to create a duration.
  • The returned Dt has its scale and target fields set to Scale::TAI.
Source

pub const fn span_f(sec: Real) -> Dt

Creates a Dt from a floating-point number of seconds without performing any time scale conversions.

  • This is an easy way to create a duration or a seconds count that doesn’t include any time scale conversions, just holds the seconds count as is.
  • The returned Dt has its scale and target fields set to Scale::TAI.
Source

pub fn from_sec_and_ufrac(sec: i64, attos: u64, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a seconds and attoseconds count such that would be returned from the functions Dt::to_sec64 and Dt::to_sec_ufrac.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.
  • The sec should be from the epoch TAI 2000-01-01 12:00:00.

This function performs a time scale conversion from the given scale to TAI, if you don’t want any time scale conversion to take place then either use Scale::TAI as an arg or use any of the following constructors:

Source

pub fn from_sec_and_attos(sec: i64, attos: u64, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a seconds and attoseconds count such that would be returned from the functions Dt::to_sec64 and Dt::to_sec_frac.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.
  • The sec should be from the epoch TAI 2000-01-01 12:00:00.

This function performs a time scale conversion from the given scale to TAI, if you don’t want any time scale conversion to take place then either use Scale::TAI as an arg or use any of the following constructors:

Source

pub const fn from_attos(attos: i128, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total attoseconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.

This function performs a time scale conversion from the given scale to TAI, if you don’t want any time scale conversion to take place then either use Scale::TAI as an arg or use any of the following constructors:

Source

pub const fn from_attos_with_target( attos: i128, scale: Scale, target: Scale, ) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total attoseconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.

This function performs a time scale conversion from the given scale to TAI, if you don’t want any time scale conversion to take place then either use Scale::TAI as an arg or use any of the following constructors:

Source

pub const fn from_tai_sec(sec: i128) -> Dt

Creates a new Dt from a total number of seconds (signed i128) without performing any time scale conversions.

Source

pub const fn from_sec(sec: i128, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total seconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.

This function performs a time scale conversion from the given scale to TAI, if you don’t want any time scale conversion to take place then either use Scale::TAI as an arg or use any of the following constructors:

Source

pub const fn from_ms(ms: i128, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total milliseconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.
Source

pub const fn from_us(us: i128, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total microseconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.
Source

pub const fn from_ns(ns: i128, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total nanoseconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.
Source

pub const fn from_ps(ps: i128, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total picoseconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.
Source

pub const fn from_fs(fs: i128, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Requires a total femtoseconds value.
  • The value should be from the epoch TAI 2000-01-01 12:00:00.
  • The returned object’s scale field is set to TAI and its target field is set to the given scale arg.
Source

pub const fn from_min(m: i64, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

Convenience wrapper around Dt::from_sec.

Source

pub const fn from_hr(h: i64, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

Convenience wrapper around Dt::from_sec.

Source

pub const fn from_hms( hr: i64, min: i64, sec: i64, ms: i128, us: i128, ns: i128, scale: Scale, ) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Params are hours, minutes, seconds, milliseconds, microseconds, and nanoseconds.
  • All values are essentially optional (you can use 0 for ones you want to leave out).
  • Negative values are handled.
  • Uses saturating arithmetic.
Source

pub const fn from_days(d: i64, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Convenience wrapper around Dt::from_sec.
  • Uses 86400 seconds per day in the calculation.
Source

pub const fn from_wk(wk: i64, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Convenience wrapper around Dt::from_sec.
  • Uses 604800 seconds per week in the calculation.
Source

pub const fn from_yr(yr: i64, scale: Scale) -> Dt

Returns a Dt on the TAI time scale, after having been converted to TAI from the given scale.

  • Convenience wrapper around Dt::from_sec.
  • Uses 31_557_600 in the calculation.
Source

pub const fn ago(self, scale: Scale) -> Dt

Returns a Dt that is this duration ago from the given scale.

Source

pub const fn from_now(self, scale: Scale) -> Dt

Returns a Dt that is this duration from now in the given scale.

Source

pub const fn neg(self) -> Dt

Returns the negation of this Dt.

Source

pub const fn abs(self) -> Dt

Returns the positive of this Dt.

Source

pub const fn from_sec_f(sec: Real, scale: Scale) -> Dt

Creates a Dt from a floating-point number of seconds.

  • Assumes the value is on the given scale.
  • Converts the values to TAI from the given scale.
  • The returned Dt is on the TAI time scale.
Source

pub const fn sec_f_to_attos(sec: Real) -> i128

High-precision conversion from Real seconds to total attoseconds (i128).

  • Uses IEEE 754 bit extraction + exact integer multiplication by 5^18.
  • Returns the rounded integer (round-to-nearest, ties away from zero).
Source

pub fn now() -> Dt

Returns the current system time as TAI from 2000-01-01 12:00:00.

This method is only available when the std feature is enabled and the target is not WASM with the js feature.

Source§

impl Dt

Source

pub const fn to_unix(&self) -> Dt

Returns this Dt but as time since the Dt::UNIX_EPOCH on its target time scale.

§Important:
  • The Dt first converts itself and the epoch to the time scale of its target field before doing a raw difference with the epoch.
  • You may need to change the Dt’s target field before calling the function if you need the timestamp to be on a particular time scale, e.g. UTC.
  • This function assumes this Dt is currently from the 2000-01-01 noon epoch, if it’s not then the output will be incorrect.
§Returns
  • A Dt whose attos is how many attoseconds have elapsed since UNIX_EPOCH.
  • The count is on whatever scale sits in this Dt’s target field — for example Scale::UTC if you built it with from_ymd(..., Scale::UTC, ...). The result’s scale and target are both set to that same value.
§Examples
use deep_time::{Dt, Scale};

// because from_ymd() with Scale::UTC sets the returned
// Dt's target field to Scale::UTC, we do not need to use
// .target() prior to calling to_unix() in order to get
// a utc unix timestamp
let dt = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);
let unix = dt.to_unix();

assert_eq!(
    unix.to_sec(),
    946728000,
    "unix sec for 2000-01-01 12:00:00 UTC is wrong, got: {}, expected: 946728000",
    unix.to_sec()
);

let dt2 = Dt::from_unix(unix);

assert_eq!(
    dt.to_attos(), dt2.to_attos(),
    "round trip to Dt got wrong attos, old: {}, new: {}",
    dt.to_attos(), dt2.to_attos()
);

let ymd = dt2.to_ymd();
assert_eq!(ymd.yr(), 2000_i64);
assert_eq!(ymd.mo(), 1);
assert_eq!(ymd.day(), 1);
assert_eq!(ymd.hr(), 12);
assert_eq!(ymd.min(), 0);
assert_eq!(ymd.sec(), 0);
assert_eq!(ymd.attos(), 0);
§See also
Examples found in repository?
examples/readme.rs (line 85)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn from_unix(unix: Dt) -> Dt

Creates a TAI Dt from a Dt that is attoseconds since Dt::UNIX_EPOCH.

This is the inverse of Dt::to_unix.

§Important:
  • unix must be a Dt whose attos is how many attoseconds have elapsed since UNIX_EPOCH — typically the return value of Dt::to_unix. The input’s scale field says which time scale that count is on — if it is Scale::UTC, the count is treated as UTC and converted to TAI (leap seconds included).
  • Dt::UNIX_EPOCH is converted to that same scale before the sum.
§Returns

A TAI Dt for the reconstructed instant. Its attos is no longer a count since UNIX_EPOCH — it is attoseconds since the library epoch (2000-01-01 noon TAI). Its target field is taken from unix.

§Examples
use deep_time::{Dt, Scale};

let dt = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);
let unix = dt.to_unix();
let roundtrip = Dt::from_unix(unix);

assert_eq!(roundtrip, dt);
§From an external POSIX unix seconds count
use deep_time::{Dt, Scale};

// 2012-08-08 15:30:00 → 1344439800.000000 s
let unix = 1344439800_i128;

// use Dt::new to avoid time scale conversions on the
// seconds count, other functions can do the same thing
// but this way lets us easily set the time scale fields
// in one go
let unix_dt = Dt::new_sec(unix, Scale::UTC, Scale::UTC);

let dt = Dt::from_unix(unix_dt);

let ymd = dt.to_ymd();
assert_eq!(ymd.yr(), 2012);
assert_eq!(ymd.mo(), 8);
assert_eq!(ymd.day(), 8);
assert_eq!(ymd.hr(), 15);
assert_eq!(ymd.min(), 30);
assert_eq!(ymd.sec(), 0);
assert_eq!(ymd.attos(), 0);
§See also
Source

pub const fn to_ntp(&self) -> Dt

Returns this Dt but as time since the Dt::NTP_EPOCH on its target time scale.

§Important:
  • The Dt first converts itself and the epoch to the time scale of its target field before doing a raw difference with the epoch.
  • You may need to change the Dt’s target field before calling the function if you need the timestamp to be on a particular time scale, e.g. UTC.
  • This function assumes this Dt is currently from the 2000-01-01 noon epoch, if it’s not then the output will be incorrect.
§Returns
  • A Dt whose attos is how many attoseconds have elapsed since NTP_EPOCH.
  • The count is on whatever scale sits in this Dt’s target field — for example Scale::UTC if you built it with from_ymd(..., Scale::UTC, ...). The result’s scale and target are both set to that same value.
§Examples
use deep_time::{Dt, Scale};

// 2698012800
let dt = Dt::from_ymd(1985, 7, 1, Scale::TAI, 0, 0, 0, 0);
let ntp = dt.to_ntp();

assert_eq!(
    ntp.to_attos(), Dt::sec_to_attos(2698012800_i128),
    "ntp sec for 1985 is wrong, got: {}, expected: {}",
    ntp.to_attos(), Dt::sec_to_attos(2698012800_i128)
);

let dt2 = Dt::from_ntp(ntp);

assert_eq!(
    dt.to_attos(), dt2.to_attos(),
    "round trip to Dt got wrong sec, old: {}, new: {}",
    dt.to_attos(), dt2.to_attos()
);

let ymd = dt2.to_ymd();
assert_eq!(ymd.yr(), 1985_i64);
assert_eq!(ymd.mo(), 7);
assert_eq!(ymd.day(), 1);
assert_eq!(ymd.hr(), 0);
assert_eq!(ymd.min(), 0);
assert_eq!(ymd.sec(), 0);
assert_eq!(ymd.attos(), 0);
§See also
Source

pub const fn from_ntp(ntp: Dt) -> Dt

Creates a TAI Dt from a Dt that is attoseconds since Dt::NTP_EPOCH.

This is the inverse of Dt::to_ntp.

§Important:
  • ntp must be a Dt whose attos is how many attoseconds have elapsed since NTP_EPOCH — typically the return value of Dt::to_ntp The input’s scale field says which time scale that count is on — if it is Scale::UTC, the count is treated as UTC and converted to TAI (leap seconds included).
  • Dt::NTP_EPOCH is converted to that same scale before the sum.
§Returns

A TAI Dt for the reconstructed instant. Its attos is no longer a count since NTP_EPOCH — it is attoseconds since the library epoch (2000-01-01 noon TAI). Its target field is taken from ntp.

§Examples
use deep_time::{Dt, Scale};

let dt = Dt::from_ymd(1985, 7, 1, Scale::TAI, 0, 0, 0, 0);
let ntp = dt.to_ntp();
let roundtrip = Dt::from_ntp(ntp);

assert_eq!(roundtrip, dt);
§See also
Source

pub const fn to_gps(&self) -> Dt

Returns this Dt but as time since the Dt::GPS_EPOCH on its target time scale.

§Important:
  • The Dt first converts itself and the epoch to the time scale of its target field before doing a raw difference with the epoch.
  • You may need to change the Dt’s target field before calling the function if you need the timestamp to be on a particular time scale, e.g. .target(Scale::GPS).
  • This function assumes this Dt is currently from the 2000-01-01 noon epoch, if it’s not then the output will be incorrect.
§Returns
  • A Dt whose attos is how many attoseconds have elapsed since GPS_EPOCH.
  • The count is on whatever scale sits in this Dt’s target field — for example Scale::GPS after .target(Scale::GPS). The result’s scale and target are both set to that same value.
§See also
§Implementation

convert_epoch is true. If we did not convert the epoch, we would not get seconds since the GPS epoch; we would get seconds since something else.

Dt::from_ymd / Dt::to_ymd do the opposite: if they converted the epoch too, the difference would cancel out. See to_ymd.

Source

pub const fn from_gps(elapsed: Dt) -> Dt

Creates a TAI Dt from a Dt that is attoseconds since Dt::GPS_EPOCH.

This is the inverse of Dt::to_gps.

§Important:
  • elapsed must be a Dt whose attos is how many attoseconds have elapsed since GPS_EPOCH — typically the return value of Dt::to_gps The input’s scale field says which time scale that count is on — if it is Scale::UTC, the count is treated as UTC and converted to TAI (leap seconds included).
  • Dt::GPS_EPOCH is converted to that same scale before the sum.
§Returns

A TAI Dt for the reconstructed instant. Its attos is no longer a count since GPS_EPOCH — it is attoseconds since the library epoch (2000-01-01 noon TAI). Its target field is taken from elapsed.

§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::TAI, 12, 0, 0, 0);
let gps = x.target(Scale::GPS).to_gps();
let roundtrip = Dt::from_gps(gps);

assert_eq!(roundtrip, x);
§See also
Source

pub const fn to_gps_wk_and_tow(&self) -> (i64, Dt)

Returns the GPS week number and Time of Week (TOW) for this instant.

Elapsed time since Dt::GPS_EPOCH is computed by Dt::to_gps — on this Dt’s target time scale — and then split into whole weeks plus a remainder.

This is the inverse of Dt::from_gps_wk_and_tow.

§Important:
  • Uses Dt::to_gps internally: this Dt and Dt::GPS_EPOCH are both converted to the target time scale before differencing.
  • You may need to change the Dt’s target field before calling if you need week/TOW on a particular time scale, e.g. Scale::GPS.
  • This function assumes this Dt is currently from the 2000-01-01 noon epoch, if it’s not then the output will be incorrect.
§Returns

A (week, tow) pair:

  • week (i64): whole weeks in the elapsed time from Dt::to_gps. Week 0 starts at the GPS epoch (1980-01-06). Before that date the elapsed time is negative and div_euclid yields a negative week — this is not a broadcast GPS week number, just how the split is defined. A plain integer is enough here; it is only a week count, not a duration in attoseconds.
  • tow (Dt): seconds-within-the-week as attoseconds in 0 .. 604800. Its scale and target are set to this Dt’s target so Dt::from_gps_wk_and_tow knows which time scale the pair belongs to. tow is a Dt rather than a bare integer so sub-second precision and scale are preserved together; the week number alone cannot carry either. div_euclid / rem_euclid are used (not truncating /) so TOW stays non-negative even when the elapsed time is negative.
§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::TAI, 12, 0, 0, 0);
let g = x.to_gps_wk_and_tow();
let z = Dt::from_gps_wk_and_tow(g.0, g.1);
assert_eq!(x, z);

// for conventional GPS-time week/TOW, set target first:
let g = x.target(Scale::GPS).to_gps_wk_and_tow();
§See also
Source

pub const fn from_gps_wk_and_tow(wk: i64, tow: Dt) -> Dt

Creates a Dt from a GPS week number and Time of Week (TOW).

Recombines week and tow into elapsed time since Dt::GPS_EPOCH, then passes that to Dt::from_gps.

This is the inverse of Dt::to_gps_wk_and_tow.

§Important:
  • Uses Dt::from_gps internally: the elapsed time is interpreted on the tow Dt’s scale / target fields, and Dt::GPS_EPOCH is converted to that same scale before the sum.
  • Pass back the tow from Dt::to_gps_wk_and_tow unchanged if you want a round trip.
§Returns

A TAI Dt for the reconstructed instant. Its target field is taken from tow.

tow must be a Dt (not a bare second count) because Dt::from_gps needs both the within-week attoseconds and the scale / target that say which time scale week and tow were expressed on. The week number is multiplied back into attoseconds (week * 604800 seconds); only tow carries the scale and sub-week precision needed for the round trip.

tow should be in 0 .. 604800 seconds, as returned by Dt::to_gps_wk_and_tow. Negative week values only arise from dates before 1980-01-06 (see that function).

§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::TAI, 12, 0, 0, 0);
let g = x.to_gps_wk_and_tow();
let z = Dt::from_gps_wk_and_tow(g.0, g.1);
assert_eq!(x, z);
§See also
Source

pub const fn to_gps_day_of_wk(&self) -> u8

Returns the day of the GPS week (0 = Sunday, 1 = Monday, …, 6 = Saturday).

This value is computed directly from the GPS Time of Week and is independent of the Gregorian calendar or civil time.

Source

pub const fn to_cxcsec(&self) -> Dt

Returns this Dt but as time since the Dt::CXC_EPOCH on its target time scale.

§Important:
  • The Dt first converts itself and the epoch to the time scale of its target field before doing a raw difference with the epoch.
  • You may need to change the Dt’s target field before calling the function if you need the timestamp to be on a particular time scale, e.g. UTC.
  • This function assumes this Dt is currently from the 2000-01-01 noon epoch, if it’s not then the output will be incorrect.
§Returns
  • A Dt whose attos is how many attoseconds have elapsed since CXC_EPOCH.
  • The count is on whatever scale sits in this Dt’s target field — for example Scale::TT after .target(Scale::TT). The result’s scale and target are both set to that same value.
§Examples
use deep_time::{Dt, Scale};

let cxc = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0)
    .target(Scale::TT)
    .to_cxcsec()
    .to_sec_f();

// cxcsec 694224032.184 (matches Astropy)
assert_eq!(cxc, 694224032.184);
§See also
Source

pub const fn from_cxcsec(elapsed: Dt) -> Dt

Creates a TAI Dt from a Dt that is attoseconds since Dt::CXC_EPOCH.

This is the inverse of Dt::to_cxcsec.

§Important:
  • elapsed must be a Dt whose attos is how many attoseconds have elapsed since CXC_EPOCH — typically the return value of Dt::to_cxcsec The input’s scale field says which time scale that count is on — if it is Scale::UTC, the count is treated as UTC and converted to TAI (leap seconds included).
  • Dt::CXC_EPOCH is converted to that same scale before the sum.
§Returns

A TAI Dt for the reconstructed instant. Its attos is no longer a count since CXC_EPOCH — it is attoseconds since the library epoch (2000-01-01 noon TAI). Its target field is taken from elapsed.

§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0);
let cxc = x.target(Scale::TT).to_cxcsec();
let roundtrip = Dt::from_cxcsec(cxc);

assert_eq!(roundtrip, x);
§See also
Source

pub const fn from_cxcsec_f(sec: Real, on: Scale) -> Dt

Convenience wrapper around Self::from_cxcsec for a bare floating-point second count.

Wraps sec in a Dt via Dt::sec_f_to_attos and Dt::new, then passes it to Self::from_cxcsec. Unlike Dt::from_sec_f, this does not convert the count to TAI up front — Self::from_cxcsec performs that conversion once, from on.

§Parameters
  • sec — seconds elapsed since CXC_EPOCH.
  • on — which Scale the count is measured in (for example Scale::TT or Scale::UTC). This becomes the wrapped Dt’s scale; Self::from_cxcsec then uses it when turning the elapsed count into an absolute TAI instant (including leap-second handling where applicable). Same role as the scale field on the Dt you would hand to Self::from_cxcsec directly.
§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0);
let cxc = x.target(Scale::TT).to_cxcsec().to_sec_f();
let roundtrip = Dt::from_cxcsec_f(cxc, Scale::TT);

assert_eq!(roundtrip.to_cxcsec().to_sec_f(), cxc);
§See also
Source

pub const fn to_galexsec(&self) -> Dt

Returns the elapsed time since the GALEX epoch as a Dt expressed in this object’s current target scale.

This method can match Astropy’s Time.galexsec format. To match Astropy output, set .target(Scale::UTC) (or the appropriate scale) before calling.

The GALEX epoch is Self::GPS_EPOCH (same epoch used by GPS time).

§Important:
  • The Dt first converts itself and the Dt::GPS_EPOCH to the time scale of its target field before doing a raw difference with the epoch.
  • This function assumes this Dt is currently from the 2000-01-01 noon epoch, if it’s not then the output will be incorrect.
§Returns
  • A Dt whose attos is how many attoseconds have elapsed since GPS_EPOCH.
  • The count is on whatever scale sits in this Dt’s target field — for example Scale::UTC after .target(Scale::UTC). The result’s scale and target are both set to that same value.
§Examples
use deep_time::{Dt, Scale};

let galexsec = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0)
    .target(Scale::UTC)
    .to_galexsec()
    .to_sec_f();

assert_eq!(galexsec, 1261871963.0);
§See also
Source

pub const fn from_galexsec(elapsed: Dt) -> Dt

Creates a TAI Dt from a Dt that is attoseconds since Dt::GPS_EPOCH.

This is the inverse of Dt::to_galexsec. GALEX seconds use the same epoch as GPS time.

§Important:
  • elapsed must be a Dt whose attos is how many attoseconds have elapsed since GPS_EPOCH — typically the return value of Dt::to_galexsec The input’s scale field says which time scale that count is on — if it is Scale::UTC, the count is treated as UTC and converted to TAI (leap seconds included).
  • Dt::GPS_EPOCH is converted to that same scale before the sum.
§Returns

A TAI Dt for the reconstructed instant. Its attos is no longer a count since GPS_EPOCH — it is attoseconds since the library epoch (2000-01-01 noon TAI). Its target field is taken from elapsed.

§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0);
let galex = x.target(Scale::UTC).to_galexsec();
let roundtrip = Dt::from_galexsec(galex);

assert_eq!(roundtrip, x);
§See also
Source

pub const fn from_galexsec_f(sec: Real, on: Scale) -> Dt

Convenience wrapper around Self::from_galexsec for a bare floating-point second count.

Wraps sec in a Dt via Dt::sec_f_to_attos and Dt::new, then passes it to Self::from_galexsec. Unlike Dt::from_sec_f, this does not convert the count to TAI up front — Self::from_galexsec performs that conversion once, from on.

§Parameters
  • sec — seconds elapsed since GPS_EPOCH.
  • on — which Scale the count is measured in (for example Scale::UTC or Scale::TT). This becomes the wrapped Dt’s scale; Self::from_galexsec then uses it when turning the elapsed count into an absolute TAI instant (including leap-second handling where applicable). Same role as the scale field on the Dt you would hand to Self::from_galexsec directly.
§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0);
let galex = x.target(Scale::UTC).to_galexsec().to_sec_f();
let roundtrip = Dt::from_galexsec_f(galex, Scale::UTC);

assert_eq!(roundtrip, x);
§See also
Source

pub const fn to_jyear(&self) -> Real

Returns the Julian epoch year (JYEAR) for this instant.

Julian years are defined as exactly 365.25 days of 86400 SI seconds. This is the system used for J2000.0 and many astronomical calculations.

This is not the same as Self::to_decimalyear, which uses the actual length of the specific Gregorian year.

This is the inverse of Self::from_jyear.

§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0);
assert_eq!(x.to_jyear(), 2019.9986310746065);
Source

pub const fn from_jyear(jyear: Real, scale: Scale) -> Dt

Inverse of Self::to_jyear.

Source

pub const fn to_byear(&self) -> Real

Returns the Besselian epoch year (BYEAR) for this instant.

Besselian years are an older astronomical convention based on a tropical year length of approximately 365.242198781 days.

This is the inverse of Self::from_byear.

§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0);
assert!((x.to_byear() - 2020.000335739628).abs() < 1e-12);
Source

pub const fn from_byear(byear: Real, scale: Scale) -> Dt

Inverse of Self::to_byear.

Source

pub fn to_decimalyear(&self) -> Real

Returns the decimal year (Gregorian calendar year + fraction of the year).

This is the direct equivalent of Astropy’s Time.decimalyear:

  • Uses the actual length of the specific Gregorian year (365 or 366 days, plus any leap seconds on UTC/UtcSpice/etc.).
  • Scale-aware (TAI, TT, UTC, TDB, etc.), converts to this Dt’s target time scale before producing an output.
  • Exact integer arithmetic for the year boundaries, then a high-precision to_sec_f division (lossy only at the final Real step, same as Astropy).
§Examples
use deep_time::{Dt, Scale};

let x = Dt::from_ymd(2020, 1, 1, Scale::TAI, 0, 0, 0, 0);
assert_eq!(x.to_decimalyear(), 2020.0);

// Also works for negative years
let y = Dt::from_ymd(-2000, 1, 1, Scale::TAI, 0, 0, 0, 0);
assert_eq!(y.to_decimalyear(), -2000.0);
Source§

impl Dt

Source

pub const fn to_scale_and_diff(&self, epoch: Dt, convert_epoch: bool) -> Dt

Converts this instant to its internally stored target scale and returns the signed difference from the given epoch.

This is a low-level const fn used internally by higher-level conversion methods such as to_ymd.

§Arguments
  • epoch — The reference epoch (e.g. Dt::UNIX_EPOCH) from which the difference is calculated.
  • convert_epoch — Whether to also convert the provided epoch to this Dt’s target time scale.
§Returns

A Dt representing the signed difference (seconds + attoseconds) between this instant (after conversion to to) and the provided epoch.

It can be interpreted as a timestamp when epoch is something like Dt::UNIX_EPOCH (e.g. for generating Unix timestamps via .to_ms() or .to_sec()).

§See also
§Examples
use deep_time::{Dt, Scale};

let dt = Dt::from_ymd(2024, 6, 15, Scale::UTC, 12, 0, 0, 0);
let diff = dt.to_scale_and_diff(Dt::UNIX_EPOCH, true);

// diff can be used as a Unix timestamp offset
let unix_ms = diff.to_ms();
assert!(unix_ms > 1_700_000_000_000);
Source

pub const fn from_diff_and_scale(diff: Dt, epoch: Dt, convert_epoch: bool) -> Dt

Creates a TAI Dt by adding a difference to an epoch and interpreting the result on the given time scale.

This is the inverse counterpart to Dt::to_scale_and_diff and is used by Dt::from_ymd and related constructors.

§Arguments
  • diff — The signed difference (as a Dt) to add to the epoch.
  • epoch — The reference epoch (commonly Dt::UNIX_EPOCH or Dt::ZERO).
  • current — The time scale on which diff + epoch should be interpreted.
§Returns

A Dt on the TAI scale representing the absolute instant epoch + diff when interpreted on current.

§Notes
  • The input diff is treated as being on the current scale.
  • The final result is always converted to TAI (the internal canonical representation).
§See also
§Examples
use deep_time::{Dt, Scale};

let diff = Dt::from_tai_sec(1_718_467_200); // ~2024-06-15
let dt = Dt::from_diff_and_scale(diff, Dt::UNIX_EPOCH, true);

let ymd = dt.to_ymd();
assert_eq!(ymd.yr(), 2024);
assert_eq!(ymd.mo(), 6);
assert_eq!(ymd.day(), 15);
Source

pub const fn to_tai(&self) -> Dt

Converts the internal attos to be on the TAI time Scale.

use deep_time::{Dt, Scale};

let tai = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);
let tt = tai.to(Scale::TT);

assert_eq!(tt.scale, Scale::TT);

let roundtrip = tt.to_tai();

assert_eq!(tai.scale, Scale::TAI);
assert_eq!(roundtrip, tai);

See Dt::to for more info.

Examples found in repository?
examples/readme.rs (line 72)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn convert(&self, new: Scale) -> Dt

Converts directly to new Scale, without first converting to TAI.

Warning:

  • This function should really only be used if the Dt is on the TAI time scale, or if you really know what you’re doing.
  • For the normal time scale conversion function see Dt::to which first converts to TAI before converting to the target scale.
Source

pub const fn to(&self, new: Scale) -> Dt

Converts this instant to another time scale, going via TAI.

Essentially when converting TT to TDB the internal process goes like TT -> TAI -> TDB. It uses the Dts scale field to determine what scale to convert from to TAI, and then the new arg dictates the new time scale.

  • Assumes that this Dt is measuring time since 2000-01-01 12:00:00.
  • It is not necessary to do this if you just want to use such functions as Dt::to_ymd as these internally convert to the scale of the object’s target field before output.
  • If a TAI Dt was created using Dt::from_ymd and the datetime had 60 seconds, converting to UTC would lose that info. To round trip a 60 second UTC datetime you need only set the Dt::target Scale to UTC and then call the desired output function, such as Dt::to_ymd.
  • The internal attos field changes to be on the new time scale.
  • The Dts target field is ignored and left unchanged.
  • The Dts scale field is changed to the new Scale.
§Returns
  • A Dt representing the same physical instant but on the new scale.
  • The returned objects scale field has been changed to new.

If current == new, this method returns *self without any computation.

§See also
§Examples
use deep_time::{Dt, Scale};

let tai = Dt::from_ymd(2024, 6, 15, Scale::UTC, 12, 0, 0, 0);
let tt = tai.to(Scale::TT);
let tdb = tt.to(Scale::TDB);

// the objects have kept the scale they originally came
// from using their `target` field, which was UTC in the
// from_ymd function
assert_eq!(tdb.target, Scale::UTC);

let roundtrip = tdb.to(Scale::TAI);

let ymd = roundtrip.to_ymd();

assert_eq!(ymd.yr(), 2024);
assert_eq!(ymd.mo(), 6);
assert_eq!(ymd.day(), 15);
assert_eq!(ymd.hr(), 12);
assert_eq!(ymd.min(), 0);
assert_eq!(ymd.sec(), 0);
assert_eq!(ymd.attos(), 0);
Examples found in repository?
examples/readme.rs (line 66)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn convert_using_drift(self, reference: Dt, drift: Drift) -> Dt

Converts this instant to any other Scale while applying an exact quadratic relativistic or clock-drift correction defined by a Drift model relative to a reference instant.

Source

pub const fn convert_back_using_drift(self, reference: Dt, drift: Drift) -> Dt

Performs the inverse conversion of Dt::convert_using_drift, recovering the original proper time on the source clock scale.

A fixed-point iteration (at most 16 steps) is used to solve the implicit equation. For the common case of a pure constant offset the function returns immediately without iteration.

Source§

impl Dt

Source

pub fn from_ccsds_ccs(input: &[u8]) -> Result<Dt, DtErr>

Parses a CCSDS CCS (Calendar Segmented Time Code) binary time code into a Dt.

Implements CCSDS 301.0-B-4 §3.4 (Level 1 only).

§P-field (exactly 1 byte)
  • Bit 7: Extension flag → must be 0 (we reject extensions)
  • Bits 6-4: Code ID = 101
  • Bit 3: Calendar type (0 = Month/Day, 1 = Day-of-Year)
  • Bits 2-0: Number of subsecond BCD octets (06)
§T-field (BCD, big-endian)
  • 2 bytes: Year (0001–9999)
  • 2 bytes: Month+Day (01-12,01-31) or Day-of-Year (001–366)
  • 3 bytes: Hour (00-23), Minute (00-59), Second (00-60)
  • 0–6 bytes: Fractional seconds (exactly 2 decimal digits per byte)

Epoch: 1958-01-01 00:00:00 UTC (identical to CDS).

§See also
Source

pub fn from_ccsds_cuc(input: &[u8]) -> Result<Dt, DtErr>

Parses a CCSDS C (CUC – Unsegmented Time Code) binary time code directly into a Dt.

Implements CCSDS 301.0-B-4 §3.2 (Level 1), including full support for the extended 2-byte P-field defined in Issue 4.

§Supported formats (Level 1 only)
  • 1-byte or 2-byte P-field (further extension beyond 2 bytes is rejected).
  • Code ID must be 001 (1958-01-01 TAI epoch).
  • Coarse time: 1–7 octets total.
  • Fractional time: 0–10 octets total.
§P-field decoding
  • First octet (P1):

    • Bit 7: Extension flag (1 = second P-field octet follows)
    • Bits 6-4: Code ID (must be 001)
    • Bits 3-2: Coarse time octets minus 1 (0–3 → 1–4 octets)
    • Bits 1-0: Fractional time octets (0–3)
  • Second octet (P2, when extension flag is set):

    • Bit 7: Further-extension flag (must be 0; 3+-byte P-fields are rejected)
    • Bits 6-5: Additional coarse octets (0–3)
    • Bits 4-2: Additional fractional octets (0–7)
    • Bits 1-0: Reserved (ignored)
§T-field
  • Coarse time is interpreted as seconds since 1958-01-01 00:00:00 TAI.
  • Fractional time is converted to attoseconds using exact integer arithmetic (value × 10¹⁸ / 2^(8·n_frac)).
§Returns

A Dt with both scale and target set to [Scale::TAI].

§Errors
  • [DtErrKind::Incomplete] if input is empty.
  • [DtErrKind::InvalidItem] if the Code ID is not 001.
  • [DtErrKind::InvalidInput] if the input is too short to contain the declared extended P-field, or if the “further extension” flag (bit 7 of the second P-field octet) is set.
  • [DtErrKind::InvalidSyntax] if the declared coarse + fractional field lengths make the T-field longer than the remaining input bytes.

Errors from Parts::finish and Parts::to_dt may also propagate.

Source

pub fn from_ccsds_cds(input: &[u8]) -> Result<Dt, DtErr>

Parses a CCSDS D (CDS – Day Segmented Time Code) binary time code directly into a Dt.

Implements CCSDS 301.0-B-4 §3.3 (Level 1).

§Supported formats (Level 1 only)
  • 1-byte or 2-byte P-field.
  • Code ID must be 100 and the Epoch bit must be 0 (1958-01-01 UTC epoch).
  • Day count: 2 or 3 bytes.
  • Milliseconds since midnight: always 4 bytes.
  • Sub-millisecond field (bits 1-0 of P-field):
    • 00: no fractional field
    • 01: 2 bytes (microseconds within the millisecond, 0–65535)
    • 10: 4 bytes (fractional part of the millisecond as 2⁻³²)
    • 11: rejected (unsupported)
§P-field bit layout (first octet)
  • Bit 7: Extension flag (1 = second P-field octet follows)
  • Bits 6-4: Code ID (must be 100)
  • Bit 3: Epoch (must be 0 for Level 1 / 1958 epoch)
  • Bit 2: Day count size (0 = 2 bytes, 1 = 3 bytes)
  • Bits 1-0: Sub-millisecond code (see above)
§T-field
  • Day count is days since 1958-01-01 00:00:00 UTC.
  • Milliseconds since midnight are always present (4 bytes).
  • Sub-millisecond data (if present) is converted to attoseconds with exact integer scaling.
§Leap-second handling

Correctly supports leap seconds. When the millisecond-of-day value represents 23:59:60 (i.e. millis_of_day >= 86_400_000), sec is set to 60 in the resulting time.

§Returns

A Dt with scale = TAI and target = UTC.

§Errors
  • [DtErrKind::Incomplete] if input is empty.
  • [DtErrKind::InvalidInput] if the P-field indicates an extended second octet but the input is too short to contain it.
  • [DtErrKind::InvalidItem] if the Code ID is not 100, the Epoch bit is set (non-Level-1 epoch), or the sub-millisecond code is 0b11.
  • [DtErrKind::InvalidSyntax] if the declared field lengths make the T-field longer than the remaining input bytes.

Errors from Parts::finish and Parts::to_dt may also propagate.

Source

pub fn from_ccsds_bin(input: &[u8]) -> Result<Dt, DtErr>

Auto-detects and parses a CCSDS binary time code (CUC, CDS, or CCS) based on the Code ID in the first P-field byte, then returns a Dt.

Convenience wrapper around Parts::from_ccsds_bin.

Dispatches as follows:

For stricter control or when the format is known in advance, prefer calling the specific from_ccsds_* function directly.

§Returns

A Dt whose scale and target depend on the detected format:

  • CUC (001): scale = TAI, target = TAI
  • CDS (100): scale = TAI, target = UTC
  • CCS (101): depends on the CCS parser implementation
§Errors
  • [DtErrKind::Incomplete] if input is empty.
  • [DtErrKind::InvalidItem] if the Code ID is not one of the three recognized Level 1 values (001, 100, or 101).

Any error returned by the dispatched parser is also propagated.

Source§

impl Dt

Source

pub fn parse(s: &str) -> Result<Self, DtErr>

Parses a date/time string.

  • When the parse feature is enabled: uses the smart auto-parser.
  • When the parse feature is disabled: falls back to CCSDS format.
§Examples
use deep_time::{Dt, Scale};

// uses impl FromStr but Dt::parse provides the same functionality
let x: Dt = "2000-01-01 12:00:00".parse().unwrap();

let ymd = x.to_ymd();
assert_eq!(ymd.yr(), 2000);
assert_eq!(ymd.mo(), 1);
assert_eq!(ymd.day(), 1);
assert_eq!(ymd.hr(), 12);
assert_eq!(ymd.min(), 0);
assert_eq!(ymd.sec(), 0);
assert_eq!(ymd.attos(), 0);
§See also
Source

pub fn from_str( s: &str, fmt: &str, inp_can_end_before_fmt: bool, fmt_can_end_before_inp: bool, allow_partial_date: bool, ) -> Result<Dt, DtErr>

Parser equivalent to strptime with a provided format string.

The returned Dt will be on the TAI time scale, converted from whatever optional time scale (%L) was provided in the input. If no time scale was provided then it’s converted from UTC -> TAI.

The result is that the Dt’s scale field will be TAI and its target field will be whatever time scale it was converted from (UTC if no time scale was in the input).

§Parameters
  • fmt: The format string containing % directives.
  • input: The string to parse.
  • inp_can_end_before_fmt: If true, the input may end before the format string is fully consumed (extra format specifiers are ignored).
  • fmt_can_end_before_inp: If true, the format may end before the input is fully consumed (trailing characters in the input are allowed).
  • allow_partial_date: If true, a missing month/day will be defaulted to 1 instead of returning an [Incomplete] error.
§Supported Directives

The format string supports literal characters and the following % directives. Literal non-whitespace characters must match the input exactly. Whitespace in the format matches (and consumes) any leading ASCII whitespace in the input.

Many directives accept format extensions right after %:

  • Flags: - (no pad), _ (space pad), 0 (zero pad), ^/# (treated as default)
  • Width: 1–3 digits (affects numeric field width / padding expectations)
  • Colons (only for %z): :, ::, ::: to control offset format
§Year / Century / Unbounded
  • %Y — Four-digit year (e.g. 2024). Supports sign, flags, and width.
  • %y — Two-digit year (0099; 0068 → 2000+, 6999 → 1900s).
  • %C — Century (0099).
  • %G — Four-digit ISO week-based year.
  • %g — Two-digit ISO week-based year (same century rule as %y).
  • %*Unbounded year (arbitrary length, supports negative years). Library extension.
§Month
  • %m — Month number 0112.
  • %B — Full English month name (e.g. January).
  • %b, %h — Abbreviated English month name (3 letters, e.g. Jan).
§Day
  • %d, %e — Day of month 0131 (%e allows space padding).
  • %j — Day of year 001366.
§Time of day
  • %H, %k — Hour 0023 (24-hour clock; %k allows space padding).
  • %I, %l — Hour 0112 (12-hour clock).
  • %M — Minute 0059.
  • %S — Second 0060 (leap second allowed).
  • %f, %N — Fractional seconds (up to 18 digits = attoseconds). Width controls precision (%3f = ms, %6N = µs, %9f = ns, etc.). Both accept an optional leading . in the input.
  • %.f, %.N, %.3f, %.6N, … — Same fractional parsing, but the dot before the fraction is optional in the input (consumes literal . if present).
  • %P, %pAM/PM indicator (case-insensitive).
§Weekday / Week number
  • %A — Full English weekday name (e.g. Monday).
  • %a — Abbreviated English weekday name (3 letters, e.g. Mon).
  • %u — Weekday number Monday=1 … Sunday=7.
  • %w — Weekday number Sunday=0 … Saturday=6.
  • %U — Week number (Sunday-first week), 0053.
  • %W — Week number (Monday-first week), 0053.
  • %V — ISO 8601 week number 0153.
§Timezone, Offset & Scale
  • %z — Timezone offset. Colon count selects format:
    • %z±HH[MM[SS]] (minutes/seconds optional)
    • %:z±HH:MM (minutes required)
    • %::z±HH:MM:SS (seconds optional)
    • %:::z±HH:MM:SS (more flexible)
  • %Q — IANA timezone name (e.g. America/New_York) or numeric offset (if input starts with +/-). Library extension.
  • %L — Time scale abbreviation (e.g. TAI, UTC, GPS). See Scale. Library extension.
§Shortcuts (compound directives)
  • %F — Equivalent to %Y-%m-%d (ISO date).
  • %D — Equivalent to %m/%d/%y (US date).
  • %T — Equivalent to %H:%M:%S.
  • %R — Equivalent to %H:%M.
§Other
  • %% — Literal % character.
  • %s — Unix timestamp (seconds since 1970-01-01 00:00 UTC, can be negative). This directive greedily consumes any fractional seconds.
  • %J — Seconds since 2000-01-01 12:00 TAI (J2000.0 noon epoch), can be negative. This directive greedily consumes any fractional seconds.
  • %n, %t — Any whitespace (consumes it from input).
§Unsupported / Unknown
§Errors

Returns a DtErr if either the strptime-style parser or the subsequent conversion from Parts to Dt fails.

§Format string errors
§Input parsing errors
§Post-processing / validation errors
§Conversion to Dt errors

These errors can occur after successful parsing, inside Parts::to_dt, when constructing the final Dt:

  • DtErrKind::InvalidInput — Invalid YMD date, or unable to construct a Julian date from the parsed components (e.g. conflicting or insufficient fields).
  • DtErrKind::OutOfRange — Day-of-year out of range for the year, ISO week 53 does not exist in the target year, week number > 53, or hour outside 1..=12 when an AM/PM indicator was also parsed.
  • DtErrKind::InvalidItem — ISO week 53 was requested for a year that does not contain 53 ISO weeks.
  • DtErrKind::Incomplete — No year (neither %Y/%y nor %G/%g) was present in the input at all.
  • DtErrKind::InvalidTimezoneOffset — Invalid IANA timezone name (only possible when the jiff-tz feature is enabled).
  • DtErrKind::InvalidNumber — Internal timestamp conversion error (rare; only occurs with the jiff-tz feature).
  • DtErrKind::InvalidBytes — A non-UTC IANA timezone name was used but the jiff-tz feature is not enabled.

Because DtErrKind is #[non_exhaustive], additional variants may appear in the future. You can match on the variants you care about and use a wildcard arm for the rest.

The concrete error kind is available via DtErr::kind() (or by iterating DtErr::trace() if the error was chained with context higher up the call stack).

Source

pub fn parse_fmt(strptime_fmt: &str) -> Result<StrPTimeFmt, DtErr>

Parses and validates a strptime-style format string into a reusable StrPTimeFmt.

The format is checked once for syntax errors and unsupported directives, then stored in a compact fixed-size buffer. The resulting StrPTimeFmt is Copy, cheap to clone, and can be used repeatedly with StrPTimeFmt::to_dt and StrPTimeFmt::to_str without re-validating.

Only ASCII formats up to 256 bytes are accepted.

§Parameters
  • strptime_fmt: The format string using % directives (e.g. "%Y-%m-%d %H:%M:%S", "%F %T", "%Y-%m-%dT%H:%M:%S%.3fZ").
§Errors

Returns DtErr if the format is:

  • Longer than 256 bytes
  • Not valid ASCII
  • Contains unknown, unsupported, or malformed directives
Source

pub fn from_str_iso(input: &str) -> Result<Self, DtErr>

Generalized ISO / CCSDS ASCII Time Code parser (A or B variant).

  • Parses e.g. +2000-01-01T17:00:00 -0500 [America/New_York] TAI.
  • Only supports ASCII characters.
  • If a time is included then some kind of date-time separator e.g. T is required.
  • Supports both calendar (%Y-%m-%d) and day-of-year (%Y-%j) formats.
  • Treats years digits literally as shown, for example 99-01-01 would be the year 99 AD not 1999.
  • Supported optional components:
    • Time components after a date e.g. T12:00:00.
    • Offset after time components or directly after the date e.g. +0200 or 2023-01-01+05:00.
    • Timezone name, requires square brackets and requires jiff-tz feature, after time or offset e.g. T12:00:00 [America/New_York].
    • Library time scale right on the end of the input, e.g. TAI.
  • This function is considerably faster than all other string parsing methods if your date-time string is in the supported formats.
Examples found in repository?
examples/readme.rs (line 39)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn from_str_sec_f(s: &str, scale: Option<Scale>) -> Option<Dt>

Parses a decimal seconds string (with optional fractional part) as seconds since Dt::ZERO on the chosen time scale.

  • If scale is Some(s), the value is interpreted on scale s.
  • If scale is None, a trailing scale abbreviation (e.g. GPS, TAI, UTC) is parsed from the input using the same logic as Dt::from_str_iso. If none is found, TAI is used.

Leading non-numeric characters are skipped until a number start is found (+, -, ., or digit).

  • Fractional seconds are limited to the first 18 digits (attosecond precision); extra digits are truncated.
  • Oversized integer parts saturate instead of failing.
  • Inputs longer than [STRTIME_SIZE] are rejected.
  • Returns None only for completely unparseable input (empty, sign/dot only, no digits after skipping, etc.).
§Examples
use deep_time::{Dt, Scale};

let d = Dt::from_str_sec_f("1700000000.123456789012345678", Some(Scale::TAI)).unwrap();
assert_eq!(d.to_sec64(), 1700000000);

// Leading junk is skipped
let d = Dt::from_str_sec_f("ts= -0.00123 suffix", Some(Scale::TAI)).unwrap();
assert!(d.to_attos() < 0);

// Pure negative fraction
let d = Dt::from_str_sec_f("-.5", Some(Scale::TT)).unwrap();
assert!(d.to_attos() < 0);

// Scale parsed from trailing abbreviation when passing None
let d = Dt::from_str_sec_f("42.75 GPS", None).unwrap();
assert_eq!(d.target, Scale::GPS);

// 1 attosecond
let d = Dt::from_str_sec_f("0.000000000000000001", Some(Scale::TAI)).unwrap();
assert_eq!(d.to_attos() % 1_000_000_000_000_000_000, 1);
Source

pub fn from_iso_duration(s: &str) -> Result<Dt, DtErr>

Parses an ISO 8601 duration string into a Dt representing a pure time interval.

Supports the full PnYnMnDTnHnMnS format (case-insensitive), including:

  • Optional leading + or - sign
  • P / p prefix (required)
  • Optional T / t separator between date and time parts
  • Weeks (W / w)
  • Fractional seconds with up to 18 digits of precision (attosecond resolution)

The returned Dt is a duration (signed interval) on the TAI scale. It can be added to/subtracted from other Dt values, multiplied/divided, rounded, etc.

§Not Reference-Time Aware

This parser is not reference-time aware. Calendar units (Y, M) are converted to a fixed number of seconds using standard average lengths rather than being resolved against a specific date. This makes parsing fast and allocation-free, but P1M always represents exactly the same duration regardless of context.

§Parameters
  • s: The ISO 8601 duration string (e.g. "P1Y2M3DT4H5M6.123456789012345678S", "-PT30M", "P7W", "+P1DT12H").
§Errors

Returns DtErr for:

  • Empty string
  • Missing P prefix
  • Invalid syntax (T with no time part, multiple Ts, etc.)
  • Unknown unit designators
  • Numeric values that are out of range or cause overflow
Source

pub fn from_str_media_duration(input: &str) -> Result<Dt, DtErr>

Parses a media-style duration string.

Accepts formats like:

  • "0:45", "9:41"
  • "1:23:45"
  • "1:07:54:30"
  • "-1:23:45"
§See also
Source§

impl Dt

Source

pub const fn unix_sec_to_ymd(unix_sec: i64) -> (i64, u8, u8)

Converts a Unix timestamp (seconds since 1970-01-01 00:00:00) to a proleptic Gregorian date (year, month, day).

Source

pub const fn to_ymd(&self) -> YmdHms

Returns the calendar date and time for this instant.

Converts to this Dts target time scale using the internal current scale before producing a result.

§Returns

A YmdHms containing:

  • yr, mo, day — calendar date
  • hr (0–23), min (0–59), sec (0–60)
  • attos — fractional second in attoseconds (0 ≤ attos < 10¹⁸)
  • scale — time scale that the object is in
§Leap-second handling

If the Dt’s target time scale is one of the scales that use leap seconds (UTC, UtcSpice, or UtcHist) and the instant falls exactly on a leap second, (requires the objects current time scale not be UTC) the returned sec will be 60. In every other case sec is in the range 0..=59.

The implementation converts internally to TAI before checking leap-second status.

§Examples
use deep_time::{Dt, Scale};

// `from_ymd` always returns a TAI instant
let dt = Dt::from_ymd(2024, 6, 15, Scale::UTC, 12, 30, 45, 0);
let ymd = dt.to_ymd();

assert_eq!(ymd.yr(), 2024);
assert_eq!(ymd.mo(), 6);
assert_eq!(ymd.day(), 15);
assert_eq!(ymd.hr(), 12);
assert_eq!(ymd.min(), 30);
assert_eq!(ymd.sec(), 45);
assert!(ymd.attos() == 0);
§See also
§Implementation

convert_epoch is false. If we converted the epoch too, the difference would cancel out — we would not find the same instant on a different scale.

Dt::to_gps etc. do the opposite: if we did not convert the epoch there, we would not get seconds since the GPS epoch; we would get seconds since something else.

Examples found in repository?
examples/readme.rs (line 76)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn from_ymd( yr: i64, mo: u8, day: u8, scale: Scale, hr: u8, min: u8, sec: u8, attos: u64, ) -> Dt

Creates a TAI Dt from a proleptic gregorian date which is assumed to be on the provided time scale.

  • Equivalent to converting to TAI for the provided date. This means for example that when using Scale::UTC leap seconds are potentially added to the returned Dt.
  • The returned Dt will have its scale field set to TAI and its target field set to the provided time scale argument from this fn. This makes functions such as Dt::to_ymd more ergonomic.

All input components are clamped to their valid ranges:

  • mo → 1..=12 1 based
  • day → 1..=31 1 based
  • hr → 0..=23 0 based
  • min → 0..=59 0 based
  • sec → 0..=60 0 based (permits leap seconds)
  • attos → 10¹⁸ 0 based (clamped to under 1 second)
§Examples
use deep_time::{Dt, Lang, Scale};

// library zero is 2000-01-01 noon TAI
let tai = Dt::from_ymd(2000, 1, 1, Scale::TAI, 12, 0, 0, 0);
assert_eq!(tai, Dt::ZERO);

// utc noon
let utc = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);
// output with timezone requires jiff-tz feature
// because from_ymd used Scale::UTC, the output is converted
// back to UTC before being offset by the timezone
let s = utc.to_str_in_tz("%A, %B %d, %Y %H:%M:%S %Q", "America/New_York", Lang::En).unwrap();
assert_eq!(s, "Saturday, January 01, 2000 07:00:00 America/New_York");
§See also
§Implementation

Same as Dt::to_ymdconvert_epoch is false. See that function’s Implementation section.

Examples found in repository?
examples/readme.rs (line 22)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn ymd_to_unix_sec( yr: i64, mo: u8, day: u8, hr: u8, min: u8, sec: u8, ) -> i64

Converts a proleptic Gregorian calendar date+time to a Unix timestamp (seconds since 1970-01-01 00:00:00).

  • Expects 1 based mo and day, and 0 based hr, min, and sec.
  • Does not perform any time scale conversions.
  • Expects pre-clamped values.
Source

pub const fn jd_to_ymd(jd: i64) -> (i64, u8, u8)

Converts a Julian Day Number (JD) to a proleptic Gregorian calendar date.

  • Returns (year, month, day) where month ∈ [1, 12] and day ∈ [1, 31] (standard 1-based Gregorian values).
  • This is the inverse of Dt::ymd_to_jd.
  • Supports the full i64 range, including negative years and year zero.
Source

pub const fn ymd_to_jd(yr: i64, mo: u8, day: u8) -> i64

Computes the Julian Day Number (JD) for a proleptic Gregorian calendar date at noon UT. This is the inverse of [jd_to_ymd].

§Arguments
  • yr - Year (any i64; proleptic Gregorian)
  • mo - Month (1-based: 1 = January, 2 = February, …, 12 = December)
  • day - Day of the month (1-based: 1 = first day of the month)

The algorithm matches the standard astronomical convention used throughout the library (ymd_to_jd(2000, 1, 1) == 2451545).

§Notes
  • This function expects 1 based mo and day. Passing mo = 0 or day = 0 (or other out-of-range values) will produce incorrect results as this function does not perform value clamping.
  • Does not deal with bad inputs like February with 30 days, does not do any clamping. If you need to sanitize a year, month, day input use Dt::clamp_mdhms first.
  • The result is the integer JD corresponding to noon on the given date.
Source

pub const fn ydoy_to_jd(yr: i64, day_of_yr: u16) -> i64

Computes the Julian Day Number from a Gregorian year and ordinal day-of-year.

Source

pub const fn jd_to_wkday(jd: i64) -> u8

Converts a Julian Day Number to the corresponding weekday number (0 = Sunday … 6 = Saturday).

Source

pub const fn iso_wk_to_jd(iso_yr: i64, iso_wk: u8, wkday: Weekday) -> i64

Computes the Julian Day Number from an ISO week date (Monday-based week).

Source

pub const fn wk_sun_to_jd(yr: i64, wk: u8, wkday: Weekday) -> i64

Computes the Julian Day Number from a Sunday-based week-of-year (%U).

Source

pub const fn wk_mon_to_jd(yr: i64, wk: u8, wkday: Weekday) -> i64

Computes the Julian Day Number from a Monday-based week-of-year (%W).

Source

pub const fn is_leap_yr(yr: i64) -> bool

Returns true if the given year is a Gregorian leap year under proleptic rules.

Source

pub const fn is_valid_ymd(yr: i64, mo: u8, day: u8) -> bool

Returns true if the supplied values form a valid proleptic Gregorian calendar date.

Source

pub const fn has_iso_wk_53(yr: i64) -> bool

Returns true if the given Gregorian year contains an ISO week 53.

Source

pub const fn day_of_yr(&self, ymd: Option<(i64, u8, u8)>) -> u16

Returns the ordinal day of the year (1-based).

January 1 is day 1; December 31 is day 365 or 366 (in leap years). Uses the proleptic Gregorian calendar.

Source

pub const fn wk_sun(&self, ymd: Option<(i64, u8, u8)>, doy: Option<u16>) -> u8

Sunday-based week number (%U in strftime).

Range: 0..=53.

  • Week 0 contains the days before the first Sunday of the year.
  • Week 1 begins on the first Sunday of the year.

The optional ymd and doy arguments are performance optimisations (same pattern used throughout the file for day_of_year, to_iso_wk_date, etc.). Pass whichever you already have; the function will use the fastest path.

Source

pub const fn wk_mon(&self, ymd: Option<(i64, u8, u8)>, doy: Option<u16>) -> u8

Monday-based week number (%W in strftime).

Range: 0..=53.

  • Week 0 contains the days before the first Monday of the year.
  • Week 1 begins on the first Monday of the year.

The optional ymd and doy arguments are performance optimisations (same pattern as wk_sun, day_of_yr, to_iso_wk_date, etc.).

Source

pub const fn to_iso_wk_date( &self, ymd: Option<(i64, u8, u8)>, ) -> (i64, u8, Weekday)

Returns the ISO 8601 week date for this Dt.

Returns (iso_year, iso_week, weekday) where:

  • iso_year is the ISO week year (may differ from the Gregorian year near year boundaries),
  • iso_week is the week number in the range 1..=53,
  • weekday is a Weekday value (Monday-based week).

Follows the ISO 8601 standard: weeks start on Monday and week 1 is the week containing January 4.

The optional ymd argument is a performance optimization. If provided, it is used directly; otherwise to_gregorian_ymd is called internally.

Source

pub const fn days_in_month(yr: i64, mo: u8) -> u8

Number of days in a month under proleptic Gregorian rules.

Source

pub const fn clamp_mdhms( yr: i64, mo: u8, day: u8, hr: u8, min: u8, sec: u8, ) -> (u8, u8, u8, u8, u8)

Clamps month, day, hour, minutes, and seconds values. Clamps days to what is correct for that particular propleptic gregorian month.

For example the year 2000 is a leap year, and February in that year has 29 days so the days are clamped to 1-29 in that year, but 1-28 in non-leap years.

Source

pub const fn days_since_1958_to_gregorian( days_since_epoch: i64, ) -> (i64, u8, u8)

Number of days since 1958-01-01 (proleptic Gregorian) → (year, month, day). This is the inverse of Dt::gregorian_to_days_since_1958.

Source

pub const fn gregorian_to_days_since_1958(year: i64, month: u8, day: u8) -> i64

Source§

impl Dt

Source

pub const fn to_jd(&self) -> (i64, u128)

Returns the exact Julian Date of this instant as (integer_days, fractional_attoseconds).

  • The returned JD is expressed in the time scale of this Dt.
  • The fractional part is always in [0, ATTOS_PER_DAY).

For a float value use Self::to_jd_f.

Source

pub const fn to_jd_f(&self) -> Real

Returns the Julian Date of this instant as a floating-point Real.

This is the lossy counterpart to Self::to_jd.

Examples found in repository?
examples/readme.rs (line 93)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn to_mjd(&self) -> (i64, u128)

Returns the exact Modified Julian Date of this instant as (integer_days, fractional_attoseconds).

  • The returned MJD is expressed in the time scale of this Dt.
  • The fractional part is always in [0, ATTOS_PER_DAY).

For a float value use Self::to_mjd_f.

Source

pub const fn to_mjd_f(&self) -> Real

Returns the Modified Julian Date of this instant as a floating-point Real.

This is the lossy counterpart to Self::to_mjd.

Source

pub const fn from_jd(jd_days: i64, frac_attos: u128, on: Scale) -> Dt

Creates a Dt from an exact Julian Date.

This is the inverse of Self::to_jd. For correct round-tripping you must pass the same on: Scale that matches the scale of the original Dt.

Source

pub const fn from_mjd(mjd_days: i64, frac_attos: u128, on: Scale) -> Dt

Creates a Dt from an exact Modified Julian Date.

This is the inverse of Self::to_mjd. For correct round-tripping you must pass the same on: Scale that matches the scale of the original Dt.

Source

pub const fn from_jd_f(jd: Real, on: Scale) -> Dt

Creates a Dt from a float Julian Date.

This is the inverse of Self::to_jd_f. For correct round-tripping you must pass the same on: Scale that matches the scale of the original Dt.

Examples found in repository?
examples/readme.rs (line 95)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub const fn from_mjd_f(mjd: Real, on: Scale) -> Dt

Creates a Dt from a float Modified Julian Date.

This is the inverse of Self::to_mjd_f. For correct round-tripping you must pass the same on: Scale that matches the scale of the original Dt.

Source§

impl Dt

Source

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

Compares the time values represented by two Dts.

  • This comparison is based solely on the raw total attosecond value (self.attos vs other.attos).
  • Does not perform scale conversion and does not compare anything other than the attos field.
Source

pub const fn min(self, other: Self) -> Self

Returns the smaller of two Dts according to the total physical-time order defined by Self::cmp.

This is a const fn and can be used in const contexts.

Source

pub const fn max(self, other: Self) -> Self

Returns the larger of two Dts according to the total physical-time order defined by Self::cmp.

See Self::min for more details.

Source

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

True if both sides have the same total attosecond value.

This is a const fn so it can be used in const contexts.

Source

pub const fn lt(&self, other: &Self) -> bool

Returns true if this Dt is less than the other.

This is a const fn so it can be used in const contexts.

Source

pub const fn gt(&self, other: &Self) -> bool

Returns true if this Dt is greater than the other.

This is a const fn so it can be used in const contexts.

Source

pub const fn le(&self, other: &Self) -> bool

Returns true if this Dt is less than or equal to the other.

This is a const fn so it can be used in const contexts.

Source

pub const fn ge(&self, other: &Self) -> bool

Returns true if this Dt is greater than or equal to the other.

This is a const fn so it can be used in const contexts.

Source§

impl Dt

Source

pub const fn tdb_minus_tt(seconds_since_j2000_tt: Real) -> Real

DE440/LTE440-tuned compact analytical TT–TDB model

Exact 13-term Fourier decomposition from LTE440 (Lu et al. 2025, Table 3)

  • physical VSOP2013 annual term + tiny JPL secular corrections.
Source

pub const fn tai_to_tdb(tai: Dt) -> Dt

Converts a TAI Dt to TDB.

Source

pub const fn tdb_to_tai(tdb: Dt) -> Dt

Converts a TDB Dt to TAI.

Source§

impl Dt

Source

pub const CCSDS_C_AND_D_MAX_SIZE: usize = 32

Maximum size needed for a CCSDS C & D (CUC) binary packet (with extended P-field).

Source

pub const CCSDS_CCS_MAX_SIZE: usize = 14

Maximum size needed for a CCSDS CCS binary packet (P-field + T-field).

Source

pub fn to_ccsds_cuc( &self, n_coarse: u8, n_frac: u8, extension: bool, ) -> Result<([u8; 32], usize), DtErr>

Formats this Dt as a CCSDS C (CUC – Unsegmented Time Code) binary packet.

Fully configurable for round-tripping with Dt::from_ccsds_cuc. Conforms to CCSDS 301.0-B-4 §3.2 (Level 1), including full support for the extended 2-byte P-field.

  • The time is always encoded on the TAI timescale (Code ID 001).
  • The target field of this Dt is ignored.
§Parameters
  • n_coarse: Number of bytes used for the coarse (integer) seconds since the 1958 epoch. Must be in 1..=7. The chosen value must be large enough to represent the full time; otherwise the high-order bytes are silently truncated. For example, a date in the year 2025 requires at least 4 bytes (n_coarse >= 4), while 3 bytes is only sufficient for dates up to roughly mid-1968.
  • n_frac: Number of bytes used for the fractional seconds. Must be in 0..=10. Higher values provide greater sub-second precision, but values of 8 or above may produce reduced accuracy when round-tripping due to internal 128-bit integer limits.
  • extension: If true, forces inclusion of the second P-field octet even when it is not strictly required by the field sizes.
§Epoch

Seconds are counted since 1958-01-01 00:00:00 TAI.

§Returns

(buffer, len) where buffer is a fixed-size array of length [CCSDS_C_AND_D_MAX_SIZE] and len is the number of bytes written.

§Errors
  • DtErrKind::OutOfRange if n_coarse is not in 1..=7, n_frac > 10, or if this instant is before 1958-01-01 00:00:00 TAI (the CUC epoch).
§See also
Source

pub fn to_ccsds_cds( &self, n_day: u8, sub_ms_code: u8, extension: bool, ) -> Result<([u8; 32], usize), DtErr>

Formats this Dt as a CCSDS D (CDS – Day Segmented Time Code) binary packet.

Fully configurable for round-tripping with from_ccsds_cds. Conforms to CCSDS 301.0-B-4 §3.3 (Level 1).

The time is always encoded on the UTC timescale (day count + milliseconds since midnight UTC). Leap-second handling follows the library’s conversion rules.

§Parameters
  • n_day: Number of day-count octets. Must be 2 or 3.
  • sub_ms_code: Sub-millisecond resolution:
    • 0: none
    • 1: 2 bytes (microseconds within the millisecond)
    • 2: 4 bytes (fraction of a millisecond as 2⁻³²)
  • extension: If true, emits the second P-field octet.
§Epoch

Day count is days since 1958-01-01 00:00:00 UTC.

§Returns

(buffer, len) where buffer is a fixed-size array of length [CCSDS_C_AND_D_MAX_SIZE] and len is the number of bytes written.

§Errors
§See also
Source

pub fn to_ccsds_ccs( &self, use_doy: bool, n_subsec: u8, ) -> Result<([u8; 14], usize), DtErr>

Formats this Dt as a CCSDS CCS (Calendar Segmented Time Code) binary packet.

Fully configurable for round-tripping with from_ccsds_ccs. Conforms to CCSDS 301.0-B-4 §3.4 (Level 1 only).

Both CCS variants are UTC-based and use BCD encoding. Leap seconds are supported (second = 60).

§Parameters
  • use_doy: false = Month/Day variant (most common), true = Day-of-Year variant.
  • n_subsec: Number of subsecond BCD octets (06). Each octet holds two decimal digits (so n_subsec = 6 gives up to 12 decimal digits of subsecond precision).
§Year Range

The year must be in the range 1 to 9999 (as defined by the CCSDS standard).

§Returns

(buffer, len) where buffer is a fixed-size array of length [CCSDS_CCS_MAX_SIZE] and len is the number of bytes written.

§Errors
§See also
Source

pub fn to_ccsds_bin(&self) -> Result<([u8; 32], usize), DtErr>

Convenience method that automatically selects the most appropriate CCSDS binary time code based on this Dt’s target time Scale.

  • If the target Scale uses leap seconds then ccsds_cds is chosen.
  • Otherwise ccsds_cuc is chosen.
Source§

impl Dt

Source

pub fn to_iso_duration(&self) -> String

Converts this Dt to an ISO 8601 duration string.

  • Example: “PT1H23M45.6789S”.
  • Requires the alloc feature.
  • Does not do any time scale conversions prior to output.
Source

pub fn to_str(&self, fmt: &str, lang: Lang) -> Result<String, DtErr>

Formats this Dt into a String. Requires the alloc feature.

  • Converts from this Dt’s current time scale to its target time scale before producing the result.
§Examples
use deep_time::{Dt, Lang, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);
let s = x.to_str("%F", Lang::En).unwrap();

println!("{}", s);
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_in_offset( &self, fmt: &str, secs: i32, lang: Lang, ) -> Result<String, DtErr>

Formats this Dt into a String, applying a fixed offset. Requires the "alloc" feature.

  • A copy of the Dt is adjusted by the given secs offset before formatting, and the offset is stored so that %z / %:z format directives will reflect it.
  • No IANA timezone name or abbreviation is set.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
§Examples
use deep_time::{Dt, Lang, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);

// offset of minus one hour
let s = x.to_str_in_offset("%F", -3600, Lang::En).unwrap();

println!("{}", s);
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_in_tz( &self, fmt: &str, tz_name: &str, lang: Lang, ) -> Result<String, DtErr>

Formats this Dt into a string, time adjusted to the given IANA timezone.

Use this method when you want full IANA-aware formatting (%Q, %Z, %z, etc.).

  • A copy of the Dt is adjusted by the offset at the Dt’s time for the given IANA timezone. This is so that the formatter will have:
    • Accurate wall time for the timezone.
    • Correct numeric offset (for %z / %:z).
    • Timezone abbreviation (for %Z). These do not round-trip (the parser does not parse them).
    • Full IANA timezone name (for %Q / %:Q).
  • Converts to the provided timezone, if your Dt is already in the timezone then use the label function instead: Dt::to_str_with_tz_label. This is unlikely to be case because when a date with a timezone is parsed the returned Dt is not in local time. But, label only functions are provided just in case anyway.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
  • Requires the jiff-tz feature for timezone names other than UTC aliases.
§Examples

You can offset an output that wasn’t originally from a zoned input:

use deep_time::{Dt, Lang, Scale};

let x: Dt = "2000-01-01 12:00:00".parse().unwrap();
let s = x.to_str_in_tz("%A, %B %d, %Y %H:%M:%S %Q", "America/New_York", Lang::En).unwrap();
assert_eq!(s, "Saturday, January 01, 2000 07:00:00 America/New_York");

You can also return to a zoned output from a zoned input:

use deep_time::{Dt, Lang, Scale};

let x: Dt = "Saturday, January 01, 2000 07:00:00 America/New_York".parse().unwrap();
let s = x.to_str_in_tz("%A, %B %d, %Y %H:%M:%S %Q", "America/New_York", Lang::En).unwrap();
assert_eq!(s, "Saturday, January 01, 2000 07:00:00 America/New_York");
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Examples found in repository?
examples/readme.rs (line 47)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn to_str_rfc9557(&self, tz_name: &str) -> Result<String, DtErr>

RFC 9557 / Temporal format with IANA timezone name in brackets.

  • Example: "2020-06-15T14:30:00-04:00[America/New_York]".
  • Converts to the provided timezone, if your Dt is already in the timezone then use the label function instead: Dt::to_str_with_tz_label. This is unlikely to be case because when a date with a timezone is parsed the returned Dt is not in local time. But, label only functions are provided just in case anyway.
  • Automatically trims trailing zeros in the fractional part.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Examples found in repository?
examples/readme.rs (line 14)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn to_str_rfc3339(&self) -> String

Returns this instant as an RFC 3339 / ISO 8601 timestamp with a Z suffix.

  • Example: "2024-03-14T15:30:45.123Z"
  • Default = 9 digits (nanoseconds) but automatically trims trailing zeros.
  • If fractional part is zero → no decimal point at all (e.g. ...45Z).
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_rfc3339_nf(&self, max_precision: usize) -> String

Same as Dt::to_str_rfc3339 but with a configurable maximum number of fractional digits (0–18). Trailing zeros are always trimmed.

  • Example: "2024-03-14T15:30:45.123Z"
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_iso8601(&self) -> String

ISO 8601 / RFC 3339 with actual offset (modern +00:00 style).

  • Example: "2025-04-16T14:30:45.123+00:00".
  • Uses colon-separated offset (%:z) instead of forcing Z.
  • Still trims trailing zeros in the fractional part.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Examples found in repository?
examples/readme.rs (line 125)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn to_str_iso8601_basic(&self) -> String

Compact ISO 8601 basic format (no separators).

  • Example: "20250416T143045.123456789Z".
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_iso_week_date(&self) -> String

ISO 8601 week date.

  • Example: "2025-W16-3". (year-week-day)
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_iso_date(&self) -> String

Just the ISO date part (no time).

  • Example: "2025-04-16".
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_iso_time(&self) -> String

Just the time part with fractional seconds (trimmed).

  • Example: "14:30:45.123456789".
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_http(&self, lang: Lang) -> String

HTTP-date format (RFC 7231 / RFC 1123) — always in GMT.

  • Example: "Wed, 16 Apr 2025 14:30:45 GMT".
  • Always outputs in GMT (equivalent to UTC+00:00). Does not apply regional DST rules.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_rfc2822(&self, lang: Lang) -> String

RFC 2822 date format (used in email Date headers).

  • Example: "Wed, 16 Apr 2025 14:30:45 +0000".
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_with_offset_label( &self, fmt: &str, offset: i32, lang: Lang, ) -> Result<String, DtErr>

Formats this Dt into a String, attaching an offset as a label only.

  • The actual datetime components are not shifted or adjusted.
  • The given offset is used only for %z / %:z format directives.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_with_tz_label( &self, fmt: &str, tz_name: &str, lang: Lang, ) -> Result<String, DtErr>

Formats this Dt into a String, attaching a timezone as a label only.

  • The actual datetime components are not shifted or adjusted.
  • The timezone is used to provide correct values for %z, %:z, %Z, %Q, and %:Q.
  • The timezone abbreviation is automatically looked up from tzdata.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
  • Requires the jiff-tz feature for timezone names other than UTC aliases.
§Errors

Returns DtErr if the format string contains invalid specifiers, if the timezone name is invalid, or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source§

impl Dt

Source

pub fn to_str_lite( &self, fmt: &str, lang: Lang, ) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

Formats this Dt into a fixed-size binary string.

  • Converts from this Dt’s current time scale to its target time scale before producing the result.
§Examples
use deep_time::{Dt, Lang, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);
let b = x.to_str_lite("%F", Lang::En).unwrap();
let s = b.as_str();

println!("{}", s);
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_lite_in_offset( &self, fmt: &str, secs: i32, lang: Lang, ) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

Formats this Dt into a fixed-size binary string, applying a fixed UTC offset.

  • A copy of the Dt is adjusted by the given secs offset before formatting, and the offset is stored so that %z / %:z format directives will reflect it.
  • No IANA timezone name or abbreviation is set.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
§Examples
use deep_time::{Dt, Lang, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);

// offset of minus one hour
let b = x.to_str_lite_in_offset("%F", -3600, Lang::En).unwrap();
let s = b.as_str();

println!("{}", s);
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_lite_in_tz( &self, fmt: &str, tz_name: &str, lang: Lang, ) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

Formats this Dt into a fixed-size binary string, time adjusted to the given IANA timezone.

Use this method when you want full IANA-aware formatting (%Q, %Z, %z, etc.).

  • A copy of the Dt is adjusted by the offset at the Dt’s time for the given IANA timezone. This is so that the formatter will have:
    • Accurate wall time for the timezone.
    • Correct numeric offset (for %z / %:z).
    • Timezone abbreviation (for %Z). These do not round-trip.
    • Full IANA timezone name (for %Q / %:Q).
  • Converts to the provided timezone, if your Dt is already in the timezone then use the label function instead: Dt::to_str_lite_with_tz_label. This is unlikely to be case because when a date with a timezone is parsed the returned Dt is not in local time. But, label only functions are provided just in case anyway.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
  • Requires the jiff-tz feature for timezone names other than UTC aliases.
§Examples
use deep_time::{Dt, Lang, Scale};

let x = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);

let b = x.to_str_lite_in_tz("%F", "America/New_York", Lang::En).unwrap();
let s = b.as_str();

println!("{}", s);
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_lite_with_offset_label( &self, fmt: &str, offset: i32, lang: Lang, ) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

Formats this Dt into a LiteStr, attaching an offset as a label only.

  • The actual datetime components are not shifted or adjusted.
  • The given offset is used only for %z / %:z format directives.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
§Errors

Returns DtErr if the format string contains invalid specifiers or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_lite_with_tz_label( &self, fmt: &str, tz_name: &str, lang: Lang, ) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

Formats this Dt into a LiteStr, attaching a timezone as a label only.

  • The actual datetime components are not shifted or adjusted.
  • The timezone is used to provide correct values for %z, %:z, %Z, %Q, and %:Q.
  • The timezone abbreviation is automatically looked up from tzdata.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
  • Requires the jiff-tz feature for timezone names other than UTC aliases.
§Errors

Returns DtErr if the format string contains invalid specifiers, if the timezone name is invalid, or if the internal formatting buffer overflows (extremely unlikely with STRTIME_SIZE).

§See also
Source

pub fn to_str_lite_iso8601(&self) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

ISO 8601 / RFC 3339 with actual offset (modern +00:00 style) as a fixed size no-alloc binary string.

  • Example: "2025-04-16T14:30:45.123+00:00".
  • Uses colon-separated offset (%:z) instead of forcing Z.
  • Trims trailing zeros in the fractional part.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Examples found in repository?
examples/readme.rs (line 40)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source

pub fn to_str_lite_rfc9557( &self, tz_name: &str, ) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

RFC 9557 / Temporal format with IANA timezone name in brackets as a fixed size no-alloc binary string.

  • Example: "2020-06-15T14:30:00-04:00[America/New_York]".
  • Automatically trims trailing zeros in the fractional part.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source

pub fn to_str_lite_http( &self, lang: Lang, ) -> Result<LiteStr<STRTIME_SIZE>, DtErr>

HTTP-date format (RFC 7231 / RFC 1123) — always in GMT as a fixed size no-alloc binary string.

  • Example: "Wed, 16 Apr 2025 14:30:45 GMT".
  • Always outputs in GMT (equivalent to UTC+00:00). Does not apply regional DST rules.
  • Converts from this Dt’s current time scale to its target time scale before producing the result.
Source§

impl Dt

Source

pub fn to_str_media_duration(&self) -> String

Formats the duration using the common media/video player style (e.g. "0:45", "9:41", "1:23:45", "1:07:54:30").

Source

pub fn to_str_lite_media_duration(&self) -> LiteStr<STRTIME_SIZE>

Same as to_media_duration but returns a stack-allocated LiteStr.

Examples found in repository?
examples/readme.rs (line 58)
3fn main() -> Result<(), DtErr> {
4    // ============================================
5    // Parsing
6    // ============================================
7
8    // Smart auto-parsing (multi-language + timezone)
9    let cfg = ParseCfg {
10        lang: Lang::Fr,
11        ..Default::default()
12    };
13    let dt = Dt::from_str_parse("15 août 2024 à 14:30 [Europe/Paris]", &cfg)?;
14    let s = dt.to_str_rfc9557("Europe/Paris")?;
15    assert_eq!("2024-08-15T14:30:00+02:00[Europe/Paris]", s);
16
17    // or with .parse
18    let dt: Dt = "1 jan 2000 07:00 [America/New_York] TAI".parse()?; // noon
19    assert_eq!(Dt::ZERO, dt);
20
21    // Relative dates are also supported
22    let ref_time = Dt::from_ymd(2026, 6, 16, Scale::UTC, 12, 0, 0, 0);
23    let en_cfg = ParseCfg {
24        ref_time: Some(ref_time),
25        ..Default::default()
26    };
27
28    let dt = Dt::from_str_parse("2 days from now at 9am", &en_cfg)?;
29    assert_eq!(dt, Dt::from_ymd(2026, 6, 18, Scale::UTC, 9, 0, 0, 0));
30
31    let dt = Dt::from_str_parse("next Monday at 14:00", &en_cfg)?;
32    assert_eq!(dt, Dt::from_ymd(2026, 6, 22, Scale::UTC, 14, 0, 0, 0));
33
34    // Relative dates use Dt::now if the `std` feature is enabled and no
35    // ref_time is provided in the ParseCfg
36    let _ = Dt::from_str_parse("next Monday at 14:00", &ParseCfg::DEFAULT)?;
37
38    // Fast ISO parsing with time scale and no alloc output
39    let dt = Dt::from_str_iso("2000-01-01T12:00:00 TAI")?;
40    let lite_str: LiteStr<512> = dt.to_str_lite_iso8601()?;
41    assert_eq!("2000-01-01T12:00:00+00:00", lite_str.as_str());
42
43    // ============================================
44    // Formatting
45    // ============================================
46
47    let s = dt.to_str_in_tz("%A, %d %B %Y %I:%M%P", "America/New_York", Lang::En)?;
48    assert_eq!("Saturday, 01 January 2000 07:00am", s);
49
50    let s = dt.to_str_in_tz("%A, %-d de %B de %Y %H:%M", "America/New_York", Lang::Es)?;
51    assert_eq!("Sábado, 1 de enero de 2000 07:00", s);
52
53    // ============================================
54    // Duration parsing
55    // ============================================
56
57    let span: Dt = Dt::from_str_duration("3 days 12 hours", Lang::En)?;
58    let dur = span.to_str_lite_media_duration();
59    assert_eq!("3:12:00:00", dur.to_string());
60
61    // ============================================
62    // Time scale conversions + round-tripping
63    // ============================================
64
65    let dt = Dt::from_ymd(2000, 1, 1, Scale::TAI, 0, 0, 0, 123456789);
66    let tt = dt.to(Scale::TT);
67    let tdb = tt.to(Scale::TDB);
68    let ltc = tdb.to(Scale::LTC);
69    let utc = ltc.to(Scale::UTC);
70    let tcl = utc.to(Scale::TCL);
71    let tcg = tcl.to(Scale::TCG);
72    let tai = tcg.to_tai();
73
74    // round trips work for pretty much everything except UTCHist
75    assert_eq!(dt, tai);
76    let ymd: YmdHms = tai.to_ymd();
77    assert_eq!(ymd.attos(), 123456789);
78
79    // ============================================
80    // Other conversions
81    // ============================================
82
83    // unix
84    let dt = Dt::from_ymd(1970, 1, 1, Scale::UTC, 0, 0, 0, 0);
85    let unix = dt.to_unix().to_sec_f();
86    assert_eq!(unix, 0.0);
87
88    // or to milliseconds
89    let unix: i128 = dt.add_ms(1000).to_unix().to_ms();
90    assert_eq!(unix, 1000);
91
92    // to and from jd
93    let jd = Dt::ZERO.to_jd_f();
94    assert_eq!(2451545.0, jd);
95    let dt = Dt::from_jd_f(jd, Scale::TAI);
96    assert_eq!(0, dt.attos);
97
98    // ============================================
99    // Calendar math
100    // ============================================
101
102    // calendar math and negative year
103    let dt = Dt::from_ymd(-2000, 1, 31, Scale::TAI, 12, 0, 0, 0);
104    let ymd = dt.add_mo(1).to_ymd();
105    assert_eq!(ymd.day(), 29);
106
107    // Timezone-aware calendar math (respects DST transitions, requires jiff-tz feature)
108    let dt = Dt::from_str_iso("2025-03-30T00:30:00Z")?; // Just before London DST start
109
110    // Normal (naive) addition — ignores DST rules
111    let normal = dt.add_hr(1);
112
113    // Timezone-aware addition — correctly handles the transition
114    let aware = dt.add_hr_tz(1, "Europe/London")?;
115
116    println!("Normal: {}", normal.to_str_rfc9557("Europe/London")?);
117    println!("Aware:  {}", aware.to_str_rfc9557("Europe/London")?);
118
119    // ============================================
120    // Leap seconds
121    // ============================================
122
123    // genuine leap second input round trips
124    let dt: Dt = "2015-06-30T23:59:60".parse()?;
125    let s = dt.to_str_iso8601();
126    assert_eq!("2015-06-30T23:59:60+00:00", s);
127
128    Ok(())
129}
Source§

impl Dt

Source

pub fn to_str_ccsds(&self) -> Result<String, DtErr>

Returns this instant as a CCSDS ASCII Time Code (calendar variant A).

  • Example: "2025-04-17T14:30:45.123456789Z"
  • Uses T separator and trailing Z.
  • Fractional seconds are trimmed (no trailing zeros, no dot if zero).
  • Round-trip with Dt::from_str_iso / [Parts::from_str_iso].
Source

pub fn to_str_ccsds_nf(&self, max_precision: usize) -> Result<String, DtErr>

Same as [to_str_ccsds] but lets you control the maximum number of fractional digits (0–18).

Source

pub fn to_ccsds_doy_str(&self) -> Result<String, DtErr>

Returns this instant as a CCSDS ASCII Time Code B (day-of-year variant).

Example: "2025-107T14:30:45.123456789Z"

Source

pub fn to_ccsds_doy_str_nf(&self, max_precision: usize) -> Result<String, DtErr>

Same as [to_ccsds_doy_str] but with configurable fractional precision.

Source§

impl Dt

Source

pub const fn to_msd(&self) -> (i64, u128)

Returns the Mars Sol Date (MSD) as a tuple of integer sols and the fractional part of a sol.

  • The computation follows the canonical NASA GISS / AM2000 formulation and works for any input Scale.
  • Leap seconds are automatically accounted for when converting from UTC.
Source

pub const fn to_mtc(&self) -> Dt

Returns Mars Coordinated Time (MTC) as a Dt representing seconds into the current sol (range [0, one Martian sol)).

Source

pub const fn from_msd(whole_sols: i64, frac_attos: u128) -> Dt

Creates a Dt (in TT) from an Mars Sol Date using full library precision.

Source

pub const fn from_msd_f(msd: Real) -> Dt

Creates a Dt (in TT) from a floating-point Mars Sol Date. Non-exact Real.

Source

pub const fn to_msd_f(&self) -> Real

Returns the Mars Sol Date (MSD) as a floating-point value (matches NASA Mars24 output). Non-exact Real.

Source

pub const fn to_mars_ls(&self) -> Real

Returns the Areocentric Solar Longitude Ls in degrees (range [0, 360)).

Ls is the angular position of the Sun as measured eastward from the Martian vernal equinox in Mars’s orbital plane. It is the standard index of Martian seasonal progression used in all mission planning, science operations, and atmospheric modeling. Due to orbital eccentricity, northern spring + summer last ~381 Earth days while autumn + winter last ~306 Earth days.

  • Ls = 0° → northern vernal equinox (northern spring begins)
  • Ls = 90° → northern summer solstice
  • Ls = 180° → northern autumnal equinox
  • Ls = 270° → northern winter solstice

Reproduces the short-series analytic model (B-1 through B-5) used by the current NASA GISS Mars24 Sunclock algorithm, which is based on Allison & McEwen (2000) with the seven largest planetary perturbations.

Source: NASA Goddard Institute for Space Studies (GISS)
Title: Mars24 Sunclock — Algorithm and Worked Examples
URL: https://www.giss.nasa.gov/tools/mars24/help/algorithm.html
Updated: 2025-01-07

Works for any input Scale because it internally converts to TT.

Source

pub const fn to_mars_lmst(&self, east_longitude_deg: Real) -> Dt

Returns Local Mean Solar Time (LMST) at the given planetocentric east longitude as a Dt representing seconds into the current Martian sol (range [0, one sol)).

LMST is the uniform mean solar time adjusted for longitude.

Longitude is east-positive (standard planetocentric convention, 0–360° E). Internally converts to TT and uses the current NASA GISS Mars24 definition of MST.

Source

pub const fn to_mars_ltst(&self, east_longitude_deg: Real) -> Dt

Returns Local True Solar Time (LTST) at the given planetocentric east longitude as a Dt representing seconds into the current Martian sol (range [0, one sol)).

LTST is the actual sundial time (true solar time) at the location — what a local observer would see on a sundial. It equals LMST plus the Equation of Time.

Longitude is east-positive (standard planetocentric convention, 0–360° E).

Source

pub const fn to_mars_year(&self) -> i64

Returns the integer Mars Year (MY) for this instant.

Mars Year numbering follows the standard Clancy et al. (2000) system:

  • Mars Year 1 begins at the northern vernal equinox (Ls = 0°) on 1955 April 11.
  • Each Mars Year is one tropical year on Mars (686.9725 Earth days).
  • Current missions operate in Mars Year 36–37 (as of 2026).

This is the canonical year count used in all Mars science literature, mission reports, and atmospheric databases.

Source: Clancy et al. (2000), J. Geophys. Res.: Planets 105(E4), 9553–9572; confirmed in NASA GISS Mars24 Technical Notes (2025) and LMD Mars Climate Database.

To get the fractional progress through the year, simply use: self.to_mars_ls(current) / 360.0

Source§

impl Dt

Source

pub fn to_hifitime_epoch(&self) -> Epoch

Converts this Dt to a hifitime::Epoch (TAI scale).

Round-trips with Dt::from_hifitime_epoch.

Source

pub fn from_hifitime_epoch(epoch: Epoch) -> Dt

Creates a Dt from a hifitime::Epoch.

  • The conversion is exact (within hifitime’s nanosecond precision).
  • Uses a runtime-computed offset so it always matches whatever calendar math hifitime uses (including negative years).
Source

pub fn to_hifitime_duration(&self) -> Duration

Converts this Dt to a hifitime::Duration (nanosecond precision).

  • Sub-nanosecond attoseconds are truncated toward zero.
  • The conversion is exact up to the nanosecond (128-bit integer arithmetic).
  • Internally uses hifitime::Duration::from_total_nanoseconds, which automatically normalizes centuries/nanoseconds and saturates at Duration::MAX / Duration::MIN if outside hifitime’s range (±32,768 centuries).
Source

pub fn from_hifitime_duration(dur: Duration) -> Dt

Creates a Dt from a hifitime::Duration (nanosecond precision).

Inverse of Dt::to_hifitime_duration.

Source§

impl Dt

Source

pub fn to_chrono_datetime_utc(&self) -> DateTime<Utc>

Converts this Dt to a chrono::DateTime.

  • Sub-nanosecond attoseconds are truncated toward zero.
  • Saturates at the minimum/maximum representable DateTime<Utc> (roughly years 1678–2262) if the instant is out of range.
Source

pub fn from_chrono_datetime_utc(dt: DateTime<Utc>) -> Dt

Creates a TAI Dt from a chrono::DateTime.

This is the inverse of Dt::to_chrono_datetime_utc.

Source

pub fn from_chrono_duration(dur: Duration) -> Dt

Creates a Dt from a chrono::Duration (nanosecond precision).

Source

pub fn to_chrono_duration(&self) -> Duration

Converts this Dt to a chrono::Duration (nanosecond precision).

  • Sub-nanosecond attoseconds are truncated toward zero.
  • The conversion is fully exact up to the nanosecond (128-bit integer arithmetic).
  • Saturates at chrono::Duration::MIN / chrono::Duration::MAX (roughly ±292 million years) if the value is out of range.
Source§

impl Dt

Source

pub fn to_jiff_timestamp(&self) -> Timestamp

Converts this Dt to a jiff::Timestamp.

Source

pub fn from_jiff_timestamp(ts: Timestamp) -> Dt

Creates a Dt from a jiff::Timestamp.

This is the inverse of Dt::to_jiff_timestamp.

Source

pub fn to_jiff_span(&self) -> Span

Converts this Dt to a jiff::Span (seconds + nanoseconds only).

Source

pub fn to_jiff_signed_duration(&self) -> SignedDuration

Converts this Span to a jiff::SignedDuration (nanosecond precision).

  • Sub-nanosecond attoseconds are truncated toward zero.
  • Supports the entire range of Span (never saturates).
Source

pub fn from_jiff_signed_duration(dur: SignedDuration) -> Dt

Creates a Dt from a jiff::SignedDuration (nanosecond precision).

This is the inverse of Dt::to_jiff_signed_duration.

Source

pub fn from_jiff_span(span: Span) -> Result<Self, DtErr>

Creates a Dt from a jiff::Dt.

This is the inverse of Dt::to_jiff_span.

Source§

impl Dt

Source

pub const fn target(&self, t: Scale) -> Dt

Returns a new Dt with the target field set to the given t arg.

Source

pub const fn with(&self, s: Scale) -> Dt

Returns a new Dt with the scale field sr to the given s arg.

Does NOT perform any time scale conversions.

Source§

impl Dt

Source

pub fn proper_time_from_states<I>( samples: I, characteristic_length_scale: Real, ) -> Result<Self, DtErr>
where I: IntoIterator<Item = (Self, Velocity, Real)>,

Computes the accumulated proper time along a trajectory given a sequence of physical states.

This function accepts samples expressed in terms of directly observable quantities — coordinate time, velocity, and gravitational potential — and integrates the proper time (Δτ) along the path. It is a convenience wrapper around the core [proper_time_from_path] routine.

The integration is performed using the trapezoidal rule applied to the instantaneous proper-time rate between consecutive samples. This approach is standard for high-precision clock modeling in astrodynamics and relativistic timing applications.

A single sample, or multiple samples at identical times, produces a result of zero (no time has elapsed). An empty iterator also returns zero.

§Parameters
  • samples: Iterator yielding (coordinate_time, velocity, gravitational_potential) triples. The coordinate times must be monotonically non-decreasing. It is the caller’s responsibility to supply samples that cover the desired time interval. The function does not validate that the first or last sample exactly matches any particular start or end time.

  • characteristic_length_scale: Controls whether the weak-field or strong-field formulation is used when constructing the local spacetime state.

    Pass 0.0 (the normal choice) for all conventional weak-field work (Earth orbit, GNSS, solar-system navigation, most spacecraft). This produces exactly the classic relativistic clock rate used by JPL, ESA, and GNSS systems, with the Kretschmann scalar set to zero.

    Supply a positive value (in meters) only when you need the library’s intrinsic Planck-scale saturation term. The value should represent the characteristic length scale over which the gravitational field varies significantly at the observer’s location. This is intended for strong-field regimes such as the vicinity of neutron stars or black-hole event horizons.

§Returns

Ok(total_proper_time) — the total proper time (Δτ) that has accumulated for an observer following the trajectory defined by the supplied samples, returned as a Dt.

This value represents the actual time that would have elapsed on a physical clock moving along the path, including all relativistic effects (velocity and gravitational time dilation, plus the Planck-scale saturation term when active). It is not a drift or difference relative to coordinate time. If you need the difference between proper time and coordinate time (Δτ − Δt), use [proper_time_drift_from_states] instead.

Err(DtErr) — if the coordinate times are not monotonically non-decreasing.

Source

pub fn proper_time_drift_from_states<I>( start: Dt, end: Dt, states: I, characteristic_length_scale: Real, ) -> Result<Dt, DtErr>
where I: IntoIterator<Item = (Self, Velocity, Real)>,

Computes the relativistic clock drift (proper time minus coordinate time) over a specific interval.

This returns how much a physical clock has gained or lost time compared with coordinate time between start and end.

  • A positive result means the onboard clock ran fast (it accumulated more proper time than the coordinate interval).
  • A negative result means the onboard clock ran slow (it accumulated less proper time than the coordinate interval).

This is the higher-level function most callers should use when they need the net drift over a well-defined time interval. It internally calls [proper_time_from_states] to integrate proper time along the supplied trajectory and then subtracts the requested coordinate time span.

§Parameters
  • start: Starting coordinate time of the interval.
  • end: Ending coordinate time of the interval.
  • states: Iterator of physical states in the form (coordinate_time, velocity, gravitational_potential). Coordinate times must be monotonically non-decreasing. It is the caller’s responsibility to ensure the provided states cover the time range from start to end. The function integrates proper time over whatever samples are supplied and subtracts the requested coordinate interval (end - start). Exact matching of the first and last state times to start and end is not validated.
  • characteristic_length_scale: Controls the weak-field vs strong-field formulation when constructing local spacetime states (see [proper_time_from_states] for full details). Pass 0.0 for all normal weak-field work (GNSS, Earth orbit, solar-system navigation). Supply a positive length (in meters) only when strong-field Planck-scale saturation effects are required.
§Returns

Ok(drift) — the accumulated drift (Δτ − Δt) as a Dt.

Err(DtErr) — if the coordinate times in states are not monotonically non-decreasing.

Source

pub fn proper_time_from_path<I>(path: I) -> Result<Self, DtErr>
where I: IntoIterator<Item = (Self, Spacetime)>,

Computes accumulated proper time along an arbitrary trajectory.

This is the core integration function of the library. It walks the supplied path segment by segment and applies the trapezoidal rule to the instantaneous proper-time rate at each step.

This approach is commonly used when integrating clock rates along sampled trajectories in astrodynamics and high-precision timing work.

The function enforces that coordinate times are monotonically non-decreasing (equal times are allowed). It performs a single pass with no heap allocation.

§Parameters
  • path: An iterator of (coordinate_time, Spacetime) pairs. Coordinate times must be monotonically non-decreasing.
§Returns

Ok(total_proper_time) — the accumulated proper time (Δτ) as a Dt. Returns ZERO if the iterator is empty (no time elapsed).

Err(DtErr) — if the path contains any decrease in coordinate time (i.e., a later sample has a strictly earlier coordinate time than a previous sample).

Source

pub const fn proper_time_between_constant_rate( self, end: Dt, dtau_dt: Real, ) -> Dt

Computes proper time advance over an interval when the proper-time rate is constant.

This method is intended for trajectory segments where the physical conditions remain unchanged, such as:

  • a fixed ground station,
  • a circular orbit, or
  • a deep-space cruise phase with constant velocity and gravitational potential.

It is mathematically equivalent to integrating a constant rate using the trapezoidal rule in [proper_time_from_path], but is more efficient and makes the caller’s intent explicit.

The method is called on the starting coordinate time (self). It calculates the coordinate time interval to end and multiplies it by the supplied constant rate dtau_dt.

§Parameters
  • end: Ending coordinate time of the interval.
  • dtau_dt: Constant proper-time rate (dimensionless). In relativistic contexts this value is typically slightly less than 1.0. The caller is responsible for providing an appropriate rate (for example, from Drift::proper_time_rate or a precomputed constant).
§Returns

The accumulated proper time advance (Δτ) over the interval as a Dt.

If end occurs before self, the result will be negative.

Source§

impl Dt

Source

pub const fn to_drift_as_constant(self, rate: Dt, accel: Dt) -> Drift

Builds a clock-drift model in which this Dt is treated as the initial fixed time difference between the observer’s proper time and the chosen coordinate time.

In practice you often compute or measure a one-time offset (for example after a clock synchronization or a leap-second jump) and then want to combine it with a steady rate difference and any quadratic change. This method lets you do that directly from a Dt without having to call the more verbose Drift::new.

The other two arguments describe how the difference between the two clocks will evolve:

  • rate — the constant fractional speed difference (how much faster or slower one clock runs compared with the other).
  • accel — how quickly that speed difference itself is changing (for example because the spacecraft is moving through a varying gravitational field).

See Drift and Drift::from_offset_and_rate for more background on why these three numbers are used to model real clocks.

Source

pub const fn to_drift_as_rate(self, constant: Dt, accel: Dt) -> Drift

Builds a clock-drift model in which this Dt supplies the constant fractional rate difference between the observer’s proper time and the chosen coordinate time.

If you have already calculated (or measured) a steady rate offset as a Dt, you can use this method to attach an initial time offset and a quadratic term and obtain a complete Drift polynomial.

Physically, the rate term captures the fact that two clocks that are moving at different velocities or sitting at different gravitational potentials will accumulate a steadily growing time difference. The other two parameters let you also describe any starting bias and any change in that rate over time.

See the documentation on Drift for the meaning of the three coefficients in a relativistic timing context.

Source

pub const fn to_drift_as_accel(self, constant: Dt, rate: Dt) -> Drift

Builds a clock-drift model in which this Dt supplies the quadratic term that describes how the rate difference itself is changing.

Some situations (a spacecraft on a highly elliptical orbit, a clock whose frequency is aging, or a trajectory that takes it through regions of changing gravitational potential) cause the rate at which two clocks diverge to change over time. If you have computed that changing rate as a Dt, this method lets you combine it with an initial offset and a base rate to form a full Drift.

The other two arguments are:

  • constant — any fixed time bias present at the start.
  • rate — the base fractional rate difference that will itself be modified by the quadratic term supplied by self.

See Drift for more explanation of why a quadratic model is used for relativistic clock predictions.

Source§

impl Dt

Source

pub const SHAPIRO_SOLAR: Self

Shapiro gravitational time scale for the Sun (2 G M_☉ / c³).

Recommended value for the Sun when building the bodies slice passed to Observer::shapiro_delay, Observer::shapiro_delay, and related methods.

Source

pub const fn shapiro_from_grav_param(gm: Real) -> Dt

Creates the Shapiro delay scale for an arbitrary central body from its standard gravitational parameter GM (μ) in m³ s⁻².

This produces the coefficient used in the Shapiro gravitational time delay formula. It is the recommended way to create a custom Shapiro scale for planets, stars, or other massive bodies.

The returned value is intended to be used for the bodies parameter when calling Observer::shapiro_delay or Observer::shapiro_delay.

Source

pub const fn to_observer( self, position: Position, velocity: Velocity, grav_potential_m2_s2: Real, characteristic_length_scale: Real, ) -> Observer

Creates an Observer using this time value along with the provided position, velocity, and gravitational information.

An Observer represents a complete snapshot of an observer (spacecraft, ground station, planet, person, etc.) at a specific moment.

It bundles together the time, position, velocity, and local gravitational environment so that relativistic calculations (light time, clock rates, Shapiro delay, etc.) can be performed.

This method is a convenience constructor. It is useful when you already have a Dt (a time value) and want to build an Observer directly from it.

§Parameters
  • position: The observer’s position in meters (typically expressed in a barycentric or heliocentric frame).
  • velocity: The observer’s velocity in meters per second.
  • grav_potential_m2_s2: The total Newtonian gravitational potential (Φ) at the observer’s location, in m²/s². This is usually negative for bound orbits and is the sum of contributions from the Sun and planets.
  • characteristic_length_scale: A length scale (in meters) over which gravity varies significantly at this location. Use 0.0 for normal solar-system and weak-field cases. Only provide a non-zero value when working in strong gravitational fields.
§Examples
use deep_time::{Dt, Position, Spacetime, Velocity};

let bodies = [
    (Position::from_au(0.0, 0.0, 0.0), 1.3271244e20),     // Sun
    (Position::from_au(1.0, 0.0, 0.0), 3.9860044e14),     // Earth
    (Position::from_au(1.00257, 0.0, 0.0), 4.9048695e12), // Moon
];

let position = Position::from_au(1.001, 0.001, 0.0); // e.g. spacecraft, asteroid, etc.

let grav_potential = Spacetime::grav_potential_from_point_masses(
    position,
    bodies.iter().copied(),
);

let t = Dt::span_f(1234.5);

let state = t.to_observer(
    Position::ZERO,
    Velocity::ZERO,
    grav_potential,
    0.0, // normal solar-system use
);
Source§

impl Dt

Source

pub const fn every(self, step: Dt) -> Every

Starts building an evenly-spaced time range.

This method returns an Every builder that can be chained with .until(end) or .up_to(end) to create a TimeRange iterator.

§Examples
use deep_time::{Dt, Scale};

let start = Dt::from_ymd(2000, 1, 1, Scale::UTC, 0, 0, 0, 0);
let end = Dt::from_ymd(2000, 1, 2, Scale::UTC, 0, 0, 0, 0);
let step = Dt::from_hr(1, Scale::TAI);

for timestamp in start.every(step).to_including(end) {
    println!("{:?}", timestamp.to_ymd());
}
Source

pub const fn range(self, end: Dt, step: Dt) -> TimeRange

Creates an exclusive evenly-spaced range from self to end.

Equivalent to self.every(step).up_to(end).

Source

pub const fn every_sec(self) -> Every

Creates a range stepping by whole seconds.

Source

pub const fn every_min(self) -> Every

Creates a range stepping by whole minutes.

Source

pub const fn every_hr(self) -> Every

Creates a range stepping by whole hours.

Source

pub const fn every_day(self) -> Every

Creates a range stepping by whole days.

Source

pub fn next_n(self, n: usize, step: Dt) -> impl ExactSizeIterator<Item = Dt>

Returns the next n points after self (exclusive of self) at the given step.

This is a convenient way to get future points without including the start.

Source

pub fn for_n_steps( self, n: usize, step: Dt, ) -> impl ExactSizeIterator<Item = Dt>

Returns an iterator yielding exactly n evenly spaced points starting from self.

This is a convenient one-liner for the common “next N steps” pattern.

Source§

impl Dt

Source

pub const fn leap_sec(&self, is_utc: bool) -> Option<LeapInfo>

Get the leap seconds info for this instant.

Uses the library’s in-built leap seconds table.

Source

pub const fn leap_sec_using( &self, is_utc: bool, table: &[LeapSec], ) -> Option<LeapInfo>

Get the leap seconds info for this instant with a given table.

Source§

impl Dt

Source

pub fn leap_sec_data_from_file<P: AsRef<Path>>(path: P) -> Result<Vec<LeapSec>>

Load directly from a file (e.g. the official IANA leap-seconds.list).

Format should be the same as the file available at: https://data.iana.org/time-zones/data/leap-seconds.list

For rows that don’t start with # (the data rows) the first column should be the NTP timestamp, the second column (separated by whitespace) should be the offset against TAI in seconds (the number of leap seconds at that point).

e.g.

#NTP TimeDTAI
#
227206080010
228778560011
230368320012
Source§

impl Dt

Source

pub fn leap_sec_data_from_str(s: &str) -> Vec<LeapSec>

Load directly from a str (e.g. the official IANA leap-seconds.list).

Format should be the same as the file available at: https://data.iana.org/time-zones/data/leap-seconds.list

For rows that don’t start with # (the data rows) the first column should be the NTP timestamp, the second column (separated by whitespace) should be the offset against TAI in seconds (the number of leap seconds at that point).

e.g.

#NTP TimeDTAI
#
227206080010
228778560011
230368320012
§Examples
let table = Self::leap_sec_from_str(&file_content_as_str);
Source§

impl Dt

Source

pub fn mjd_to_eop_offset( mjd: Real, op_data: &EopData, ) -> Result<EopOffset, DtErr>

Get an orientation parameters offset in seconds inside a struct: (EopOffset) for a particular Modified Julian Date.

  • On Earth this would be the UT1 time scale.
  • Earth Orientation Parameters data is available from: https://maia.usno.navy.mil/ser7/finals2000A.all
Source

pub fn mjd_to_eop_offset_f(mjd: Real, op_data: &EopData) -> Result<Real, DtErr>

Get an orientation parameters offset in seconds for a particular Modified Julian Date.

  • On Earth this would be the UT1 time scale.
  • Earth Orientation Parameters data is available from: https://maia.usno.navy.mil/ser7/finals2000A.all
Source

pub fn to_eop(&self, op_data: &EopData) -> Result<Self, DtErr>

Offsets a Dt using orientation parameters data.

  • On Earth this would be the UT1 time scale.
  • Earth Orientation Parameters data is available from: https://maia.usno.navy.mil/ser7/finals2000A.all
Source

pub fn from_eop(&self, op_data: &EopData) -> Result<Self, DtErr>

Convert a Dt already offset using orientation parameters data back to whatever it was before.

  • On Earth this would be the UT1 time scale.
  • Earth Orientation Parameters data is available from: https://maia.usno.navy.mil/ser7/finals2000A.all

Trait Implementations§

Source§

impl Add for Dt

Source§

type Output = Dt

The resulting type after applying the + operator.
Source§

fn add(self, rhs: Dt) -> Self

Performs the + operation. Read more
Source§

impl AddAssign for Dt

Source§

fn add_assign(&mut self, rhs: Dt)

Performs the += operation. Read more
Source§

impl Clone for Dt

Source§

fn clone(&self) -> Dt

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Dt

Source§

impl Debug for Dt

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for Dt

Source§

fn default() -> Dt

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Dt

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for Dt

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Div for Dt

Source§

type Output = f64

The resulting type after applying the / operator.
Source§

fn div(self, rhs: Dt) -> Real

Performs the / operation. Read more
Source§

impl Div<f64> for Dt

Source§

type Output = Dt

The resulting type after applying the / operator.
Source§

fn div(self, rhs: f64) -> Self

Performs the / operation. Read more
Source§

impl Div<i64> for Dt

Source§

fn div(self, rhs: i64) -> Self

Divides this Dt by an integer scalar.

Source§

type Output = Dt

The resulting type after applying the / operator.
Source§

impl DivAssign<f64> for Dt

Source§

fn div_assign(&mut self, rhs: f64)

Performs the /= operation. Read more
Source§

impl DivAssign<i64> for Dt

Source§

fn div_assign(&mut self, rhs: i64)

Divides this Dt by an integer scalar in place.

Source§

impl Eq for Dt

Source§

impl From<Dt> for f64

Source§

fn from(dt: Dt) -> f64

Converts to this type from the input type.
Source§

impl FromStr for Dt

Available on crate feature parse only.
Source§

type Err = AnErr<DtErrKind, 2, 49>

The associated error which can be returned from parsing.
Source§

fn from_str(s: &str) -> Result<Self, DtErr>

Parses a string s to return a value of this type. Read more
Source§

impl Hash for Dt

Source§

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

Hashes the canonical TAI representation so that two Dts that are physically equal (after conversion) produce the same hash, regardless of the original [Scale].

1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Mul<Dt> for i64

Source§

type Output = Dt

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Dt) -> Dt

Performs the * operation. Read more
Source§

impl Mul<Dt> for f64

Source§

type Output = Dt

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Dt) -> Dt

Performs the * operation. Read more
Source§

impl Mul<f64> for Dt

Source§

type Output = Dt

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: f64) -> Self

Performs the * operation. Read more
Source§

impl Mul<i64> for Dt

Source§

fn mul(self, rhs: i64) -> Self

Multiplies this Dt by an integer scalar.

Source§

type Output = Dt

The resulting type after applying the * operator.
Source§

impl MulAssign<f64> for Dt

Source§

fn mul_assign(&mut self, rhs: f64)

Performs the *= operation. Read more
Source§

impl MulAssign<i64> for Dt

Source§

fn mul_assign(&mut self, rhs: i64)

Multiplies this Dt by an integer scalar in place.

Source§

impl Neg for Dt

Source§

fn neg(self) -> Self

Negates this Dt (returns the additive inverse).

Source§

type Output = Dt

The resulting type after applying the - operator.
Source§

impl Ord for Dt

Source§

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

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for Dt

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialOrd for Dt

Source§

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

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Serialize for Dt

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Sub for Dt

Source§

type Output = Dt

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Dt) -> Self

Performs the - operation. Read more
Source§

impl SubAssign for Dt

Source§

fn sub_assign(&mut self, rhs: Dt)

Performs the -= operation. Read more
Source§

impl Tsify for Dt

Source§

const DECL: &'static str = "/**\n * **The library\\\'s central time type.** A high-precision instant/duration with attosecond\n * resolution.\n *\n * **Fields:**\n *\n * - pub attos: [`i128`] - total time in attoseconds since the reference epoch\n * (2000-01-01 noon), as a signed integer. Negative values represent times\n * before the epoch.\n * - pub scale: [`Scale`] - the current time scale of the object.\n * - pub target: [`Scale`] - a target time scale used by many output functions such as\n * [`Dt::to_ymd`](../struct.Dt.html#method.to_ymd) and\n * [`Dt::to_unix`](../struct.Dt.html#method.to_unix). The functions convert to the\n * `target` time scale before producing an output.\n *\n * **Notes:**\n *\n * - In theory it supports a range of roughly \u{b1}5.39 trillion years but many of the to and\n * from functions cap at i64 seconds, which can mean a range of \u{b1}292 billion years in practice.\n * Additionally, when parsing dates with a timezone the Rust library `jiff` is used which has\n * a limit of `-9999 - 9999` years.\n * - Implements `Copy` and `Clone`. Optional derives for `serde` and `tsify` are available\n * behind the corresponding features.\n * - A wide range of math is available for this type, including basic calendar aware math and,\n * with the `jiff-tz` feature enabled, timezone and DST aware math. **Behavior greatly\n * differs between functions.**\n *\n * ## Reference epoch and scales\n *\n * - The librarys epoch for nearly all functionality such as the conversion functions is\n * **2000-01-01 noon**. See also: [`Scale`](../enum.Scale.html).\n * - Leap-second handling follows the chosen `Scale` (UTC, UtcSpice, UtcHist).\n *\n * ## See also (non-exhaustive list)\n *\n * ### From and to calendar dates\n *\n * - [`Dt::from_ymd`](../struct.Dt.html#method.from_ymd)\n * - [`Dt::to_ymd`](../struct.Dt.html#method.to_ymd)\n *\n * ### From and to str and bytes\n *\n * Some of these require the alloc feature, they\\\'re marked with *\n *\n * - [`Dt::from_str_parse`](../struct.Dt.html#method.from_str_parse)*\n * - [`Dt::from_str_iso`](../struct.Dt.html#method.from_str_iso)\n * - [`Dt::parse`](../struct.Dt.html#method.parse)\n * - [`Dt::from_str`](../struct.Dt.html#method.from_str)\n * - [`Dt::to_str`](../struct.Dt.html#method.to_str)*\n * - [`Dt::to_str_in_offset`](../struct.Dt.html#method.to_str_in_offset)*\n * - [`Dt::to_str_in_tz`](../struct.Dt.html#method.to_str_in_tz)*\n * - [`Dt::to_str_iso8601`](../struct.Dt.html#method.to_str_iso8601)*\n * - [`Dt::to_str_lite`](../struct.Dt.html#method.to_str_lite)\n * - [`Dt::to_str_lite_in_offset`](../struct.Dt.html#method.to_str_lite_in_offset)\n * - [`Dt::to_str_lite_in_tz`](../struct.Dt.html#method.to_str_lite_in_tz)\n *\n * ### From and to julian dates\n *\n * - [`Dt::from_jd_f`](../struct.Dt.html#method.from_jd_f)\n * - [`Dt::from_mjd_f`](../struct.Dt.html#method.from_mjd_f)\n * - [`Dt::to_jd_f`](../struct.Dt.html#method.to_jd_f)\n * - [`Dt::to_mjd_f`](../struct.Dt.html#method.to_mjd_f)\n * - [`Dt::ymd_to_jd`](../struct.Dt.html#method.ymd_to_jd)\n * - [`Dt::jd_to_ymd`](../struct.Dt.html#method.jd_to_ymd)\n *\n * ### Conversions, time scales etc.\n *\n * - [`Dt::target`](../struct.Dt.html#method.target)\n * - [`Dt::to`](../struct.Dt.html#method.to)\n * - [`Dt::convert`](../struct.Dt.html#method.convert)\n * - [`Dt::to_tai`](../struct.Dt.html#method.to_tai)\n * - [`Dt::from_sec`](../struct.Dt.html#method.from_sec)\n * - [`Dt::to_sec64`](../struct.Dt.html#method.to_sec64)\n * - [`Dt::from_attos`](../struct.Dt.html#method.from_attos)\n * - [`Dt::convert_internal`](../struct.Dt.html#method.convert_internal)\n * - [`Dt::to_unix`](../struct.Dt.html#method.to_unix)\n * - [`Dt::to_ntp`](../struct.Dt.html#method.to_ntp)\n * - [`Dt::to_gps_wk_and_tow`](../struct.Dt.html#method.to_gps_wk_and_tow)\n *\n * ### Conversions from and to types from other libraries\n *\n * - [`Dt::to_hifitime_epoch`](../struct.Dt.html#method.to_hifitime_epoch)\n * - [`Dt::to_jiff_timestamp`](../struct.Dt.html#method.to_jiff_timestamp)\n * - [`Dt::to_chrono_datetime_utc`](../struct.Dt.html#method.to_chrono_datetime_utc)\n * - [`Dt::from_hifitime_epoch`](../struct.Dt.html#method.from_hifitime_epoch)\n * - [`Dt::from_jiff_timestamp`](../struct.Dt.html#method.from_jiff_timestamp)\n * - [`Dt::from_chrono_datetime_utc`](../struct.Dt.html#method.from_chrono_datetime_utc)\n *\n * ## Examples\n *\n * ### Parsing a date\n *\n * ```rust\n * use deep_time::{Dt, Scale};\n *\n * // uses impl FromStr but Dt::parse provides the same functionality\n * let x: Dt = \\\"2000-01-01 12:00:00\\\".parse().unwrap();\n *\n * let ymd = x.to_ymd();\n * assert_eq!(ymd.yr(), 2000);\n * assert_eq!(ymd.mo(), 1);\n * assert_eq!(ymd.day(), 1);\n * assert_eq!(ymd.hr(), 12);\n * assert_eq!(ymd.min(), 0);\n * assert_eq!(ymd.sec(), 0);\n * assert_eq!(ymd.attos(), 0);\n * ```\n *\n * ### Outputting a date to string / bytes\n *\n * ```rust\n * # #[cfg(all(feature = \\\"jiff-tz\\\", feature = \\\"parse\\\"))]\n * # {\n * use deep_time::{Dt, Lang, Scale};\n *\n * let x: Dt = \\\"2000-01-01 12:00:00\\\".parse().unwrap();\n *\n * let s = x\n * .to_str_in_tz(\\\"%A, %B %d, %Y %H:%M:%S %Q\\\", \\\"America/New_York\\\", Lang::En)\n * .unwrap();\n * let b = x\n * .to_str_lite_in_tz(\\\"%A, %B %d, %Y %H:%M:%S %Q\\\", \\\"America/New_York\\\", Lang::En)\n * .unwrap();\n *\n * assert_eq!(s, \\\"Saturday, January 01, 2000 07:00:00 America/New_York\\\");\n * assert_eq!(b.as_str(), \\\"Saturday, January 01, 2000 07:00:00 America/New_York\\\");\n * # }\n * ```\n *\n * ### Creating a unix timestamp in milliseconds\n *\n * ```rust\n * use deep_time::{Dt, Scale};\n *\n * // this fn converts from UTC and creates a TAI Dt\n * let dt = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);\n *\n * // dt is internally TAI but has a UTC tag\n * let unix_ms = dt.to_unix().to_ms();\n *\n * // unix timestamp in ms for 2000-01-01 noon UTC\n * assert_eq!(unix_ms, 946728000000);\n * ```\n *\n * ### Converting time scales\n *\n * Many functions such as\n * [`Dt::to_ymd`](../struct.Dt.html#method.to_ymd) will convert to\n * `TAI` from the [`Dt`]s current `scale` then to the [`Dt`]s `target`\n * [`Scale`] prior to producing an output.\n *\n * So you don\\\'t necessarily have to convert time scales prior to using\n * many of the output functions. You just have to change the `target`\n * time scale.\n *\n * #### Using the target field\n *\n * ```rust\n * use deep_time::{Dt, Lang, Scale};\n *\n * // Leap seconds were added to the secounds count\n * // This Dt has attos that are now on the TAI timescale\n * let dt = Dt::from_ymd(2025, 1, 1, Scale::UTC, 0, 0, 0, 0);\n *\n * // The internal target is currently UTC so we don\\\'t need to do\n * // anything to output back to UTC and round trip\n * let bytes = dt.to_str_lite(\\\"%d %m %Y %H:%M:%S\\\", Lang::En).unwrap();\n *\n * assert_eq!(bytes.as_str(), \\\"01 01 2025 00:00:00\\\");\n *\n * // Perhaps we want to make a GPS timestamp out of our Dt\n * // If we want it to be on the GPS time scale we have to set the\n * // target prior to calling to_gps()\n * let gps = dt.target(Scale::GPS).to_gps().to_sec_f();\n * ```\n *\n * #### Converting the internal attos to a new time scale\n *\n * ```rust\n * use deep_time::{Dt, Scale};\n *\n * // this fn converts from UTC and creates a TAI Dt\n * let dt = Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 0);\n *\n * // to tdb\n * let tdb = dt.to(Scale::TDB);\n *\n * // then to tt, the current scale is TDB\n * let tt = tdb.to(Scale::TT);\n *\n * // then back to TAI\n * let tai = tt.to(Scale::TAI);\n *\n * // round trip equality\n * assert_eq!(dt, tai);\n * ```\n *\n * ### Performing some basic calendar aware math\n *\n * ```rust\n * use deep_time::{Dt, Scale};\n *\n * let x = Dt::from_ymd(2000, 2, 29, Scale::UTC, 0, 0, 0, 0).to_ymd();\n * let x = x.add_yr(1);\n *\n * assert_eq!(x.day(), 28);\n * ```\n *\n * ### Changing a dates format\n *\n * ```rust\n * use deep_time::{Dt, Lang, StrPTimeFmt};\n *\n * let fmt = Dt::parse_fmt(\\\"%Y-%m-%dT%H:%M:%S\\\").unwrap();\n *\n * # #[cfg(feature = \\\"alloc\\\")]\n * let s = fmt.to_str(\\\"2000-01-01T12:00:00\\\", \\\"%d %m %Y %H:%M:%S\\\", false, false, false, Lang::En).unwrap();\n *\n * # #[cfg(feature = \\\"alloc\\\")]\n * assert_eq!(s, \\\"01 01 2000 12:00:00\\\", \\\"expected: {}, got: {}\\\", \\\"01 01 2000 12:00:00\\\", s);\n * ```\n */\nexport interface Dt {\n attos: number;\n scale: Scale;\n target: Scale;\n}"

Source§

const SERIALIZATION_CONFIG: SerializationConfig

Source§

type JsType = JsType

Source§

fn into_js(&self) -> Result<Self::JsType, Error>
where Self: Serialize,

Source§

fn from_js<T>(js: T) -> Result<Self, Error>
where T: Into<JsValue>, Self: DeserializeOwned,

Auto Trait Implementations§

§

impl Freeze for Dt

§

impl RefUnwindSafe for Dt

§

impl Send for Dt

§

impl Sync for Dt

§

impl Unpin for Dt

§

impl UnsafeUnpin for Dt

§

impl UnwindSafe for Dt

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

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

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Comparable<K> for Q
where Q: Ord + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn compare(&self, key: &K) -> Ordering

Compare self to key and return their ordering.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

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

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

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

Performs the conversion.
Source§

impl<S, T> Upcast<T> for S
where T: UpcastFrom<S> + ?Sized, S: ?Sized,

Source§

fn upcast(&self) -> &T
where Self: ErasableGeneric, T: Sized + ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider ref type within the Wasm bindgen generics type system. Read more
Source§

fn upcast_into(self) -> T
where Self: Sized + ErasableGeneric, T: Sized + ErasableGeneric<Repr = Self::Repr>,

Perform a zero-cost type-safe upcast to a wider type within the Wasm bindgen generics type system. Read more