1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
pub const MONTHS_PER_YEAR: u32 = 12;
pub const HOURS_PER_DAY: u32 = 24;
pub const MINUTES_PER_HOUR: u32 = 60;
pub const SECONDS_PER_MINUTE: u32 = 60;
pub const USECONDS_MAX: u32 = 999_999;
pub const USECONDS_PER_DAY: i64 = 86_400_000_000;
pub const USECONDS_PER_HOUR: i64 = 3_600_000_000;
pub const USECONDS_PER_MINUTE: i64 = 60_000_000;
pub const USECONDS_PER_SECOND: i64 = 1_000_000;
pub const DATE_MIN_YEAR: i32 = 1;
pub const DATE_MAX_YEAR: i32 = 9999;
pub const UNIX_EPOCH_JULIAN: i32 = date2julian(1970, 1, 1);
pub const DATE_MIN_JULIAN: i32 = date2julian(DATE_MIN_YEAR, 1, 1);
pub const DATE_MAX_JULIAN: i32 = date2julian(DATE_MAX_YEAR, 12, 31);
pub const TIMESTAMP_MIN: i64 = (DATE_MIN_JULIAN - UNIX_EPOCH_JULIAN) as i64 * USECONDS_PER_DAY;
pub const TIMESTAMP_MAX: i64 =
(date2julian(10000, 1, 1) - UNIX_EPOCH_JULIAN) as i64 * USECONDS_PER_DAY - 1;
#[inline]
pub const fn date2julian(year: i32, month: u32, day: u32) -> i32 {
let (y, m) = if month > 2 {
(year + 4800, month + 1)
} else {
(year + 4799, month + 13)
};
let century = y / 100;
let mut julian = y * 365 - 32167;
julian += y / 4 - century + century / 4;
julian += 7834 * m as i32 / 256 + day as i32;
julian
}
#[inline]
pub const fn julian2date(julian_day: i32) -> (i32, u32, u32) {
let mut julian = julian_day as u32 + 32044;
let mut quad = julian / 146097;
let extra = (julian - quad * 146097) * 4 + 3;
julian += 60 + quad * 3 + extra / 146097;
quad = julian / 1461;
julian -= quad * 1461;
let mut y: i32 = (julian * 4 / 1461) as i32;
julian = if y != 0 {
(julian + 305) % 365 + 123
} else {
(julian + 306) % 366 + 123
};
y += (quad * 4) as i32;
let year = y - 4800;
quad = julian * 2141 / 65_536;
let day = julian - 7834 * quad / 256;
let month = (quad + 10) % MONTHS_PER_YEAR as u32 + 1;
(year, month, day)
}
#[inline(always)]
pub const fn is_valid_date(date: i32) -> bool {
date >= (DATE_MIN_JULIAN - UNIX_EPOCH_JULIAN) && date <= (DATE_MAX_JULIAN - UNIX_EPOCH_JULIAN)
}
#[inline(always)]
pub const fn is_valid_timestamp(timestamp: i64) -> bool {
timestamp >= TIMESTAMP_MIN && timestamp <= TIMESTAMP_MAX
}
#[inline(always)]
pub const fn is_valid_time(time: i64) -> bool {
time >= 0 && time < USECONDS_PER_DAY
}
#[inline(always)]
const fn is_leap_year(year: i32) -> bool {
year % 4 == 0 && ((year % 100) != 0 || (year % 400) == 0)
}
#[inline(always)]
pub const fn days_of_month(year: i32, month: u32) -> u32 {
const DAY_TABLE: [[u32; 12]; 2] = [
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
];
DAY_TABLE[is_leap_year(year) as usize][month as usize - 1]
}