1use time::OffsetDateTime;
2
3use crate::base::status::Status;
4
5const SECONDS_OF_DAY: i64 = 60 * 60 * 24;
6
7const MILL_SECONDS_OF_DAY: i64 = SECONDS_OF_DAY * 1000;
8
9const EIGHT_HOUR: i64 = 60 * 60 * 8 * 1000;
10
11#[allow(dead_code)]
15pub fn cur_timestamp() -> i64 {
16 (OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000_000) as i64
17}
18
19#[allow(dead_code)]
23pub fn next_day_begin_timestamp_from_today() -> i64 {
24 next_day_begin_timestamp_from(cur_timestamp())
25}
26
27#[allow(dead_code)]
31pub fn next_day_begin_timestamp_from(timestamp: i64) -> i64 {
32 let next_day =
33 ((timestamp + EIGHT_HOUR) / MILL_SECONDS_OF_DAY + 1) * MILL_SECONDS_OF_DAY - EIGHT_HOUR;
34 next_day
35}
36
37#[allow(dead_code)]
41pub fn pre_day_begin_timestamp_from_today() -> i64 {
42 pre_day_begin_timestamp_from(cur_timestamp())
43}
44
45#[allow(dead_code)]
49pub fn pre_day_begin_timestamp_from(timestamp: i64) -> i64 {
50 let pre_day =
51 (timestamp / MILL_SECONDS_OF_DAY) * MILL_SECONDS_OF_DAY - MILL_SECONDS_OF_DAY - EIGHT_HOUR;
52 pre_day
53}
54
55#[allow(dead_code)]
59pub fn begin_timestamp_from(timestamp: i64) -> i64 {
60 (timestamp / MILL_SECONDS_OF_DAY) * MILL_SECONDS_OF_DAY * MILL_SECONDS_OF_DAY - EIGHT_HOUR
61}
62
63#[allow(dead_code)]
67pub fn last_min_timestamp_from(timestamp: i64) -> i64 {
68 let day_begin_timestamp = begin_timestamp_from(timestamp);
69 day_begin_timestamp + MILL_SECONDS_OF_DAY - 60 * 1000
70}
71
72#[allow(dead_code)]
73fn timestamp_to_local(timestamp: i64) -> i64 {
74 let local_offset = OffsetDateTime::now_local();
75
76 if let Ok(local) = local_offset {
77 return timestamp + (local.offset().whole_seconds() as i64 * 1000);
78 }
79 return timestamp;
80}
81
82#[allow(dead_code)]
86pub fn ymd_from_timestamp(timestamp: i64) -> Result<(u32, u32, u32), Status> {
87 let local_timestamp = timestamp_to_local(timestamp);
88 let datetime = OffsetDateTime::from_unix_timestamp(local_timestamp / 1000);
89 if let Ok(date) = datetime {
90 Ok((date.year() as u32, date.month() as u32, date.day() as u32))
91 } else {
92 Err(Status::error("转换为 datetime 错误!".into()))
93 }
94}
95#[allow(dead_code)]
99pub fn hms_from_timestamp(timestamp: i64) -> Result<(u32, u32, u32), Status> {
100 let local_timestamp = timestamp_to_local(timestamp);
101 let datetime = OffsetDateTime::from_unix_timestamp(local_timestamp / 1000);
102 if let Ok(date) = datetime {
103 Ok((
104 date.hour() as u32,
105 date.minute() as u32,
106 date.second() as u32,
107 ))
108 } else {
109 Err(Status::error("转换为 datetime 错误!".into()))
110 }
111}
112
113fn fill_buffer(
114 format: &str,
115 match_char: char,
116 time_no: i32,
117 buffer: &mut [u8],
118 cur_index: &mut usize,
119) {
120 let mut symbol_num = 0;
121 while *cur_index < format.len() {
123 let ch = format.chars().nth(*cur_index).unwrap();
124 if ch == match_char {
125 symbol_num += 1;
126 } else {
127 *cur_index -= 1;
128 break;
129 }
130 *cur_index += 1;
131 }
132 if *cur_index == format.len() {
133 *cur_index -= 1;
134 }
135 let mut begin = 1;
136 for j in 0..symbol_num {
137 buffer[*cur_index - j] = (time_no / begin % 10) as u8 + 48;
138 begin *= 10;
139 }
140}
141#[allow(dead_code)]
142pub fn time_to_str(
143 format: &str,
144 year: i32,
145 month: i32,
146 day: i32,
147 hour: i32,
148 minutes: i32,
149 seconds: i32,
150 millisecond: i32,
151) -> String {
152 let format_chars: Vec<char> = format.chars().collect();
153 let mut buffer: Vec<u8> = vec![0; format_chars.len()];
154 let format_len = format.len();
155 let mut cur_index = 0;
156 while cur_index < format_len {
157 let ch = format_chars[cur_index];
158 match ch {
159 'y' => fill_buffer(format, ch, year, &mut buffer, &mut cur_index),
160 'M' => fill_buffer(format, ch, month, &mut buffer, &mut cur_index),
161 'd' => fill_buffer(format, ch, day, &mut buffer, &mut cur_index),
162 'h' => fill_buffer(format, ch, hour, &mut buffer, &mut cur_index),
163 'm' => fill_buffer(format, ch, minutes, &mut buffer, &mut cur_index),
164 's' => fill_buffer(format, ch, seconds, &mut buffer, &mut cur_index),
165 'S' => fill_buffer(format, ch, millisecond, &mut buffer, &mut cur_index),
166 _ => buffer[cur_index] = ch as u8,
167 }
168 cur_index += 1;
169 }
170 unsafe { String::from_utf8_unchecked(buffer) }
171}
172#[allow(dead_code)]
173pub fn timestamp_to_string(format: &str, timestamp: i64) -> String {
174 let local_timestamp = timestamp_to_local(timestamp);
175 let datetime = OffsetDateTime::from_unix_timestamp(local_timestamp / 1000);
176 if let Ok(date) = datetime {
177 let second_timestamp = local_timestamp / 1000;
178 let millisecond = (local_timestamp - second_timestamp * 1000) as i32;
179 time_to_str(
180 format,
181 date.year(),
182 date.month() as i32,
183 date.day() as i32,
184 date.hour() as i32,
185 date.minute() as i32,
186 date.second() as i32,
187 millisecond,
188 )
189 } else {
190 "--".to_string()
191 }
192}
193
194#[allow(dead_code)]
195pub fn cur_time_str_with_format(format: &str) -> String {
196 timestamp_to_string(format, cur_timestamp())
197}
198
199
200
201#[allow(dead_code)]
205pub fn cur_time_str() -> String {
206 cur_time_str_with_format("yyyy-MM-dd hh:mm:ss.SSS")
207}
208
209
210fn buffer_to_number(
211 format: &str,
212 str: &str,
213 match_char: char,
214 format_len: usize,
215 time_no: &mut i32,
216 cur_index: &mut usize,
217) {
218 let mut ch: char;
219 let mut c_ch: char;
220 *time_no = 0;
221 let mut has_val = false;
222
223 while *cur_index < format_len {
224 ch = format.chars().nth(*cur_index).unwrap();
225 c_ch = str.chars().nth(*cur_index).unwrap();
226 if ch != match_char || !c_ch.is_ascii_digit() {
227 if has_val {
228 *cur_index -= 1;
229 }
230 break;
231 }
232 has_val = true;
233 *time_no *= 10;
234 *time_no += c_ch as i32 - '0' as i32;
235 *cur_index += 1;
236 }
237}
238
239pub fn str_to_time(format: &str, string: &str) -> Option<(i32, i32, i32, i32, i32, i32, i32)> {
240 let mut year = 0;
241 let mut month = 0;
242 let mut day = 0;
243 let mut hour = 0;
244 let mut minutes = 0;
245 let mut seconds = 0;
246 let mut millisecond = 0;
247
248 let format_len = format.len();
249 let str_len = string.len();
250 if str_len < format_len {
251 return None;
252 }
253
254 let mut cur_index = 0;
255
256 while cur_index < format_len {
257 let ch = format.chars().nth(cur_index).unwrap();
258 match ch {
259 'y' => buffer_to_number(format, string, ch, format_len, &mut year, &mut cur_index),
260 'M' => buffer_to_number(format, string, ch, format_len, &mut month, &mut cur_index),
261 'd' => buffer_to_number(format, string, ch, format_len, &mut day, &mut cur_index),
262 'h' => buffer_to_number(format, string, ch, format_len, &mut hour, &mut cur_index),
263 'm' => buffer_to_number(format, string, ch, format_len, &mut minutes, &mut cur_index),
264 's' => buffer_to_number(format, string, ch, format_len, &mut seconds, &mut cur_index),
265 'S' => buffer_to_number(
266 format,
267 string,
268 ch,
269 format_len,
270 &mut millisecond,
271 &mut cur_index,
272 ),
273 _ => {
274 if ch != string.chars().nth(cur_index).unwrap() {
275 return None;
276 }
277 }
278 }
279 cur_index += 1;
280 }
281
282 Some((year, month, day, hour, minutes, seconds, millisecond))
283}