use crate::error::InvalidArgumentError;
use chrono::{DateTime, Datelike, Days, Months, NaiveDateTime, Offset, TimeZone, Utc, Weekday};
use chrono_tz::Tz;
pub fn local_datetime_to_utc(
datetime: &str,
pattern: &str,
timezone: &Tz,
) -> Result<DateTime<Utc>, InvalidArgumentError> {
let naive_datetime = NaiveDateTime::parse_from_str(datetime, pattern);
if naive_datetime.is_err() {
let err = naive_datetime.as_ref().unwrap_err();
println!("parse_from_str error => {:#?}", err);
return Err(InvalidArgumentError::new(format!("{err:#?}").as_ref()));
}
Ok({
let offset = timezone.offset_from_utc_datetime(naive_datetime.as_ref().unwrap());
let fixed = offset.fix();
Utc.from_utc_datetime(
&fixed
.from_local_datetime(naive_datetime.as_ref().unwrap())
.unwrap()
.naive_utc(),
)
})
}
pub fn utc_datetime_to_local(
datetime: &str,
pattern: &str,
timezone: &Tz,
) -> Result<NaiveDateTime, InvalidArgumentError> {
let utc_datetime = NaiveDateTime::parse_from_str(datetime, pattern);
if utc_datetime.is_err() {
let err = utc_datetime.as_ref().unwrap_err();
println!("parse_from_str error => {:#?}", err);
return Err(InvalidArgumentError::new(format!("{err:#?}").as_ref()));
}
Ok({
let utc_datetime = utc_datetime.unwrap();
let offset = timezone.offset_from_local_datetime(&utc_datetime).unwrap();
let fixed = offset.fix();
fixed.from_utc_datetime(&utc_datetime).naive_local()
})
}
pub fn get_latest_day<T: TimeZone + Sized>(datetime: &DateTime<T>) -> u32 {
let mut dummy = DateTime::from_timestamp(datetime.timestamp(), 0).unwrap();
dummy = dummy.checked_add_months(Months::new(1)).unwrap();
dummy = dummy.with_day(1).unwrap();
dummy = dummy.checked_sub_days(Days::new(1)).unwrap();
dummy.day()
}
pub fn get_week_start_end(datetime: &NaiveDateTime) -> (NaiveDateTime, NaiveDateTime) {
let current_day_of_week = datetime.weekday();
let days_since = current_day_of_week.days_since(Weekday::Mon);
let mut monday = datetime.clone();
monday = monday
.checked_sub_days(Days::new(days_since as u64))
.unwrap();
let mut sunday = monday.clone();
sunday = sunday.checked_add_days(Days::new(6)).unwrap();
(monday, sunday)
}
#[cfg(test)]
mod tests {
use crate::date_util::{
get_latest_day, get_week_start_end, local_datetime_to_utc, utc_datetime_to_local,
};
use chrono::{
DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Timelike, Utc,
};
use chrono_tz::Tz;
#[test]
fn local_datetime_to_utc_test() {
let str_datetime = "20241122095445"; let pattern = "%Y%m%d%H%M%S";
let timezone = Tz::Asia__Seoul;
let result = local_datetime_to_utc(str_datetime, pattern, &timezone);
assert!(
result.is_ok(),
"{}",
format!("변환 실패 : {:#?}", result.as_ref().unwrap_err())
);
let result = result.unwrap();
println!("utc result => {:#?}", result);
assert_eq!(2024, result.year());
assert_eq!(11, result.month());
assert_eq!(22, result.day());
assert_eq!(0, result.hour());
assert_eq!(54, result.minute());
assert_eq!(45, result.second());
}
#[test]
fn utc_datetime_to_local_test() {
let utc_datetime = "20241122225445";
let patter = "%Y%m%d%H%M%S";
let timezone = Tz::Asia__Seoul;
let result = utc_datetime_to_local(utc_datetime, patter, &timezone);
assert!(
result.is_ok(),
"{}",
format!("변환 실패 : {:#?}", result.as_ref().unwrap_err())
);
let result = result.unwrap();
println!("local result => {:#?}", result);
assert_eq!(2024, result.year());
assert_eq!(11, result.month());
assert_eq!(23, result.day());
assert_eq!(7, result.hour());
assert_eq!(54, result.minute());
assert_eq!(45, result.second());
}
#[test]
fn get_latest_day_test() {
let utc_leap_datetime: DateTime<Utc> =
Utc.with_ymd_and_hms(2024, 2, 11, 13, 27, 0).unwrap();
let latest_day = get_latest_day(&utc_leap_datetime);
assert_eq!(29, latest_day);
let utc_datetime = Utc.with_ymd_and_hms(2025, 2, 11, 13, 27, 0).unwrap();
let latest_day = get_latest_day(&utc_datetime);
assert_eq!(28, latest_day);
}
#[test]
fn get_week_start_end_test() {
let datetime = NaiveDateTime::new(
NaiveDate::from_ymd_opt(1978, 6, 22).unwrap(),
NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
);
let (monday, sunday) = get_week_start_end(&datetime);
assert_eq!(1978, monday.year());
assert_eq!(6, monday.month());
assert_eq!(19, monday.day());
assert_eq!(6, sunday.month());
assert_eq!(25, sunday.day());
}
}