use crate::*;
pub const LEAP_YEAR: [u64; 12] = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
pub const COMMON_YEAR: [u64; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
pub const DAYS: [&str; 7] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
pub const MONTHS: [&str; 12] = [
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
];
pub fn from_env_var() -> Lang {
let lang: Lang = env::var("LANG")
.unwrap_or_default()
.parse::<Lang>()
.unwrap_or_default();
lang
}
#[inline(always)]
pub fn is_leap_year(year: u64) -> bool {
(year.is_multiple_of(4) && !year.is_multiple_of(100)) || year.is_multiple_of(400)
}
pub fn time() -> String {
let (year, month, day, hour, minute, second, _, _) = calculate_time();
let mut date_time: String = String::new();
write!(
&mut date_time,
"{year:04}-{month:02}-{day:02} {hour:02}:{minute:02}:{second:02}"
)
.unwrap_or_default();
date_time
}
pub fn date() -> String {
let (year, month, day, _, _, _, _, _) = calculate_time();
let mut date_time: String = String::new();
write!(&mut date_time, "{year:04}-{month:02}-{day:02}").unwrap_or_default();
date_time
}
pub fn compute_date(mut days_since_epoch: u64) -> (u64, u64, u64) {
let mut year: u64 = 1970;
loop {
let days_in_year: u64 = if is_leap_year(year) { 366 } else { 365 };
if days_since_epoch < days_in_year {
break;
}
days_since_epoch -= days_in_year as u64;
year += 1;
}
let mut month: u64 = 0;
for (i, &days) in COMMON_YEAR.iter().enumerate() {
let days_in_month = if i == 1 && is_leap_year(year) {
days + 1
} else {
days
};
if days_since_epoch < days_in_month as u64 {
month = i as u64 + 1;
return (year, month, days_since_epoch + 1);
}
days_since_epoch -= days_in_month as u64;
}
(year, month, 1)
}
pub fn gmt() -> String {
let now: SystemTime = SystemTime::now();
let duration_since_epoch: Duration = now.duration_since(UNIX_EPOCH).unwrap();
let timestamp: u64 = duration_since_epoch.as_secs();
let seconds_in_day: u64 = 86_400;
let days_since_epoch: u64 = timestamp / seconds_in_day;
let seconds_of_day: u64 = timestamp % seconds_in_day;
let hours: u64 = seconds_of_day / 3600;
let minutes: u64 = (seconds_of_day % 3600) / 60;
let seconds: u64 = seconds_of_day % 60;
let (year, month, day) = compute_date(days_since_epoch);
let weekday: usize = ((days_since_epoch + 4) % 7) as usize;
format!(
"{}, {:02} {} {} {:02}:{:02}:{:02} GMT",
DAYS[weekday],
day,
MONTHS[month as usize - 1],
year,
hours,
minutes,
seconds
)
}
pub fn year() -> u64 {
calculate_time().0
}
pub fn month() -> u64 {
calculate_time().1
}
pub fn day() -> u64 {
calculate_time().2
}
pub fn hour() -> u64 {
calculate_time().3
}
pub fn minute() -> u64 {
calculate_time().4
}
pub fn second() -> u64 {
calculate_time().5
}
pub fn millis() -> u64 {
calculate_time().6
}
pub fn micros() -> u64 {
calculate_time().7
}
pub fn calculate_time() -> (u64, u64, u64, u64, u64, u64, u64, u64) {
let start: SystemTime = SystemTime::now();
let duration: Duration = start.duration_since(UNIX_EPOCH).unwrap();
let total_seconds: u64 = duration.as_secs();
let nanoseconds: u64 = duration.subsec_nanos() as u64;
let milliseconds: u64 = nanoseconds / 1_000_000;
let microseconds: u64 = nanoseconds / 1_000;
let mut total_days: u64 = total_seconds / 86400;
let mut year: u64 = 1970;
while total_days >= if is_leap_year(year) { 366 } else { 365 } {
total_days -= if is_leap_year(year) { 366 } else { 365 };
year += 1;
}
let mut month: u64 = 1;
let month_days: [u64; 12] = if is_leap_year(year) {
LEAP_YEAR
} else {
COMMON_YEAR
};
while total_days >= month_days[month as usize - 1] {
total_days -= month_days[month as usize - 1];
month += 1;
}
let day: u64 = total_days + 1;
let remaining_seconds: u64 = total_seconds % 86400;
let timezone_offset: u64 = from_env_var().value();
let hour: u64 = ((remaining_seconds + timezone_offset) / 3600) % 24;
let minute: u64 = (remaining_seconds % 3600) / 60;
let second: u64 = remaining_seconds % 60;
(
year,
month,
day,
hour,
minute,
second,
milliseconds,
microseconds,
)
}
pub fn time_millis() -> String {
let (year, month, day, hour, minute, second, millisecond, _) = calculate_time();
let mut date_time: String = String::new();
write!(
&mut date_time,
"{year:04}-{month:02}-{day:02} {hour:02}:{minute:02}:{second:02}.{millisecond:03}"
)
.unwrap_or_default();
date_time
}
pub fn time_micros() -> String {
let (year, month, day, hour, minute, second, _, microseconds) = calculate_time();
let mut date_time: String = String::new();
write!(
&mut date_time,
"{year:04}-{month:02}-{day:02} {hour:02}:{minute:02}:{second:02}.{microseconds:06}"
)
.unwrap_or_default();
date_time
}
pub fn timestamp() -> u64 {
let timezone_offset: u64 = from_env_var().value();
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
.saturating_add(timezone_offset)
}
pub fn timestamp_millis() -> u64 {
let timezone_offset: u64 = from_env_var().value();
let duration: Duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
(duration.as_secs().saturating_add(timezone_offset)) * 1000 + duration.subsec_millis() as u64
}
pub fn timestamp_micros() -> u64 {
let timezone_offset: u64 = from_env_var().value();
let duration: Duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
(duration.as_secs().saturating_add(timezone_offset)) * 1_000_000
+ duration.subsec_micros() as u64
}