pub struct TimeParts {Show 18 fields
pub yr: Option<i64>,
pub mo: Option<u8>,
pub day: Option<u8>,
pub hr: u8,
pub min: u8,
pub sec: u8,
pub attos: u64,
pub offset: Option<Offset>,
pub iana_name: Option<LiteStr<49>>,
pub scale: Scale,
pub wkday: Option<Weekday>,
pub day_of_yr: Option<u16>,
pub iso_wk_yr: Option<i64>,
pub iso_wk: Option<u8>,
pub wk_sun: Option<u8>,
pub wk_mon: Option<u8>,
pub meridiem: Option<Meridiem>,
pub unix_timestamp_seconds: Option<i64>,
}Expand description
A flexible, partially-filled representation of a civil datetime.
TimeParts is the central intermediate type used throughout the library
for parsing, formatting, and converting between different time representations
(CCSDS, ISO-like strings, chrono, jiff, Dt, etc.).
Most fields are optional, allowing partial dates/times. It also carries
metadata such as the time scale, IANA zone name, leap-second flag,
and various weekday/week-number representations.
- Convert to [
Dt] usingTimeParts::to_dt. - Conversions to types from other crates require relevant features to be enabled.
Fields§
§yr: Option<i64>Year (can be negative for BCE dates).
mo: Option<u8>Month of the year (1–12).
day: Option<u8>Day of the month (1–31).
hr: u8Hour of the day (0–23).
min: u8Minute of the hour (0–59).
sec: u8Second of the minute (0–60). Value 60 is used for leap seconds.
attos: u64Attoseconds (0 ≤ value < 10¹⁸).
offset: Option<Offset>Timezone offset from UTC.
iana_name: Option<LiteStr<49>>IANA timezone name (e.g. "America/New_York"), stored as ASCII.
scale: ScaleThe time scale this value belongs to (TAI, UTC, etc.).
wkday: Option<Weekday>Day of the week.
day_of_yr: Option<u16>Day of the year (1–366), corresponding to %j.
iso_wk_yr: Option<i64>ISO week year (%G / %g).
iso_wk: Option<u8>ISO week number (1–53), corresponding to %V.
wk_sun: Option<u8>Week number with Sunday as first day of week (0–53), %U.
wk_mon: Option<u8>Week number with Monday as first day of week (0–53), %W.
meridiem: Option<Meridiem>AM / PM indicator.
unix_timestamp_seconds: Option<i64>Unix timestamp in seconds (%s).
Implementations§
Source§impl TimeParts
impl TimeParts
Sourcepub const WIRE_VERSION: u8 = 1
pub const WIRE_VERSION: u8 = 1
Current wire format version.
Sourcepub fn to_wire_bytes(&self) -> [u8; 119]
pub fn to_wire_bytes(&self) -> [u8; 119]
Serializes TimeParts into a fixed 119-byte buffer.
Sourcepub fn from_wire_bytes(bytes: &[u8]) -> Option<Self>
pub fn from_wire_bytes(bytes: &[u8]) -> Option<Self>
Deserializes TimeParts from exactly 119 bytes.
Source§impl TimeParts
impl TimeParts
Sourcepub fn days_since_1958_to_gregorian(days_since_epoch: i64) -> (i64, u8, u8)
pub fn days_since_1958_to_gregorian(days_since_epoch: i64) -> (i64, u8, u8)
Converts days since 1958-01-01 (midnight UTC/TAI) into Gregorian date. Pure integer arithmetic matching the CCSDS 301.0-B-4 Level 1 epoch.
Sourcepub fn gregorian_to_days_since_1958(year: i64, month: u8, day: u8) -> i64
pub fn gregorian_to_days_since_1958(year: i64, month: u8, day: u8) -> i64
Exact inverse of days_since_1958_to_gregorian.
Sourcepub fn from_ccsds_ccs(input: &[u8]) -> Result<TimeParts, DtErr>
pub fn from_ccsds_ccs(input: &[u8]) -> Result<TimeParts, DtErr>
Parses a CCSDS Calendar Segmented Time Code (CCS) into TimeParts.
Implements CCSDS 301.0-B-4 §3.4 (Level 1 only).
This function accepts a single-byte P-field followed by a BCD-encoded T-field. It supports both calendar variants:
- Month/Day format (most common)
- Day-of-Year format
§P-field
- Must not have the extension bit set (only 1-byte P-fields are supported).
- Code ID must be
101. - Subsecond resolution: 0 to 6 BCD octets (0–12 decimal digits).
§T-field
- Year is encoded as 4 BCD digits (0001–9999).
- Time of day uses BCD with leap second support (
second == 60). - When a leap second is present,
secondis normalized to 59 andis_leap_secondis set totruein the returnedTimeParts.
§Epoch
1958-01-01 00:00:00 UTC (identical to CDS).
§Errors
Returns an error if the P-field is extended, the Code ID is wrong, BCD digits are invalid, field lengths are insufficient, or any component (month, day, DOY, hour, minute, second) is out of range.
The resulting TimeParts has scale = UTC.
Sourcepub fn from_ccsds_cuc(input: &[u8]) -> Result<TimeParts, DtErr>
pub fn from_ccsds_cuc(input: &[u8]) -> Result<TimeParts, DtErr>
Parses a CCSDS C (CUC – Unsegmented Time Code) binary time code
into a TimeParts.
Implements CCSDS 301.0-B-4 §3.2 (Level 1), including full support for the extended 2-byte P-field.
§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 TimeParts with scale = TAI and the decoded civil date/time.
§Errors
DtErrKind::Incompleteifinputis empty.DtErrKind::InvalidItemif the Code ID is not001.DtErrKind::InvalidInputif 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::InvalidSyntaxif the declared coarse + fractional field lengths make the T-field longer than the remaining input bytes.
Sourcepub fn from_ccsds_cds(input: &[u8]) -> Result<TimeParts, DtErr>
pub fn from_ccsds_cds(input: &[u8]) -> Result<TimeParts, DtErr>
Parses a CCSDS D (CDS – Day Segmented Time Code) binary time code
into a TimeParts.
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
100and the Epoch bit must be0(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 field01: 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
0for 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 and is_leap_second is effectively indicated via the sec field
in the returned TimeParts.
§Returns
A TimeParts with scale = UTC and the decoded civil date/time.
§Errors
DtErrKind::Incompleteifinputis empty.DtErrKind::InvalidInputif the P-field indicates an extended second octet but the input is too short to contain it.DtErrKind::InvalidItemif the Code ID is not100, the Epoch bit is set (non-Level-1 epoch), or the sub-millisecond code is0b11.DtErrKind::InvalidSyntaxif the declared field lengths make the T-field longer than the remaining input bytes.
Sourcepub fn from_ccsds_bin(input: &[u8]) -> Result<TimeParts, DtErr>
pub fn from_ccsds_bin(input: &[u8]) -> Result<TimeParts, 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.
Examines the Code ID and dispatches to the appropriate parser:
001→from_ccsds_cuc(CUC – Unsegmented Time Code)100→from_ccsds_cds(CDS – Day Segmented Time Code)101→from_ccsds_ccs(CCS – Calendar Segmented Time Code)
This is a convenience wrapper. For stricter control or when the format
is known in advance, prefer calling the specific from_ccsds_* function directly.
§Errors
DtErrKind::Incompleteifinputis empty.DtErrKind::InvalidItemif the Code ID is not one of the three recognized Level 1 values (001,100, or101).
The resulting TimeParts has scale set according to the detected format
(TAI for CUC, UTC for CDS, and format-dependent for CCS).
Source§impl TimeParts
impl TimeParts
Sourcepub fn from_str(
fmt: &str,
input: &str,
inp_can_end_before_fmt: bool,
fmt_can_end_before_inp: bool,
allow_partial_date: bool,
) -> Result<TimeParts, DtErr>
pub fn from_str( fmt: &str, input: &str, inp_can_end_before_fmt: bool, fmt_can_end_before_inp: bool, allow_partial_date: bool, ) -> Result<TimeParts, DtErr>
Parser equivalent to strptime with a provided format string.
The parser populates a TimeParts struct. After successful parsing,
Self::finish is called automatically to apply defaults and validation.
§Parameters
fmt: The format string containing%directives.input: The string to parse.inp_can_end_before_fmt: Iftrue, the input may end before the format string is fully consumed (extra format specifiers are ignored).fmt_can_end_before_inp: Iftrue, the format may end before the input is fully consumed (trailing characters in the input are allowed).allow_partial_date: Iftrue, a missing month/day will be defaulted to1instead 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 (00–99;00–68→ 2000+,69–99→ 1900s).%C— Century (00–99).%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 number01–12.%B— Full English month name (e.g.January).%b,%h— Abbreviated English month name (3 letters, e.g.Jan).
§Day
%d,%e— Day of month01–31(%eallows space padding).%j— Day of year001–366.
§Time of day
%H,%k— Hour00–23(24-hour clock;%kallows space padding).%I,%l— Hour01–12(12-hour clock).%M— Minute00–59.%S— Second00–60(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,%p—AM/PMindicator (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),00–53.%W— Week number (Monday-first week),00–53.%V— ISO 8601 week number01–53.
§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 epoch; up to 19 digits, can be negative).%n,%t— Any whitespace (consumes it from input).
§Unsupported / Unknown
%c,%r,%x,%X,%Z→DtErrKind::UnsupportedItem- Any other unknown directive character →
DtErrKind::UnknownItem
§Errors
Returns DtErr containing one of the following DtErrKind variants:
§Format string errors
DtErrKind::TruncatedDirective— The format string ended immediately after a%or after a.in a fractional directive (e.g.%.).DtErrKind::UnknownItem— Unknown%directive character.DtErrKind::UnsupportedItem— Known but unsupported directive (e.g.%c,%r,%x,%X,%Z).DtErrKind::BadFractional— Malformed fractional directive (e.g.%.xwherexis notforN).
§Input parsing errors
DtErrKind::UnexpectedInputEnd— Input ended before a required value could be parsed.Expected*variants:DtErrKind::ExpectedYearDtErrKind::ExpectedMonthDtErrKind::ExpectedDayDtErrKind::ExpectedDayOfYearDtErrKind::ExpectedHourDtErrKind::ExpectedMinuteDtErrKind::ExpectedSecondDtErrKind::ExpectedFractionalSecondsDtErrKind::ExpectedTimestampDtErrKind::ExpectedWeekNumberDtErrKind::ExpectedWeekdayNumber
DtErrKind::MismatchedLiteral— A literal character from the format string did not match the input.DtErrKind::OutOfRange— A numeric value was parsed but is outside the valid range for that component (e.g. month 13, hour 25, day 32).DtErrKind::InvalidName— Unrecognized month name, weekday name, oram/pmvalue.DtErrKind::InvalidTimezoneOffset— Invalid or malformed timezone offset / IANA name.DtErrKind::MustStartWith— Timezone offset did not start with+or-.
§Post-processing / validation errors
DtErrKind::Incomplete— Required date components (month/day) were missing andallow_partial_datewasfalse.DtErrKind::TrailingCharacters— The input contained trailing characters after parsing andfmt_can_end_before_inpwasfalse.
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).
Sourcepub fn finish(&mut self, allow_partial_date: bool) -> Result<(), DtErr>
pub fn finish(&mut self, allow_partial_date: bool) -> Result<(), DtErr>
Finalizes a TimeParts after parsing by applying sensible defaults and
performing validation.
This is called automatically by the various parsing paths (from_str,
CCSDS parsers, etc.). It ensures the struct is in a consistent state
before being turned into a full [Dt] or passed to other converters.
§Behavior
- If a Unix timestamp is present then no action is taken.
- Date completeness is checked in this priority order:
- Calendar date (
year,month,day) - Ordinal date (
year,day_of_year) - ISO week date (
iso_week_year,iso_week)
- Calendar date (
- If
allow_partial_dateistrue, missing month/day are defaulted to1.
§Errors
DtErrKind::Incompleteif no valid date representation is present.
Source§impl TimeParts
impl TimeParts
Sourcepub fn from_str_iso(input: &str) -> Result<Self, DtErr>
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.
Tis required. - Supports both calendar (
%Y-%m-%d) and day-of-year (%Y-%j) formats. - Treats years digits literally as shown, for example
99-01-01would 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.
+0200or2023-01-01+05:00. - Timezone name, requires square brackets and requires
jiff-tzfeature, 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.
- Time components after a date e.g.
- This function is considerably faster than all other string parsing methods if your date-time string is in the supported formats.
Source§impl TimeParts
impl TimeParts
Sourcepub fn to_ccsds_cuc(
&self,
n_coarse: u8,
n_frac: u8,
extension: bool,
) -> Result<([u8; 32], usize), DtErr>
pub fn to_ccsds_cuc( &self, n_coarse: u8, n_frac: u8, extension: bool, ) -> Result<([u8; 32], usize), DtErr>
Formats this TimeParts as a CCSDS C (CUC) binary time code.
- Fully configurable for round-tripping with [
from_ccsds_cuc]. - Conforms to CCSDS 301.0-B-4 §3.2 (Level 1), including full support
for the extended P-field (second octet) when
n_coarse > 4orn_frac > 3.
§Parameters
n_coarse: 1–7 (number of coarse-time octets)n_frac: 0–10 (number of fractional octets)extension: advisory flag (ignored when larger sizes force the second octet)
Sourcepub fn to_ccsds_cds(
&self,
n_day: u8,
sub_ms_code: u8,
extension: bool,
) -> Result<([u8; 32], usize), DtErr>
pub fn to_ccsds_cds( &self, n_day: u8, sub_ms_code: u8, extension: bool, ) -> Result<([u8; 32], usize), DtErr>
Formats this TimeParts as a CCSDS D (CDS) binary time code.
- Fully configurable for round-tripping with
TimeParts::from_ccsds_cds. - Conforms to CCSDS 301.0-B-4 §3.3 (Level 1): UTC day count + ms-of-day since 1958-01-01 UTC.
Sourcepub fn to_ccsds_ccs(
&self,
use_doy: bool,
n_subsec: u8,
) -> Result<([u8; 14], usize), DtErr>
pub fn to_ccsds_ccs( &self, use_doy: bool, n_subsec: u8, ) -> Result<([u8; 14], usize), DtErr>
Formats this TimeParts as a CCSDS CCS (Calendar Segmented Time Code).
Implements CCSDS 301.0-B-4 §3.4 (Level 1 only).
§Parameters
use_doy:false= Month/Day variant (most common),true= Day-of-Year variantn_subsec: Number of subsecond BCD octets (0–6). Each octet holds 2 decimal digits.
§Returns
(buffer, written_len) — the P-field + T-field (big-endian BCD).
§Precision & Rounding
Fractional seconds are rounded to the nearest representable value at the chosen precision
(exactly as to_ccsds_d does for milliseconds).
Sourcepub fn to_ccsds_bin(&self) -> Result<([u8; 32], usize), DtErr>
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 TimeParts’s [Scale].
§Automatic selection (matches common mission practice)
Scale::TAI→ CUC (4 coarse + 4 fractional bytes)- Any other
Scale(UTC, TT, GPS, TCG, …) → converted to UTC and uses CDS (2 day bytes + 4 ms bytes + 2-byte sub-ms)
Source§impl TimeParts
impl TimeParts
Sourcepub fn to_str_ccsds(&self) -> Result<String, DtErr>
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
Tseparator and trailingZ. - Fractional seconds are trimmed (no trailing zeros, no dot if zero).
- Round-trips with
Dt::from_str_iso/TimeParts::from_str_iso.
Sourcepub fn to_str_ccsds_nf(&self, max_precision: usize) -> Result<String, DtErr>
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).
Sourcepub fn to_ccsds_doy_str(&self) -> Result<String, DtErr>
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§impl TimeParts
impl TimeParts
Sourcepub fn to_chrono_naive_datetime(&self) -> Result<NaiveDateTime, DtErr>
pub fn to_chrono_naive_datetime(&self) -> Result<NaiveDateTime, DtErr>
Converts TimeParts → chrono::NaiveDateTime (civil time, no TZ).
Sourcepub fn to_chrono_datetime(&self) -> Result<DateTime<FixedOffset>, DtErr>
pub fn to_chrono_datetime(&self) -> Result<DateTime<FixedOffset>, DtErr>
Converts TimeParts → chrono::DateTime<FixedOffset>.
- If this
TimePartshas a unix timestamp then it is used instead of anything else (timezones are ignored in this route).
Sourcepub fn to_chrono_timestamp(&self) -> Result<i64, DtErr>
pub fn to_chrono_timestamp(&self) -> Result<i64, DtErr>
- If this
TimePartshas a unix timestamp then it is used instead of anything else (timezones are ignored). - Uses
TimeParts::to_chrono_datetimeinternally.
Source§impl TimeParts
impl TimeParts
Sourcepub fn to_jiff_broken_down_time(&self) -> Result<BrokenDownTime, DtErr>
pub fn to_jiff_broken_down_time(&self) -> Result<BrokenDownTime, DtErr>
Converts TimeParts → jiff::fmt::strtime::BrokenDownTime.
Sourcepub fn to_jiff_zoned(&self) -> Result<Zoned, DtErr>
pub fn to_jiff_zoned(&self) -> Result<Zoned, DtErr>
Converts TimeParts → jiff::Zoned.
Sourcepub fn to_jiff_timestamp(&self) -> Result<Timestamp, DtErr>
pub fn to_jiff_timestamp(&self) -> Result<Timestamp, DtErr>
Converts TimeParts → jiff::Timestamp.