1pub fn current_utc_timestamp() -> String {
2 let duration = std::time::SystemTime::now()
3 .duration_since(std::time::UNIX_EPOCH)
4 .unwrap_or_default();
5 format_utc_timestamp(duration.as_secs())
6}
7
8pub fn format_utc_timestamp(timestamp: u64) -> String {
9 let second = timestamp % 60;
10 let minute = (timestamp / 60) % 60;
11 let hour = (timestamp / 3600) % 24;
12 let mut days = timestamp / 86400;
13 let mut year = 1970u64;
14 loop {
15 let days_in_year = if is_leap_year(year) { 366 } else { 365 };
16 if days < days_in_year {
17 break;
18 }
19 days -= days_in_year;
20 year += 1;
21 }
22 let month_days = month_lengths(is_leap_year(year));
23 let mut month = 1u64;
24 for &length in &month_days {
25 if days < length {
26 break;
27 }
28 days -= length;
29 month += 1;
30 }
31 let day = days + 1;
32 format!("{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}Z")
33}
34
35pub fn parse_timestamp_to_epoch(timestamp: &str) -> Option<u64> {
36 let parts: Vec<&str> = timestamp.split('T').collect();
37 if parts.len() != 2 {
38 return None;
39 }
40 let date_parts: Vec<u64> = parts[0].split('-').filter_map(|p| p.parse().ok()).collect();
41 if date_parts.len() != 3 {
42 return None;
43 }
44 let time_str = parts[1].trim_end_matches('Z');
45 let time_parts: Vec<u64> = time_str.split(':').filter_map(|p| p.parse().ok()).collect();
46 if time_parts.len() != 3 {
47 return None;
48 }
49 let (year, month, day) = (date_parts[0], date_parts[1], date_parts[2]);
50 let (hour, minute, second) = (time_parts[0], time_parts[1], time_parts[2]);
51 let mut total_days: u64 = 0;
52 for y in 1970..year {
53 total_days += if is_leap_year(y) { 366 } else { 365 };
54 }
55 let months = month_lengths(is_leap_year(year));
56 for &month_days in months.iter().take(month.saturating_sub(1) as usize) {
57 total_days += month_days;
58 }
59 total_days += day.saturating_sub(1);
60 Some(total_days * 86400 + hour * 3600 + minute * 60 + second)
61}
62
63fn is_leap_year(year: u64) -> bool {
64 (year.is_multiple_of(4) && !year.is_multiple_of(100)) || year.is_multiple_of(400)
65}
66
67fn month_lengths(leap: bool) -> [u64; 12] {
68 let feb = if leap { 29 } else { 28 };
69 [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
70}