xref: /DragonOS/kernel/src/time/timeconv.rs (revision 40314b30ab2a7e1fd06a05a00f693e644e446035)
1 use super::syscall::PosixTimeT;
2 /// 一小时所包含的秒数
3 const SECS_PER_HOUR: i64 = 60 * 60;
4 /// 一天所包含的秒数
5 const SECS_PER_DAY: i64 = SECS_PER_HOUR * 24;
6 /// 每年中每个月最后一天所对应天数
7 const MON_OF_YDAY: [[i64; 13]; 2] = [
8     // 普通年
9     [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
10     // 闰年
11     [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366],
12 ];
13 #[derive(Debug)]
14 #[allow(dead_code)]
15 pub struct CalendarTime {
16     tm_sec: i32,
17     tm_min: i32,
18     tm_hour: i32,
19     tm_mday: i32,
20     tm_mon: i32,
21     tm_wday: i32,
22     tm_yday: i32,
23     tm_year: i32,
24 }
25 impl CalendarTime {
26     pub fn new() -> Self {
27         CalendarTime {
28             tm_year: Default::default(),
29             tm_sec: Default::default(),
30             tm_min: Default::default(),
31             tm_hour: Default::default(),
32             tm_mday: Default::default(),
33             tm_mon: Default::default(),
34             tm_wday: Default::default(),
35             tm_yday: Default::default(),
36         }
37     }
38 }
39 
40 /// # 判断是否是闰年
41 ///
42 /// ## 参数
43 ///
44 /// * 'year' - 年份
45 fn is_leap(year: u32) -> bool {
46     let mut flag = false;
47     if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {
48         flag = true;
49     }
50     return flag;
51 }
52 
53 /// # 计算除法
54 ///
55 /// # 参数
56 ///
57 /// * 'left' - 被除数
58 /// * 'right' - 除数
59 fn math_div(left: u32, right: u32) -> u32 {
60     return left / right;
61 }
62 
63 /// # 计算两年之间的闰年数目
64 ///
65 /// ## 参数
66 ///
67 /// * 'y1' - 起始年份
68 /// * 'y2' - 结束年份
69 fn leaps_between(y1: u32, y2: u32) -> u32 {
70     // 算出y1之前的闰年数量
71     let y1_leaps = math_div(y1 - 1, 4) - math_div(y1 - 1, 100) + math_div(y1 - 1, 400);
72     // 算出y2之前的闰年数量
73     let y2_leaps = math_div(y2 - 1, 4) - math_div(y2 - 1, 100) + math_div(y2 - 1, 400);
74 
75     y2_leaps - y1_leaps
76 }
77 
78 /// # 将秒数转换成日期
79 ///
80 /// ## 参数
81 ///
82 /// * 'totalsecs' - 1970年1月1日 00:00:00 UTC到现在的秒数
83 /// * 'offset' - 指定的秒数对应的时间段(含)的偏移量(以秒为单位)
84 #[allow(dead_code)]
85 pub fn time_to_calendar(totalsecs: PosixTimeT, offset: i32) -> CalendarTime {
86     let mut result = CalendarTime::new();
87     // 计算对应的天数
88     let mut days = totalsecs / SECS_PER_DAY;
89     // 一天中剩余的秒数
90     let mut rem = totalsecs % SECS_PER_DAY;
91 
92     // 加入偏移量
93     rem += offset as i64;
94     while rem < 0 {
95         rem += SECS_PER_DAY;
96         days -= 1;
97     }
98     while rem >= SECS_PER_DAY {
99         rem -= SECS_PER_DAY;
100         days += 1;
101     }
102     // 计算对应的小时数
103     result.tm_hour = (rem / SECS_PER_HOUR) as i32;
104     rem = rem % SECS_PER_HOUR;
105 
106     // 计算对应的分钟数
107     result.tm_min = (rem / 60) as i32;
108     rem = rem % 60;
109 
110     // 秒数
111     result.tm_sec = rem as i32;
112 
113     // totalsec是从1970年1月1日 00:00:00 UTC到现在的秒数
114     // 当时是星期四
115     result.tm_wday = ((4 + days) % 7) as i32;
116 
117     let mut year = 1970;
118     while days < 0 || (is_leap(year) && days >= 366) || (!is_leap(year) && days >= 365) {
119         // 假设每一年都是365天,计算出大概的年份
120         let guess_year = year + math_div(days.try_into().unwrap(), 365);
121         // 将已经计算过的天数去掉
122         days -= ((guess_year - year) * 365 + leaps_between(year, guess_year)) as i64;
123         year = guess_year;
124     }
125     result.tm_year = (year - 1900) as i32;
126     result.tm_yday = days as i32;
127     let mut il = 0;
128     if is_leap(year) {
129         il = 1
130     };
131     let mut mon = 0;
132     for i in MON_OF_YDAY[il] {
133         if days < i {
134             break;
135         }
136         mon += 1;
137     }
138     days -= MON_OF_YDAY[il][mon - 1];
139     result.tm_mon = (mon - 1) as i32;
140     result.tm_mday = (days + 1) as i32;
141 
142     result
143 }
144