utc_datetime/
lib.rs

1use core::panic;
2use std::fmt;
3
4// 派生比较UtcDatetime的特性(=,>,<,<=,>=,!=)
5#[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        // 指定宽度输入数字
18        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    /// Create a new UtcDateTime structure
48    pub fn new(year:u16,month:u8,day:u8,hour:u8,minute:u8,second:u8)->Result<UtcDatetime, IllegalTimeError>{
49        if year<1970{
50            // println!("年份非法");
51            return Err(IllegalTimeError::YearNumberError)
52        }
53		if month==0 || month >12{
54            // println!("月份非法");
55            return Err(IllegalTimeError::MonthNumberError)
56        }
57        if day==0 || day >days_of_the_month(year,month){
58            // println!("天数非法");
59            return Err(IllegalTimeError::DayNumberError)
60        }
61        if hour >23{
62            // println!("小时数非法");
63            return Err(IllegalTimeError::HourNumberError)
64        }
65        if minute>59{
66            // println!("分钟数非法");
67            return Err(IllegalTimeError::MinuteNumberError)
68        }
69        if second>59{
70            // println!("秒数非法");
71            return Err(IllegalTimeError::SecondNumberError)
72        }
73        Ok(UtcDatetime{year,month,day,hour,minute,second})
74    }
75    /// Returns the number of seconds since January 1, 1970
76    /// # Example
77    /// ```
78    /// use utc_datetime::UtcDatetime;
79    /// let anew_date=UtcDatetime::new(2020,2,2,2,2,2).unwrap();
80    /// assert_eq!(anew_date.timestamp().unwrap(),1580608922)
81    /// ```
82    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        // 计算1970年到去年的秒数   
94        for i in 1970..self.year{
95            total_seconds+=days_of_the_year(i)*24*60*60;
96        }
97
98        // 计算今年过去的月份的秒数
99        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        // 计算这个月时间的秒数
105        total_seconds+=(day-1)*60*60*24+hour*60*60+minute*60+second;
106        
107        Ok(total_seconds)
108    }
109
110    // 返回今天是星期几:星期一到星期六依次返回1到6,星期天返回0
111    /// Return today is the day of the week,Monday to Saturday Return 1 to 6,Sunday return 0
112    /// # Example
113    /// ```
114    /// use utc_datetime::UtcDatetime;
115    /// let a_date=UtcDatetime::new(2021,11,15,0,0,0).unwrap();
116    /// assert_eq!(a_date.weekday(),1);
117    /// ```
118    pub fn weekday(&self)->u8{
119        let ts=self.timestamp().unwrap();
120        //7*24*3600 为7天的秒数
121        let this_week_seconds=ts%(7*24*3600);
122        // 24*3600为一天的秒数
123        let this_week_days=this_week_seconds/(24*3600);
124        // 1970年1月1日是周四
125        let week_number=(4+this_week_days)%7;
126        week_number as u8
127    }
128    // 输入一个时间字符串(如"2002-04-01 00:00:01") 返回一个时间对象
129    /// Convert a string containing time to UtcDatetime.
130    /// 
131    /// Time strings must be sorted by year, month, day, hour, minute, and second,
132    /// and Non-arabic numbers can be used as separators.
133    /// 
134    /// Parsable string example:"2020-12-31 23:59:59","2020z12z31z23z59z59".
135    /// # Example
136    /// ```
137    /// use utc_datetime::UtcDatetime;
138    /// let datetime=UtcDatetime::from_string("时间:2020年12月31日23点59分59秒").unwrap();
139    /// assert_eq!(datetime,UtcDatetime::new(2020,12,31,23,59,59).unwrap());
140    /// ```
141    pub fn from_string(time_str:&str)->Result<UtcDatetime, IllegalTimeError>{
142		// 能转换的字符串的日期必须为阿拉伯数字,且顺序必须按照年,月,日,小时,分,秒的顺序
143		// 只保留字符串中的阿拉伯数字
144		// '0'-'9'的ascii码为48-57
145        let mut time_string_array:Vec<&str>=time_str.split(|x| (x as u8) < 48 || x as u8  >57).collect();
146        // retain non-empty items in time_string_array
147        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
161/// Conditions for judging leap years
162/// 1. Divisible by 4, but not divisible by 100
163/// 2. Divisible by 400
164/// # Example
165/// ```
166/// use utc_datetime::leap_year;
167/// assert!(leap_year(2000));
168/// assert_eq!(leap_year(2021),false);
169/// assert_eq!(leap_year(1900),false);
170/// ```
171pub fn leap_year(year:u16)->bool{
172	// 判断闰年的条件
173    // 1.能被4整除,但不能被100整除 
174	// 2.能被400整除
175    (year%4==0 && year%100!=0)||year%400==0
176}
177
178/// Returns the number of days in a year
179pub fn days_of_the_year(year:u16)->u32{
180    if leap_year(year){366}else{365}
181}
182
183/// Returns the number of days in this month
184/// # Example
185/// ```
186/// use utc_datetime::days_of_the_month;
187/// assert_eq!(days_of_the_month(2020,2),29);
188/// assert_eq!(days_of_the_month(2020,3),31)
189/// ```
190pub 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}