use time::OffsetDateTime;
use crate::base::status::Status;
const SECONDS_OF_DAY: i64 = 60 * 60 * 24;
const MILL_SECONDS_OF_DAY: i64 = SECONDS_OF_DAY * 1000;
const EIGHT_HOUR: i64 = 60 * 60 * 8 * 1000;
#[allow(dead_code)]
pub fn cur_timestamp() -> i64 {
(OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000_000) as i64
}
#[allow(dead_code)]
pub fn next_day_begin_timestamp_from_today() -> i64 {
next_day_begin_timestamp_from(cur_timestamp())
}
#[allow(dead_code)]
pub fn next_day_begin_timestamp_from(timestamp: i64) -> i64 {
let next_day =
((timestamp + EIGHT_HOUR) / MILL_SECONDS_OF_DAY + 1) * MILL_SECONDS_OF_DAY - EIGHT_HOUR;
next_day
}
#[allow(dead_code)]
pub fn pre_day_begin_timestamp_from_today() -> i64 {
pre_day_begin_timestamp_from(cur_timestamp())
}
#[allow(dead_code)]
pub fn pre_day_begin_timestamp_from(timestamp: i64) -> i64 {
let pre_day =
(timestamp / MILL_SECONDS_OF_DAY) * MILL_SECONDS_OF_DAY - MILL_SECONDS_OF_DAY - EIGHT_HOUR;
pre_day
}
#[allow(dead_code)]
pub fn begin_timestamp_from(timestamp: i64) -> i64 {
(timestamp / MILL_SECONDS_OF_DAY) * MILL_SECONDS_OF_DAY * MILL_SECONDS_OF_DAY - EIGHT_HOUR
}
#[allow(dead_code)]
pub fn last_min_timestamp_from(timestamp: i64) -> i64 {
let day_begin_timestamp = begin_timestamp_from(timestamp);
day_begin_timestamp + MILL_SECONDS_OF_DAY - 60 * 1000
}
#[allow(dead_code)]
fn timestamp_to_local(timestamp: i64) -> i64 {
let local_offset = OffsetDateTime::now_local();
if let Ok(local) = local_offset {
return timestamp + (local.offset().whole_seconds() as i64 * 1000);
}
return timestamp;
}
#[allow(dead_code)]
pub fn ymd_from_timestamp(timestamp: i64) -> Result<(u32, u32, u32), Status> {
let local_timestamp = timestamp_to_local(timestamp);
let datetime = OffsetDateTime::from_unix_timestamp(local_timestamp / 1000);
if let Ok(date) = datetime {
Ok((date.year() as u32, date.month() as u32, date.day() as u32))
} else {
Err(Status::error("转换为 datetime 错误!".into()))
}
}
#[allow(dead_code)]
pub fn hms_from_timestamp(timestamp: i64) -> Result<(u32, u32, u32), Status> {
let local_timestamp = timestamp_to_local(timestamp);
let datetime = OffsetDateTime::from_unix_timestamp(local_timestamp / 1000);
if let Ok(date) = datetime {
Ok((
date.hour() as u32,
date.minute() as u32,
date.second() as u32,
))
} else {
Err(Status::error("转换为 datetime 错误!".into()))
}
}
fn fill_buffer(
format: &str,
match_char: char,
time_no: i32,
buffer: &mut [u8],
cur_index: &mut usize,
) {
let mut symbol_num = 0;
while *cur_index < format.len() {
let ch = format.chars().nth(*cur_index).unwrap();
if ch == match_char {
symbol_num += 1;
} else {
*cur_index -= 1;
break;
}
*cur_index += 1;
}
if *cur_index == format.len() {
*cur_index -= 1;
}
let mut begin = 1;
for j in 0..symbol_num {
buffer[*cur_index - j] = (time_no / begin % 10) as u8 + 48;
begin *= 10;
}
}
#[allow(dead_code)]
pub fn time_to_str(
format: &str,
year: i32,
month: i32,
day: i32,
hour: i32,
minutes: i32,
seconds: i32,
millisecond: i32,
) -> String {
let format_chars: Vec<char> = format.chars().collect();
let mut buffer: Vec<u8> = vec![0; format_chars.len()];
let format_len = format.len();
let mut cur_index = 0;
while cur_index < format_len {
let ch = format_chars[cur_index];
match ch {
'y' => fill_buffer(format, ch, year, &mut buffer, &mut cur_index),
'M' => fill_buffer(format, ch, month, &mut buffer, &mut cur_index),
'd' => fill_buffer(format, ch, day, &mut buffer, &mut cur_index),
'h' => fill_buffer(format, ch, hour, &mut buffer, &mut cur_index),
'm' => fill_buffer(format, ch, minutes, &mut buffer, &mut cur_index),
's' => fill_buffer(format, ch, seconds, &mut buffer, &mut cur_index),
'S' => fill_buffer(format, ch, millisecond, &mut buffer, &mut cur_index),
_ => buffer[cur_index] = ch as u8,
}
cur_index += 1;
}
unsafe { String::from_utf8_unchecked(buffer) }
}
#[allow(dead_code)]
pub fn timestamp_to_string(format: &str, timestamp: i64) -> String {
let local_timestamp = timestamp_to_local(timestamp);
let datetime = OffsetDateTime::from_unix_timestamp(local_timestamp / 1000);
if let Ok(date) = datetime {
let second_timestamp = local_timestamp / 1000;
let millisecond = (local_timestamp - second_timestamp * 1000) as i32;
time_to_str(
format,
date.year(),
date.month() as i32,
date.day() as i32,
date.hour() as i32,
date.minute() as i32,
date.second() as i32,
millisecond,
)
} else {
"--".to_string()
}
}
#[allow(dead_code)]
pub fn cur_time_str_with_format(format: &str) -> String {
timestamp_to_string(format, cur_timestamp())
}
#[allow(dead_code)]
pub fn cur_time_str() -> String {
cur_time_str_with_format("yyyy-MM-dd hh:mm:ss.SSS")
}
fn buffer_to_number(
format: &str,
str: &str,
match_char: char,
format_len: usize,
time_no: &mut i32,
cur_index: &mut usize,
) {
let mut ch: char;
let mut c_ch: char;
*time_no = 0;
let mut has_val = false;
while *cur_index < format_len {
ch = format.chars().nth(*cur_index).unwrap();
c_ch = str.chars().nth(*cur_index).unwrap();
if ch != match_char || !c_ch.is_ascii_digit() {
if has_val {
*cur_index -= 1;
}
break;
}
has_val = true;
*time_no *= 10;
*time_no += c_ch as i32 - '0' as i32;
*cur_index += 1;
}
}
pub fn str_to_time(format: &str, string: &str) -> Option<(i32, i32, i32, i32, i32, i32, i32)> {
let mut year = 0;
let mut month = 0;
let mut day = 0;
let mut hour = 0;
let mut minutes = 0;
let mut seconds = 0;
let mut millisecond = 0;
let format_len = format.len();
let str_len = string.len();
if str_len < format_len {
return None;
}
let mut cur_index = 0;
while cur_index < format_len {
let ch = format.chars().nth(cur_index).unwrap();
match ch {
'y' => buffer_to_number(format, string, ch, format_len, &mut year, &mut cur_index),
'M' => buffer_to_number(format, string, ch, format_len, &mut month, &mut cur_index),
'd' => buffer_to_number(format, string, ch, format_len, &mut day, &mut cur_index),
'h' => buffer_to_number(format, string, ch, format_len, &mut hour, &mut cur_index),
'm' => buffer_to_number(format, string, ch, format_len, &mut minutes, &mut cur_index),
's' => buffer_to_number(format, string, ch, format_len, &mut seconds, &mut cur_index),
'S' => buffer_to_number(
format,
string,
ch,
format_len,
&mut millisecond,
&mut cur_index,
),
_ => {
if ch != string.chars().nth(cur_index).unwrap() {
return None;
}
}
}
cur_index += 1;
}
Some((year, month, day, hour, minutes, seconds, millisecond))
}