feat: converstion method implementations

* to_datetime_constructor (internal): converts DateTime to
  DateTimeConstructor
* to_local_time: converts DateTime to DateTimeConstructor with local
  timezone
* to_universal_time: converts DateTime to DateTimeConstructor with UTC
  timezone
* to_iso_date: converts DateTime to UTC ISO 8601 string
This commit is contained in:
Erica Marigold 2023-08-23 00:20:00 +05:30
parent 5ccab5b15a
commit a53927b66b
No known key found for this signature in database
GPG key ID: 23CD97ABBBCC5ED2

View file

@ -43,6 +43,34 @@ impl DateTime {
}
}
pub fn from_universal_time(date_time: Option<DateTimeConstructor>) -> Self {
if let Some(date_time) = date_time {
let utc_time: ChronoDateTime<Utc> = Utc.from_utc_datetime(&NaiveDateTime::new(
NaiveDate::from_ymd_opt(date_time.year, date_time.month, date_time.day)
.expect("invalid date"),
NaiveTime::from_hms_milli_opt(
date_time.hour,
date_time.minute,
date_time.second,
date_time.millisecond,
)
.expect("invalid time"),
));
Self {
unix_timestamp: utc_time.timestamp(),
unix_timestamp_millis: utc_time.timestamp_millis(),
}
} else {
let utc_time = Utc::now();
Self {
unix_timestamp: utc_time.timestamp(),
unix_timestamp_millis: utc_time.timestamp_millis(),
}
}
}
pub fn from_local_time(date_time: Option<DateTimeConstructor>) -> Self {
if let Some(date_time) = date_time {
let local_time: ChronoDateTime<Local> = Local
@ -77,7 +105,8 @@ impl DateTime {
where
T: ToString,
{
let time = ChronoDateTime::parse_from_str(iso_date.to_string().as_str(), "%Y-%m-%dT%H:%M:%SZ")
let time =
ChronoDateTime::parse_from_str(iso_date.to_string().as_str(), "%Y-%m-%dT%H:%M:%SZ")
.expect("invalid ISO 8601 string");
Self {
@ -85,6 +114,52 @@ impl DateTime {
unix_timestamp_millis: time.timestamp_millis(),
}
}
fn to_datetime_constructor<T>(date_time: ChronoDateTime<T>) -> DateTimeConstructor
where
T: TimeZone,
{
let mut date_time_constructor = DateTimeConstructor::default();
// Any less tedious way to get Enum member based on index?
// I know there's some crates available with derive macros for this,
// would it be okay if used some of them?
date_time_constructor
.with_year(date_time.year())
.with_month(match date_time.month() {
1 => Month::January,
2 => Month::February,
3 => Month::March,
4 => Month::April,
5 => Month::May,
6 => Month::June,
7 => Month::July,
8 => Month::August,
9 => Month::September,
10 => Month::October,
11 => Month::November,
12 => Month::December,
_ => panic!("invalid month ordinal"),
})
.with_day(date_time.day())
.with_hour(date_time.hour())
.with_minute(date_time.minute())
.with_second(date_time.second());
date_time_constructor
}
pub fn to_local_time(&self) -> DateTimeConstructor {
Self::to_datetime_constructor(Local.timestamp_opt(self.unix_timestamp, 0).unwrap())
}
pub fn to_universal_time(&self) -> DateTimeConstructor {
Self::to_datetime_constructor(Utc.timestamp_opt(self.unix_timestamp, 0).unwrap())
}
pub fn to_iso_date(&self) -> String {
self.to_universal_time().to_iso_string(Timezone::UTC)
}
}
pub struct DateTimeConstructor {
@ -112,6 +187,7 @@ impl Default for DateTimeConstructor {
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum Month {
January,
February,
@ -127,61 +203,99 @@ pub enum Month {
December,
}
// fn match_month_to_num(month: Month) {
// match month {
// Month::January => 1,
// Month::February => 2,
// Month::March => 3,
// Month::April => 4,
// Month::May => 5,
// Month::June => 6,
// Month::July => 7,
// Month::August => 8,
// Month::September => 9,
// Month::October => 10,
// Month::November => 11,
// Month::December => 12,
// };
// }
enum Timezone {
UTC,
Local,
}
impl DateTimeConstructor {
pub fn with_year(&mut self, year: i32) -> &Self {
pub fn with_year(&mut self, year: i32) -> &mut Self {
self.year = year;
self
}
pub fn with_month(&mut self, month: Month) -> &Self {
let month = match month {
Month::January => 1,
Month::February => 2,
Month::March => 3,
Month::April => 4,
Month::May => 5,
Month::June => 6,
Month::July => 7,
Month::August => 8,
Month::September => 9,
Month::October => 10,
Month::November => 11,
Month::December => 12,
};
self.month = month;
pub fn with_month(&mut self, month: Month) -> &mut Self {
self.month = month as u32;
self
}
pub fn with_day(&mut self, day: u32) -> &Self {
pub fn with_day(&mut self, day: u32) -> &mut Self {
self.day = day;
self
}
pub fn with_hour(&mut self, hour: u32) -> &Self {
pub fn with_hour(&mut self, hour: u32) -> &mut Self {
self.hour = hour;
self
}
pub fn with_minute(&mut self, minute: u32) -> &Self {
pub fn with_minute(&mut self, minute: u32) -> &mut Self {
self.minute = minute;
self
}
pub fn with_second(&mut self, second: u32) -> &Self {
pub fn with_second(&mut self, second: u32) -> &mut Self {
self.second = second;
self
}
pub fn with_millisecond(&mut self, millisecond: u32) -> &Self {
pub fn with_millisecond(&mut self, millisecond: u32) -> &mut Self {
self.millisecond = millisecond;
self
}
fn to_iso_string(&self, timezone: Timezone) -> String {
let iso_format = "%Y-%m-%dT%H:%M:%SZ";
match timezone {
Timezone::UTC => Utc
.with_ymd_and_hms(
self.year,
self.month,
self.day,
self.hour,
self.minute,
self.second,
)
.unwrap()
.format(iso_format)
.to_string(),
Timezone::Local => Local
.with_ymd_and_hms(
self.year,
self.month,
self.day,
self.hour,
self.minute,
self.second,
)
.unwrap()
.format(iso_format)
.to_string(),
}
}
}