chj_rustbin/time/
tai.rs

1use std::time::SystemTime;
2
3use anyhow::{anyhow, bail, Result};
4use chrono::{DateTime, Local, Utc};
5use tai64::Tai64N;
6
7use crate::{
8    fp::complement,
9    text::parseutil::{
10        char_is_white, drop_n, first_rest, parse_hex, take_while,
11    },
12    time::excel::exceldays_from_unixtime,
13};
14
15pub fn parse_timestamp(s: &str) -> Result<(Tai64N, &str)> {
16    let (c0, r) = first_rest(s)
17        .ok_or_else(|| anyhow!("empty line, missing timestamp"))?;
18    if c0 != '@' {
19        bail!("line does not start with @")
20    }
21    let (stamp, rest) = take_while(r, complement(char_is_white));
22    if stamp.len() < 24 {
23        bail!("timestamp string is too short")
24    }
25    let stamp8: [u8; 12] = parse_hex(stamp)?;
26    let t = Tai64N::from_slice(&stamp8)?;
27    Ok((t, drop_n(rest, 1, char_is_white)?))
28}
29
30pub trait Tai64Format {
31    fn to_rfc2822_local(&self) -> String;
32    fn to_rfc2822_utc(&self) -> String;
33    fn to_datetime_utc(&self) -> DateTime<Utc>;
34    fn to_exceldays(&self, offset_hours: f64) -> f64;
35}
36
37impl Tai64Format for Tai64N {
38    fn to_rfc2822_local(&self) -> String {
39        let t = self.to_system_time();
40        let dt: DateTime<Local> = DateTime::from(t);
41        dt.to_rfc2822()
42    }
43
44    fn to_rfc2822_utc(&self) -> String {
45        let t = self.to_system_time();
46        let dt: DateTime<Utc> = DateTime::from(t);
47        dt.to_rfc2822()
48    }
49
50    fn to_datetime_utc(&self) -> DateTime<Utc> {
51        let t = self.to_system_time();
52        DateTime::from(t)
53    }
54
55    /// Convert to Excel's days-since-~1900 values. You need to pass
56    /// the correct zone difference, and adapt it for DST. Panics on
57    /// potential conversion errors.  offset_hours: `1.0` represents
58    /// `+01:00`.
59    fn to_exceldays(&self, offset_hours: f64) -> f64 {
60        let st = self.to_system_time();
61        let t = st
62            .duration_since(SystemTime::UNIX_EPOCH)
63            .expect("no overflows?")
64            .as_secs_f64();
65        exceldays_from_unixtime(t, offset_hours)
66    }
67}