pub struct DosTimestamp {
pub date: u16,
pub time: u16,
pub tenth: u8,
}Expand description
An instant in the DOS date and time encoding: two sixteen-bit words counting years from 1980 and seconds in units of two, and a companion field of hundredths.
FAT and exFAT both store this, bit for bit, because both inherited it from the same ancestor rather than each choosing it. Where a directory entry puts the two words and what it keeps beside them differ — a FAT entry holds them as separate fields and gives only its creation time a hundredths byte, an exFAT entry packs them into one 32-bit field and adds a zone offset — so each family’s on-disk layer owns that part and this owns the arithmetic underneath it.
The conversion is lossy in three separate ways, and each one is a property of the encoding rather than a choice:
- Range. Nothing before
SECS_MINor afterSECS_MAXfits, because the date word holds seven bits of year. - Granularity. The time word’s seconds field counts two-second units.
tenthrecovers the rest to a hundredth of a second, and a field the format gives no hundredths to is granular to two seconds. - Zone. The words carry no zone. Every conversion here is UTC, so an image’s bytes do not depend on where the machine that wrote it thinks it is. A format that records an offset beside the words records it beside them, not in them.
An instant outside the range is reported rather than wrapped: a year that overflowed seven bits would land in the 1980s and look entirely plausible.
use ferrosys::{DosTimestamp, Timestamp};
// 2015-03-14T09:26:53Z. The odd second is what the hundredths field carries, because
// the seconds field counts twos and rounds down.
let stamp = DosTimestamp::encode(Timestamp::from_secs(1_426_325_213)).expect("in range");
assert_eq!(stamp.tenth, 100);
assert_eq!(DosTimestamp::decode(stamp).secs, 1_426_325_213);
// The Unix epoch is thirty-five years too early for the date word.
assert!(DosTimestamp::encode(Timestamp::from_secs(0)).is_none());Fields§
§date: u16The date word: years since 1980 in bits 9..16, month 1 to 12 in bits 5..9, and day 1 to 31 in bits 0..5.
time: u16The time word: hours in bits 11..16, minutes in bits 5..11, and two-second units in bits 0..5.
tenth: u8Hundredths of a second past what time holds, 0 to 199 — the odd
second the two-second unit dropped, plus the fraction within it. A field the format
gives no hundredths to leaves this zero.
Implementations§
Source§impl DosTimestamp
impl DosTimestamp
Sourcepub const SECS_MIN: i64 = 315_532_800
pub const SECS_MIN: i64 = 315_532_800
The first instant the encoding represents: 1980-01-01T00:00:00Z, in seconds since the Unix epoch. The date word counts years from 1980, so there is nothing earlier to encode.
Sourcepub const SECS_MAX: i64 = 4_354_819_198
pub const SECS_MAX: i64 = 4_354_819_198
The last instant the encoding represents: 2107-12-31T23:59:58Z, in seconds since the Unix epoch. The year field is seven bits wide, reaching 1980 + 127, and the seconds field counts two-second units, so the final odd second is not representable either.
Sourcepub const MAX_TENTH: u8 = 199
pub const MAX_TENTH: u8 = 199
The largest value tenth holds: 199 hundredths, which is the odd
second the two-second unit dropped plus the ninety-nine hundredths within it.
A byte reaches 255, so the top fifty-six values are ones the field cannot mean —
is_well_formed is where an image carrying one is judged.
Sourcepub fn encode(time: Timestamp) -> Option<Self>
pub fn encode(time: Timestamp) -> Option<Self>
The date, time, and hundredths this encoding records time as, or None where the
instant is outside the range the fields reach.
The seconds field counts two-second units and rounds down, so the dropped odd
second reappears in tenth rather than moving the instant. A field
that has no hundredths therefore records a time up to two seconds early, which is the
encoding’s granularity and not a rounding choice.
Sourcepub const fn decode(self) -> Timestamp
pub const fn decode(self) -> Timestamp
The instant this date, time, and hundredths describe, UTC.
Every field is taken as it is found. An image may hold a date no calendar has — day 31
of February, month 0, day 0 — and this reports the instant that arithmetic reaches
rather than refusing, because a reader’s job is to say what the image holds and
is_well_formed is what judges it. A field with no time word
passes zero, which is midnight.
Sourcepub const fn is_well_formed(self) -> bool
pub const fn is_well_formed(self) -> bool
Whether every field holds a value the encoding defines for it.
This is what decode defers: a month of 0, a day of 31 in February, a
twenty-fifth hour, a seconds field counting past 58, and a hundredths byte past
MAX_TENTH are each a field an image may carry and no encoder
produces. A reader hands back the instant the arithmetic reaches; a scan asks this and
reports the ones that answer false.
The month lengths are not tabulated. A date the calendar has is one a round trip through the calendar returns unchanged, and one it does not have is one the arithmetic moves — February 31 comes back as March 3, hour 24 as midnight the next day — so the round trip is the whole test.
use ferrosys::DosTimestamp;
// 2015-03-14T09:26:52Z, which the calendar has.
assert!(DosTimestamp { date: 0x4A6E, time: 0x4B5A, tenth: 0 }.is_well_formed());
// Month 0 and day 0, which is what an entry of zero bytes spells.
assert!(!DosTimestamp::default().is_well_formed());Sourcepub const fn represents(time: Timestamp) -> bool
pub const fn represents(time: Timestamp) -> bool
Whether time is an instant this encoding represents.
The final odd second of 2107 is excluded along with everything past it: the seconds field counts two-second units, so there is no encoding for it.
Trait Implementations§
Source§impl Clone for DosTimestamp
impl Clone for DosTimestamp
Source§fn clone(&self) -> DosTimestamp
fn clone(&self) -> DosTimestamp
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for DosTimestamp
impl Debug for DosTimestamp
Source§impl Default for DosTimestamp
impl Default for DosTimestamp
Source§fn default() -> DosTimestamp
fn default() -> DosTimestamp
Source§impl PartialEq for DosTimestamp
impl PartialEq for DosTimestamp
Source§fn eq(&self, other: &DosTimestamp) -> bool
fn eq(&self, other: &DosTimestamp) -> bool
self and other values to be equal, and is used by ==.