Skip to main content

iasinat_lib/
timestamp.rs

1use regex::Regex;
2
3use super::*;
4
5pub const JD_UNIX : f64 = 2440587.5;
6
7pub struct TimestampParser {
8    re:Regex,
9}
10
11pub trait ToUnix {
12    fn to_unix(&self)->f64;
13}
14
15impl ToUnix for GregorianDateHMS { 
16    fn to_unix(&self)->f64 {
17	let (jd1,jd2) = self.to_julian();
18	((jd1 - JD_UNIX) + jd2)*86400.0
19    }
20}
21
22pub fn julian_to_unix(jd1:R,jd2:R)->f64 {
23    ((jd1 - JD_UNIX) + jd2)*86400.0
24}
25
26pub fn unix_to_julian(t:f64)->(R,R) {
27    let t0 = t.floor();
28    (t0/86400.0 + JD_UNIX,(t - t0)/86400.0)
29}
30
31pub fn now()->(R,R) {
32    let dt = std::time::SystemTime::now()
33	.duration_since(std::time::UNIX_EPOCH)
34	.expect("Can't get timestamp");
35    unix_to_julian(dt.as_secs_f64())
36}
37    
38impl TimestampParser {
39    pub fn new()->Result<Self> {
40	let re = Regex::new(
41	    r"^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}|\d{5})Z$")?;
42	Ok(Self { re })
43    }
44
45    pub fn parse(&self,u:&str)->Result<GregorianDateHMS> {
46	let caps = self.re.captures(u)
47	    .ok_or_else(|| anyhow!("Cannot parse timestamp from {:?}",u))?;
48	Self::parse_caps(&caps,1)
49    }
50
51    fn parse_caps_gd(caps:&regex::Captures<'_>,i:usize)->
52	Result<GregorianDate>
53    {
54	let year : i32 = caps.get(i    ).unwrap().as_str().parse()?;
55	let month : i32 = caps.get(i + 1).unwrap().as_str().parse()?;
56	let day : i32 = caps.get(i + 2).unwrap().as_str().parse()?;
57	let gd = GregorianDate::new(year,month,day)?;
58	Ok(gd)
59    }
60
61    fn parse_caps(caps:&regex::Captures<'_>,i:usize)->
62	Result<GregorianDateHMS>
63    {
64	let date = Self::parse_caps_gd(caps,i)?;
65	let hour : u8 = caps.get(i + 3).unwrap().as_str().parse()?;
66	let minute : u8 = caps.get(i + 4).unwrap().as_str().parse()?;
67	let second_s = caps.get(i + 5).unwrap().as_str();
68	let second : u32 = second_s.parse()?;
69	let second =
70	    if second_s.len() == 2 {
71		second as f64
72	    } else {
73		second as f64 / 1000.0
74	    };
75	let hms = HMS { hour,minute,second };
76	Ok(Timestamp { date,hms })
77    }
78}
79
80#[test]
81fn test_timestamps() {
82    let ts_unix =
83	GregorianDateHMS {
84	    date:GregorianDate::new(1970,1,1).unwrap(),
85	    hms:HMS::new(0,0,0.0)
86	};
87    let (jd0_unix,jd1_unix) = ts_unix.to_julian();
88    println!("UNIX epoch: JD {}",jd0_unix + jd1_unix);
89    let ts_bill =
90	GregorianDateHMS {
91	    date:GregorianDate::new(2001,9,9).unwrap(),
92	    hms:HMS::new(1,46,40.0)
93	};
94    let (jd0_bill,jd1_bill) = ts_bill.to_julian();
95    println!("bill: JD {}",jd0_bill + jd1_bill);
96
97    let t_bill = 86400.0*((jd0_bill - jd0_unix) + (jd1_bill - jd1_unix));
98    println!("bill: Unix {:14.3}",t_bill);
99    assert!((t_bill - 1e9).abs() < 1e-6);
100}