1use std::ops::Range;
2
3pub use coarsetime::{self, Clock, Duration};
4use num_traits::cast::AsPrimitive;
5
6pub const DAY: i64 = 86400;
7
8pub fn readable(n: u64) -> String {
9 if n < 100 {
10 format!("{}s", n)
11 } else if n < 100 * 60 {
12 format!("{}m", n / 60)
13 } else if n < 100 * 60 * 60 {
14 format!("{}h", n / 3600)
15 } else {
16 format!("{}d", n / 86400)
17 }
18}
19
20pub fn now() -> Duration {
21 Clock::now_since_epoch()
22}
23
24pub fn sec() -> u64 {
25 now().as_secs()
26}
27
28pub fn ms() -> u64 {
29 now().as_millis()
30}
31
32pub fn nano() -> u64 {
33 now().as_nanos()
34}
35
36pub fn min() -> u64 {
37 now().as_mins()
38}
39
40pub fn hour() -> u64 {
41 now().as_hours()
42}
43
44pub fn day() -> u64 {
45 now().as_days()
46}
47
48pub fn day_month(day: impl AsPrimitive<i32>) -> i32 {
49 sec_month((day.as_() as i64) * DAY)
50}
51
52pub fn sec_month(sec: impl AsPrimitive<i64>) -> i32 {
53 use chrono::{DateTime, Datelike, Utc};
54
55 let datetime: DateTime<Utc> = DateTime::from_timestamp(sec.as_(), 0).unwrap();
56 let year = datetime.year();
57 let month = datetime.month() as i32;
58 ym_n(year, month)
59}
60
61pub fn ym_n(year: i32, month: i32) -> i32 {
62 (year - 1970) * 12 + month
63}
64
65pub fn n_ym(n: i32) -> (i32, i32) {
66 let n = n - 1;
67 let year = 1970 + n / 12;
68 let month = 1 + n % 12;
69 (year, month)
70}
71
72pub fn now_month() -> i32 {
73 sec_month(sec())
74}
75
76pub fn month_sec(month: i32) -> Range<i64> {
78 use chrono::{TimeZone, Utc};
79 let month = month - 1;
80 let year = 1970 + month / 12;
81 let month = (month % 12 + 1) as u32;
82
83 let this_month_start = Utc.with_ymd_and_hms(year, month, 1, 0, 0, 0).unwrap();
84 let next_month_start = if month == 12 {
85 Utc.with_ymd_and_hms(year + 1, 1, 1, 0, 0, 0)
86 } else {
87 Utc.with_ymd_and_hms(year, month + 1, 1, 0, 0, 0)
88 }
89 .unwrap();
90
91 let this_month_start_sec = this_month_start.timestamp();
92 let this_month_end_sec = next_month_start.timestamp();
93
94 this_month_start_sec..this_month_end_sec
95}
96
97pub fn month_day(month: i32) -> Range<i32> {
98 let r = month_sec(month);
99 ((r.start / DAY) as i32)..((r.end / DAY) as i32)
100}
101
102pub fn now_month_day() -> Range<i32> {
103 use chrono::{DateTime, Datelike, TimeZone, Utc};
104 let now: DateTime<Utc> = DateTime::from_timestamp(sec() as _, 0).unwrap();
105 let begin = now.with_day(1).unwrap();
106 let begin = begin.timestamp() / 86400;
107 let year = now.year();
108 let month = now.month();
109 let next_month_start = if month == 12 {
110 Utc.with_ymd_and_hms(year + 1, 1, 1, 0, 0, 0)
111 } else {
112 Utc.with_ymd_and_hms(year, month + 1, 1, 0, 0, 0)
113 }
114 .unwrap();
115
116 let end = next_month_start.timestamp() / 86400;
117 (begin as i32)..(end as i32)
118}