fhir_rs/datatype/base/
datetime.rs

1use std::fmt::{Display, Formatter};
2use std::str::FromStr;
3use chrono::{FixedOffset, Local};
4use crate::error::FhirError;
5
6#[derive(Clone, Debug)]
7pub struct Date(chrono::NaiveDate, usize);
8
9impl From<chrono::DateTime<Local>> for Date {
10    fn from(value: chrono::DateTime<Local>) -> Self {
11        Self(value.date_naive(), 10)
12    }
13}
14
15impl FromStr for Date {
16    type Err = FhirError;
17
18    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
19        let precision = s.len();
20        let val = match precision {
21            4 => {format!("{}-01-01", s)},
22            7 => {format!("{}-01", s)},
23            10 => {format!("{}", s)},
24            _ => {return Err(FhirError::error("错误的日期格式,只接受YYYY,YYYY-MM,YYYY-MM-DD三种格式"));}
25        };
26        let val = chrono::NaiveDate::from_str(val.as_str())?;
27        Ok(Date(val, precision))
28    }
29}
30
31impl Display for Date {
32    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
33        match self.1 {
34            4 => {write!(f, "{}", self.0.format("%Y"))},
35            7 => {write!(f, "{}", self.0.format("%Y-%m"))},
36            10 => {write!(f, "{}", self.0.format("%Y-%m-%d"))},
37            _ => {write!(f, "Error")}
38        }
39    }
40}
41
42#[derive(Clone, Debug)]
43pub struct Time(chrono::NaiveTime, usize);
44
45impl From<chrono::DateTime<Local>> for Time {
46    fn from(value: chrono::DateTime<Local>) -> Self {
47        Self(value.time(), 12)
48    }
49}
50
51impl Display for Time {
52    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53        match self.1 {
54            8 => {write!(f, "{}", self.0.format("%H:%M:%S"))},
55            12 => {write!(f, "{}", self.0.format("%H:%M:%S.%3f"))},
56            _ => {write!(f, "Error")}
57        }
58    }
59}
60
61impl FromStr for Time {
62    type Err = FhirError;
63
64    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
65        let precision = s.len();
66        let val = match precision {
67            8 => {chrono::NaiveTime::parse_from_str(s, "%H:%M:%S")?},
68            12 => {chrono::NaiveTime::parse_from_str(s, "%H:%M:%S.%3f")?},
69            _ => {return Err(FhirError::error("错误的时间格式,只接受HH::MM::SS,HH:MM:SS.sss两种格式"));}
70        };
71        Ok(Time(val, precision))
72    }
73}
74
75/// 日期与时间
76///
77/// 精度不限,展示形式灵活.
78///
79/// 可以表示:
80/// * 年 - 2023
81/// * 年月 - 2023-08
82/// * 年月日 - 2023-08-17
83/// * 年月日时分秒 - 2023-08-17T08:21:45
84/// * 年月日时分秒(毫秒) - 2023-08-17T08:21:45.234
85/// * 年月日时分秒(毫秒)时区 - 2023-08-17T08:21:45.234+08:00
86#[derive(Clone, Debug)]
87pub struct DateTime(chrono::DateTime<FixedOffset>, usize);
88
89impl From<chrono::DateTime<Local>> for DateTime {
90    fn from(value: chrono::DateTime<Local>) -> Self {
91        Self(value.into(), 29)
92    }
93}
94
95impl Display for DateTime {
96    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
97        match self.1 {
98            4 => {write!(f, "{}", self.0.format("%Y"))},
99            7 => {write!(f, "{}", self.0.format("%Y-%m"))},
100            10 => {write!(f, "{}", self.0.format("%Y-%m-%d"))},
101            20|25 => {write!(f, "{}", self.0.format("%Y-%m-%dT%H:%M:%S%:z"))},
102            24|29 => {write!(f, "{}", self.0.format("%Y-%m-%dT%H:%M:%S.%3f%:z"))},
103            _ => {write!(f, "Error")}
104        }
105    }
106}
107
108impl FromStr for DateTime {
109    type Err = FhirError;
110
111    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
112        let pattern = "0000-01-01T00:00:00.000Z";
113        let precision = s.len();
114        let val = match precision {
115            4|7|10|24 => {
116                let dt = format!("{}{}", s, &pattern[precision..]);
117                chrono::DateTime::<chrono::Local>::from_str(dt.as_str())?.into()
118            },
119            20 => {
120                let dt = format!("{}{}", &s[0..precision-1], &pattern[precision-1..]);
121                chrono::DateTime::<chrono::Local>::from_str(dt.as_str())?.into()
122            },
123            25|29 => {
124                chrono::DateTime::from_str(s)?
125            },
126            _ => {return Err(FhirError::error("错误的时间格式,只接受FHIR规范约定的日期时间格式"));}
127        };
128        Ok(DateTime(val, precision))
129    }
130}
131
132/// 日期与时间
133///
134/// 精度更高,最小精度要到秒,必须有时区。一般这种时间都是由机器生成的。
135///
136/// 只接受FHIR规范约定的四种格式:
137/// * 2009-12-24T07:12:45Z
138/// * 2009-12-24T07:12:45.234Z
139/// * 2009-12-24T07:12:45+08:00
140/// * 2009-12-24T07:12:45.234+08:00
141///
142/// 输出时,只有两种:
143/// * 2009-12-24T07:12:45+08:00
144/// * 2009-12-24T07:12:45.234+08:00
145/// 导入之后,会根据当地的时区将Z转换为对应的时区
146#[derive(Clone, Debug)]
147pub struct Instant(chrono::DateTime<FixedOffset>, usize);
148
149impl From<chrono::DateTime<Local>> for Instant {
150    fn from(value: chrono::DateTime<Local>) -> Self {
151        Self(value.into(), 29)
152    }
153}
154
155impl Display for Instant {
156    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
157        match self.1 {
158            20|25 => {write!(f, "{}", self.0.format("%Y-%m-%dT%H:%M:%S%:z"))},
159            24|29 => {write!(f, "{}", self.0.format("%Y-%m-%dT%H:%M:%S.%3f%:z"))},
160            _ => {write!(f, "Error")}
161        }
162    }
163}
164
165impl FromStr for Instant {
166    type Err = FhirError;
167
168    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
169        let precision = s.len();
170        let val = match precision {
171            20|24 => {
172                chrono::DateTime::<chrono::Local>::from_str(s)?.into()
173            },
174            25|29 => {
175                chrono::DateTime::from_str(s)?
176            },
177            _ => {return Err(FhirError::error("错误的时间格式,只接受FHIR规范约定的日期时间格式"));}
178        };
179        Ok(Instant(val, precision))
180    }
181}
182
183#[test]
184fn test_datetime() -> crate::prelude::Result<()> {
185    let d1 = Date::from(Local::now());
186    println!("Date: {}", d1.to_string());
187
188    let t1 = Time::from(Local::now());
189    println!("Time: {}", t1.to_string());
190
191    let local = Local::now();
192
193    let dt1 = DateTime::from(local);
194    println!("DateTime: {}", dt1.to_string());
195
196    let instance = Instant::from(local);
197    println!("Instant: {}", instance.to_string());
198
199    Ok(())
200}