1use core::panic;
2use std::fmt;
3
4#[derive(PartialEq,PartialOrd,Debug)]
6pub struct UtcDatetime{
7 year:u16,
8 month:u8,
9 day:u8,
10 hour:u8,
11 minute:u8,
12 second:u8,
13}
14
15impl fmt::Display for UtcDatetime{
16 fn fmt(&self,f: &mut fmt::Formatter)->fmt::Result{
17 write!(f,"{}-{:02}-{:02} {:02}:{:02}:{:02}",self.year,self.month,self.day,self.hour,self.minute,self.second)
19 }
20}
21
22pub enum IllegalTimeError{
23 YearNumberError,
24 MonthNumberError,
25 DayNumberError,
26 HourNumberError,
27 MinuteNumberError,
28 SecondNumberError,
29 TimeStringError
30}
31
32impl fmt::Debug for IllegalTimeError {
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 match self{
35 IllegalTimeError::YearNumberError=>write!(f, "Year Number Error"),
36 IllegalTimeError::MonthNumberError=>write!(f, "Month Number Error"),
37 IllegalTimeError::DayNumberError=>write!(f, "Day Number Error"),
38 IllegalTimeError::HourNumberError=>write!(f, "Hour Number Error"),
39 IllegalTimeError::MinuteNumberError=>write!(f, "Minute Number Error"),
40 IllegalTimeError::SecondNumberError=>write!(f, "Second Number Error"),
41 IllegalTimeError::TimeStringError=>write!(f,"The format of the input time string is not standardized")
42 }
43 }
44}
45
46impl UtcDatetime{
47 pub fn new(year:u16,month:u8,day:u8,hour:u8,minute:u8,second:u8)->Result<UtcDatetime, IllegalTimeError>{
49 if year<1970{
50 return Err(IllegalTimeError::YearNumberError)
52 }
53 if month==0 || month >12{
54 return Err(IllegalTimeError::MonthNumberError)
56 }
57 if day==0 || day >days_of_the_month(year,month){
58 return Err(IllegalTimeError::DayNumberError)
60 }
61 if hour >23{
62 return Err(IllegalTimeError::HourNumberError)
64 }
65 if minute>59{
66 return Err(IllegalTimeError::MinuteNumberError)
68 }
69 if second>59{
70 return Err(IllegalTimeError::SecondNumberError)
72 }
73 Ok(UtcDatetime{year,month,day,hour,minute,second})
74 }
75 pub fn timestamp(&self)->Result<u32,IllegalTimeError>{
83 if self.year<1970{
84 return Err(IllegalTimeError::YearNumberError)
85 }
86 let second=self.second as u32;
87 let minute=self.minute as u32;
88 let hour=self.hour as u32;
89 let day =self.day as u32;
90
91 let mut total_seconds=0;
92
93 for i in 1970..self.year{
95 total_seconds+=days_of_the_year(i)*24*60*60;
96 }
97
98 for i in 1..self.month{
100 let days_num=days_of_the_month(self.year, i) as u32;
101 total_seconds+=days_num*24*60*60;
102 }
103
104 total_seconds+=(day-1)*60*60*24+hour*60*60+minute*60+second;
106
107 Ok(total_seconds)
108 }
109
110 pub fn weekday(&self)->u8{
119 let ts=self.timestamp().unwrap();
120 let this_week_seconds=ts%(7*24*3600);
122 let this_week_days=this_week_seconds/(24*3600);
124 let week_number=(4+this_week_days)%7;
126 week_number as u8
127 }
128 pub fn from_string(time_str:&str)->Result<UtcDatetime, IllegalTimeError>{
142 let mut time_string_array:Vec<&str>=time_str.split(|x| (x as u8) < 48 || x as u8 >57).collect();
146 time_string_array.retain(|&x|x.len()!=0);
148 if time_string_array.len()!=6{
149 return Err(IllegalTimeError::TimeStringError)
150 }
151 let year=time_string_array[0].parse::<u16>().unwrap();
152 let month=time_string_array[1].parse::<u8>().unwrap();
153 let day=time_string_array[2].parse::<u8>().unwrap();
154 let hour=time_string_array[3].parse::<u8>().unwrap();
155 let minute=time_string_array[4].parse::<u8>().unwrap();
156 let second=time_string_array[5].parse::<u8>().unwrap();
157 UtcDatetime::new(year,month,day,hour,minute,second)
158 }
159}
160
161pub fn leap_year(year:u16)->bool{
172 (year%4==0 && year%100!=0)||year%400==0
176}
177
178pub fn days_of_the_year(year:u16)->u32{
180 if leap_year(year){366}else{365}
181}
182
183pub fn days_of_the_month(year:u16,month:u8)->u8{
191 match month{
192 1|3|5|7|8|10|12=>31,
193 4|6|9|11=>30,
194 2=>{
195 if leap_year(year){
196 return 29
197 }
198 28
199 }
200 _=>panic!("Illegal number of days in the month.")
201 }
202}
203
204#[cfg(test)]
205mod tests{
206 use super::UtcDatetime;
207 #[test]
208 fn test1() {
209 let a_utc_datetime=UtcDatetime::from_string("时间:2021年2月28日23点59分0秒").unwrap();
210 assert_eq!(a_utc_datetime,UtcDatetime::new(2021,2,28,23,59,0).unwrap());
211 }
212
213 #[test]
214 fn test2(){
215 let a=UtcDatetime::from_string("2020-12-31 23:59:59").unwrap();
216 let b=UtcDatetime::from_string("2020/12/31 23:59:59").unwrap();
217 assert!(a==b);
218 }
219
220 #[test]
221 fn test3(){
222 let a=UtcDatetime::new(2020,4,28,12,12,12).unwrap();
223 assert_eq!(a.weekday(),2);
224 }
225
226 #[test]
227 fn test4(){
228 let dt_1=UtcDatetime::new(2020,4,28,12,30,12).unwrap();
229 let dt_2=UtcDatetime::new(2020,4,28,12,12,29).unwrap();
230 assert!(dt_1>dt_2);
231 }
232}