From 15722ec5d2fdde125c29be405b7ee10497265596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 6 Dec 2020 12:29:12 +0200 Subject: [PATCH] gstreamer/datetime: Check invariants on the bindings side instead of asserting in the C code Newer versions of GStreamer (1.20 and above) will not assert any longer but handle it more gracefully, so let's do the same here for all versions. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/297 --- gstreamer/Gir.toml | 80 ++++++- gstreamer/src/auto/date_time.rs | 122 ++--------- gstreamer/src/date_time.rs | 352 +++++++++++++++++++++++++++---- gstreamer/src/date_time_serde.rs | 39 ++-- 4 files changed, 437 insertions(+), 156 deletions(-) diff --git a/gstreamer/Gir.toml b/gstreamer/Gir.toml index ee2795f58..a40825995 100644 --- a/gstreamer/Gir.toml +++ b/gstreamer/Gir.toml @@ -1654,9 +1654,63 @@ status = "generate" [[object.function]] name = "new" - [object.function.return] - nullable = true - nullable_return_is_error = "Can't create DateTime" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "new_local_time" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "new_y" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "new_ym" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "new_ymd" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "get_month" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "get_day" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "get_hour" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "get_minute" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "get_second" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "get_microsecond" + # Needs manual checking of invariants + manual = true + + [[object.function]] + name = "get_time_zone_offset" + # Needs manual checking of invariants + manual = true [[object.function]] name = "new_y" @@ -1696,6 +1750,26 @@ status = "generate" [object.function.return] nullable_return_is_error = "Failed to create ISO-8601 string from DateTime" + [[object.function]] + name = "new_from_unix_epoch_local_time" + [object.function.return] + nullable_return_is_error = "Can't create DateTime from UNIX epoch" + + [[object.function]] + name = "new_from_unix_epoch_local_time_usecs" + [object.function.return] + nullable_return_is_error = "Can't create DateTime from UNIX epoch" + + [[object.function]] + name = "new_from_unix_epoch_utc" + [object.function.return] + nullable_return_is_error = "Can't create DateTime from UNIX epoch" + + [[object.function]] + name = "new_from_unix_epoch_utc_usecs" + [object.function.return] + nullable_return_is_error = "Can't create DateTime from UNIX epoch" + [[object]] name = "Gst.ControlSource" status = "generate" diff --git a/gstreamer/src/auto/date_time.rs b/gstreamer/src/auto/date_time.rs index 7a4cdb704..f8ee0e15e 100644 --- a/gstreamer/src/auto/date_time.rs +++ b/gstreamer/src/auto/date_time.rs @@ -16,24 +16,6 @@ glib::glib_wrapper! { } impl DateTime { - pub fn new( - tzoffset: f32, - year: i32, - month: i32, - day: i32, - hour: i32, - minute: i32, - seconds: f64, - ) -> Result { - assert_initialized_main_thread!(); - unsafe { - Option::<_>::from_glib_full(ffi::gst_date_time_new( - tzoffset, year, month, day, hour, minute, seconds, - )) - .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) - } - } - pub fn from_g_date_time(dt: &glib::DateTime) -> Result { assert_initialized_main_thread!(); unsafe { @@ -52,47 +34,41 @@ impl DateTime { } } - pub fn from_unix_epoch_local_time(secs: i64) -> Option { - assert_initialized_main_thread!(); - unsafe { from_glib_full(ffi::gst_date_time_new_from_unix_epoch_local_time(secs)) } - } - - #[cfg(any(feature = "v1_18", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] - pub fn from_unix_epoch_local_time_usecs(usecs: i64) -> Option { + pub fn from_unix_epoch_local_time(secs: i64) -> Result { assert_initialized_main_thread!(); unsafe { - from_glib_full(ffi::gst_date_time_new_from_unix_epoch_local_time_usecs( - usecs, - )) + Option::<_>::from_glib_full(ffi::gst_date_time_new_from_unix_epoch_local_time(secs)) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime from UNIX epoch")) } } - pub fn from_unix_epoch_utc(secs: i64) -> Option { + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + pub fn from_unix_epoch_local_time_usecs(usecs: i64) -> Result { assert_initialized_main_thread!(); - unsafe { from_glib_full(ffi::gst_date_time_new_from_unix_epoch_utc(secs)) } + unsafe { + Option::<_>::from_glib_full(ffi::gst_date_time_new_from_unix_epoch_local_time_usecs( + usecs, + )) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime from UNIX epoch")) + } + } + + pub fn from_unix_epoch_utc(secs: i64) -> Result { + assert_initialized_main_thread!(); + unsafe { + Option::<_>::from_glib_full(ffi::gst_date_time_new_from_unix_epoch_utc(secs)) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime from UNIX epoch")) + } } #[cfg(any(feature = "v1_18", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] - pub fn from_unix_epoch_utc_usecs(usecs: i64) -> Option { - assert_initialized_main_thread!(); - unsafe { from_glib_full(ffi::gst_date_time_new_from_unix_epoch_utc_usecs(usecs)) } - } - - pub fn new_local_time( - year: i32, - month: i32, - day: i32, - hour: i32, - minute: i32, - seconds: f64, - ) -> Option { + pub fn from_unix_epoch_utc_usecs(usecs: i64) -> Result { assert_initialized_main_thread!(); unsafe { - from_glib_full(ffi::gst_date_time_new_local_time( - year, month, day, hour, minute, seconds, - )) + Option::<_>::from_glib_full(ffi::gst_date_time_new_from_unix_epoch_utc_usecs(usecs)) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime from UNIX epoch")) } } @@ -106,58 +82,6 @@ impl DateTime { unsafe { from_glib_full(ffi::gst_date_time_new_now_utc()) } } - pub fn new_y(year: i32) -> Result { - assert_initialized_main_thread!(); - unsafe { - Option::<_>::from_glib_full(ffi::gst_date_time_new_y(year)) - .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) - } - } - - pub fn new_ym(year: i32, month: i32) -> Result { - assert_initialized_main_thread!(); - unsafe { - Option::<_>::from_glib_full(ffi::gst_date_time_new_ym(year, month)) - .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) - } - } - - pub fn new_ymd(year: i32, month: i32, day: i32) -> Result { - assert_initialized_main_thread!(); - unsafe { - Option::<_>::from_glib_full(ffi::gst_date_time_new_ymd(year, month, day)) - .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) - } - } - - pub fn get_day(&self) -> i32 { - unsafe { ffi::gst_date_time_get_day(self.to_glib_none().0) } - } - - pub fn get_hour(&self) -> i32 { - unsafe { ffi::gst_date_time_get_hour(self.to_glib_none().0) } - } - - pub fn get_microsecond(&self) -> i32 { - unsafe { ffi::gst_date_time_get_microsecond(self.to_glib_none().0) } - } - - pub fn get_minute(&self) -> i32 { - unsafe { ffi::gst_date_time_get_minute(self.to_glib_none().0) } - } - - pub fn get_month(&self) -> i32 { - unsafe { ffi::gst_date_time_get_month(self.to_glib_none().0) } - } - - pub fn get_second(&self) -> i32 { - unsafe { ffi::gst_date_time_get_second(self.to_glib_none().0) } - } - - pub fn get_time_zone_offset(&self) -> f32 { - unsafe { ffi::gst_date_time_get_time_zone_offset(self.to_glib_none().0) } - } - pub fn get_year(&self) -> i32 { unsafe { ffi::gst_date_time_get_year(self.to_glib_none().0) } } diff --git a/gstreamer/src/date_time.rs b/gstreamer/src/date_time.rs index d86b2d480..67242297e 100644 --- a/gstreamer/src/date_time.rs +++ b/gstreamer/src/date_time.rs @@ -6,13 +6,291 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use glib::translate::*; use std::cmp; use std::convert; use std::fmt; use crate::DateTime; +// Validate that the given values result in a valid DateTime +fn validate( + tzoffset: Option, + year: i32, + month: Option, + day: Option, + hour: Option, + minute: Option, + seconds: Option, +) -> Result<(), glib::BoolError> { + skip_assert_initialized!(); + + // Check for valid ranges + if year <= 0 || year > 9999 { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Year out of range" + )); + } + + if let Some(month) = month { + if month <= 0 || month > 12 { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Month out of range" + )); + } + } + + if let Some(day) = day { + if day <= 0 || day > 31 { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Day out of range" + )); + } + } + + if let Some(hour) = hour { + if hour < 0 || hour >= 24 { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Hour out of range" + )); + } + } + + if let Some(minute) = minute { + if minute < 0 || minute >= 60 { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Minute out of range" + )); + } + } + + if let Some(seconds) = seconds { + if seconds < 0.0 || seconds >= 60.0 { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Seconds out of range" + )); + } + } + + if let Some(tzoffset) = tzoffset { + if tzoffset < -12.0 || tzoffset > 12.0 { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Timezone offset out of range" + )); + } + } + + // If day is provided, month also has to be provided + if day.is_some() && month.is_none() { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Need to provide month if providing day" + )); + } + + // If hour is provided, day also has to be provided + if hour.is_some() && day.is_none() { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Need to provide day if providing hour" + )); + } + + // If minutes are provided, hours also need to be provided and the other way around + if hour.is_none() && minute.is_some() { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Need to provide both hour and minute or neither" + )); + } + + if minute.is_some() && hour.is_none() { + return Err(glib::glib_bool_error!( + "Can't create DateTime: Need to provide both hour and minute or neither" + )); + } + + // If seconds or tzoffset are provided then also hours and minutes must be provided + if (seconds.is_some() || tzoffset.is_some()) && (hour.is_none() || minute.is_none()) { + return Err(glib::glib_bool_error!("Can't create DateTime: Need to provide hour and minute if providing seconds or timezone offset")); + } + + Ok(()) +} + impl DateTime { + pub fn new< + TZ: Into>, + Y: Into, + MO: Into>, + D: Into>, + H: Into>, + MI: Into>, + S: Into>, + >( + tzoffset: TZ, + year: Y, + month: MO, + day: D, + hour: H, + minute: MI, + seconds: S, + ) -> Result { + assert_initialized_main_thread!(); + + let tzoffset = tzoffset.into(); + let year = year.into(); + let month = month.into(); + let day = day.into(); + let hour = hour.into(); + let minute = minute.into(); + let seconds = seconds.into(); + + validate(tzoffset, year, month, day, hour, minute, seconds)?; + + unsafe { + Option::<_>::from_glib_full(ffi::gst_date_time_new( + tzoffset.unwrap_or(0.0), + year, + month.unwrap_or(-1), + day.unwrap_or(-1), + hour.unwrap_or(-1), + minute.unwrap_or(-1), + seconds.unwrap_or(-1.0), + )) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) + } + } + + pub fn new_local_time< + Y: Into, + MO: Into>, + D: Into>, + H: Into>, + MI: Into>, + S: Into>, + >( + year: Y, + month: MO, + day: D, + hour: H, + minute: MI, + seconds: S, + ) -> Result { + assert_initialized_main_thread!(); + + let year = year.into(); + let month = month.into(); + let day = day.into(); + let hour = hour.into(); + let minute = minute.into(); + let seconds = seconds.into(); + + validate(None, year, month, day, hour, minute, seconds)?; + + unsafe { + Option::<_>::from_glib_full(ffi::gst_date_time_new_local_time( + year, + month.unwrap_or(-1), + day.unwrap_or(-1), + hour.unwrap_or(-1), + minute.unwrap_or(-1), + seconds.unwrap_or(-1.0), + )) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) + } + } + + pub fn new_y(year: i32) -> Result { + assert_initialized_main_thread!(); + + validate(None, year, None, None, None, None, None)?; + + unsafe { + Option::<_>::from_glib_full(ffi::gst_date_time_new_y(year)) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) + } + } + + pub fn new_ym(year: i32, month: i32) -> Result { + assert_initialized_main_thread!(); + + validate(None, year, Some(month), None, None, None, None)?; + + unsafe { + Option::<_>::from_glib_full(ffi::gst_date_time_new_ym(year, month)) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) + } + } + + pub fn new_ymd(year: i32, month: i32, day: i32) -> Result { + assert_initialized_main_thread!(); + + validate(None, year, Some(month), Some(day), None, None, None)?; + + unsafe { + Option::<_>::from_glib_full(ffi::gst_date_time_new_ymd(year, month, day)) + .ok_or_else(|| glib::glib_bool_error!("Can't create DateTime")) + } + } + + pub fn get_day(&self) -> Option { + if !self.has_day() { + return None; + } + + unsafe { Some(ffi::gst_date_time_get_day(self.to_glib_none().0)) } + } + + pub fn get_hour(&self) -> Option { + if !self.has_time() { + return None; + } + + unsafe { Some(ffi::gst_date_time_get_hour(self.to_glib_none().0)) } + } + + pub fn get_microsecond(&self) -> Option { + if !self.has_second() { + return None; + } + + unsafe { Some(ffi::gst_date_time_get_microsecond(self.to_glib_none().0)) } + } + + pub fn get_minute(&self) -> Option { + if !self.has_time() { + return None; + } + + unsafe { Some(ffi::gst_date_time_get_minute(self.to_glib_none().0)) } + } + + pub fn get_month(&self) -> Option { + if !self.has_month() { + return None; + } + + unsafe { Some(ffi::gst_date_time_get_month(self.to_glib_none().0)) } + } + + pub fn get_second(&self) -> Option { + if !self.has_second() { + return None; + } + + unsafe { Some(ffi::gst_date_time_get_second(self.to_glib_none().0)) } + } + + pub fn get_time_zone_offset(&self) -> Option { + if !self.has_time() { + return None; + } + + unsafe { + Some(ffi::gst_date_time_get_time_zone_offset( + self.to_glib_none().0, + )) + } + } + pub fn to_utc(&self) -> Result { if !self.has_time() { // No time => no TZ offset @@ -43,7 +321,7 @@ impl DateTime { self.get_day(), self.get_hour(), self.get_minute(), - 0f64, + Some(0.0), ) .and_then(|d| d.to_g_date_time()) .and_then(|d| { @@ -52,13 +330,13 @@ impl DateTime { }) .and_then(|d| { DateTime::new( - 0f32, // UTC TZ offset + None, // UTC TZ offset d.get_year(), - d.get_month(), - d.get_day_of_month(), - d.get_hour(), - d.get_minute(), - -1f64, // No second + Some(d.get_month()), + Some(d.get_day_of_month()), + Some(d.get_hour()), + Some(d.get_minute()), + None, // No second ) }) } @@ -121,7 +399,7 @@ impl cmp::PartialOrd for DateTime { return None; } - let month_delta = self_norm.get_month() - other_norm.get_month(); + let month_delta = self_norm.get_month().unwrap() - other_norm.get_month().unwrap(); if month_delta != 0 { return get_cmp(month_delta); } @@ -138,7 +416,7 @@ impl cmp::PartialOrd for DateTime { return None; } - let day_delta = self_norm.get_day() - other_norm.get_day(); + let day_delta = self_norm.get_day().unwrap() - other_norm.get_day().unwrap(); if day_delta != 0 { return get_cmp(day_delta); } @@ -155,12 +433,12 @@ impl cmp::PartialOrd for DateTime { return None; } - let hour_delta = self_norm.get_hour() - other_norm.get_hour(); + let hour_delta = self_norm.get_hour().unwrap() - other_norm.get_hour().unwrap(); if hour_delta != 0 { return get_cmp(hour_delta); } - let minute_delta = self_norm.get_minute() - other_norm.get_minute(); + let minute_delta = self_norm.get_minute().unwrap() - other_norm.get_minute().unwrap(); if minute_delta != 0 { return get_cmp(minute_delta); } @@ -176,12 +454,12 @@ impl cmp::PartialOrd for DateTime { // One has second, the other doesn't => can't compare (note 1) return None; } - let second_delta = self_norm.get_second() - other_norm.get_second(); + let second_delta = self_norm.get_second().unwrap() - other_norm.get_second().unwrap(); if second_delta != 0 { return get_cmp(second_delta); } - get_cmp(self_norm.get_microsecond() - other_norm.get_microsecond()) + get_cmp(self_norm.get_microsecond().unwrap() - other_norm.get_microsecond().unwrap()) } } @@ -281,12 +559,12 @@ mod tests { .to_utc() .unwrap(); assert_eq!(utc_date_time.get_year(), 2019); - assert_eq!(utc_date_time.get_month(), 8); - assert_eq!(utc_date_time.get_day(), 20); - assert_eq!(utc_date_time.get_hour(), 18); - assert_eq!(utc_date_time.get_minute(), 9); - assert_eq!(utc_date_time.get_second(), 42); - assert_eq!(utc_date_time.get_microsecond(), 123_456); + assert_eq!(utc_date_time.get_month().unwrap(), 8); + assert_eq!(utc_date_time.get_day().unwrap(), 20); + assert_eq!(utc_date_time.get_hour().unwrap(), 18); + assert_eq!(utc_date_time.get_minute().unwrap(), 9); + assert_eq!(utc_date_time.get_second().unwrap(), 42); + assert_eq!(utc_date_time.get_microsecond().unwrap(), 123_456); // Year, month, day and hour offset let utc_date_time = DateTime::new(2f32, 2019, 1, 1, 0, 0, 42.123_456f64) @@ -294,31 +572,31 @@ mod tests { .to_utc() .unwrap(); assert_eq!(utc_date_time.get_year(), 2018); - assert_eq!(utc_date_time.get_month(), 12); - assert_eq!(utc_date_time.get_day(), 31); - assert_eq!(utc_date_time.get_hour(), 22); - assert_eq!(utc_date_time.get_minute(), 0); - assert_eq!(utc_date_time.get_second(), 42); - assert_eq!(utc_date_time.get_microsecond(), 123_456); + assert_eq!(utc_date_time.get_month().unwrap(), 12); + assert_eq!(utc_date_time.get_day().unwrap(), 31); + assert_eq!(utc_date_time.get_hour().unwrap(), 22); + assert_eq!(utc_date_time.get_minute().unwrap(), 0); + assert_eq!(utc_date_time.get_second().unwrap(), 42); + assert_eq!(utc_date_time.get_microsecond().unwrap(), 123_456); // Date without an hour (which implies no TZ) let utc_date_time = DateTime::new_ymd(2019, 1, 1).unwrap().to_utc().unwrap(); assert_eq!(utc_date_time.get_year(), 2019); - assert_eq!(utc_date_time.get_month(), 1); - assert_eq!(utc_date_time.get_day(), 1); + assert_eq!(utc_date_time.get_month().unwrap(), 1); + assert_eq!(utc_date_time.get_day().unwrap(), 1); assert!(!utc_date_time.has_time()); assert!(!utc_date_time.has_second()); // Date without seconds - let utc_date_time = DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64) + let utc_date_time = DateTime::new(2f32, 2018, 5, 28, 16, 6, None) .unwrap() .to_utc() .unwrap(); assert_eq!(utc_date_time.get_year(), 2018); - assert_eq!(utc_date_time.get_month(), 5); - assert_eq!(utc_date_time.get_day(), 28); - assert_eq!(utc_date_time.get_hour(), 14); - assert_eq!(utc_date_time.get_minute(), 6); + assert_eq!(utc_date_time.get_month().unwrap(), 5); + assert_eq!(utc_date_time.get_day().unwrap(), 28); + assert_eq!(utc_date_time.get_hour().unwrap(), 14); + assert_eq!(utc_date_time.get_minute().unwrap(), 6); assert!(!utc_date_time.has_second()); } @@ -442,8 +720,8 @@ mod tests { ); assert_eq!( - DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap(), - DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap() + DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap(), + DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap() ); assert_eq!( @@ -456,16 +734,16 @@ mod tests { // but they are not equal (note 1) assert_ne!( DateTime::new_ymd(2018, 5, 28).unwrap(), - DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap() + DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap() ); assert_ne!( - DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap(), + DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap(), DateTime::new_ym(2018, 5).unwrap() ); assert_ne!( - DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap(), + DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap(), DateTime::new_y(2018).unwrap() ); } diff --git a/gstreamer/src/date_time_serde.rs b/gstreamer/src/date_time_serde.rs index 7fea3a9fa..436906f35 100644 --- a/gstreamer/src/date_time_serde.rs +++ b/gstreamer/src/date_time_serde.rs @@ -73,26 +73,31 @@ impl<'a> Serialize for DateTime { let variant = if self.has_second() { DateTimeVariants::YMDhmsTz( self.get_year(), - self.get_month(), - self.get_day(), - self.get_hour(), - self.get_minute(), - f64::from(self.get_second()) + f64::from(self.get_microsecond()) / 1_000_000f64, - self.get_time_zone_offset(), + self.get_month().unwrap(), + self.get_day().unwrap(), + self.get_hour().unwrap(), + self.get_minute().unwrap(), + f64::from(self.get_second().unwrap()) + + f64::from(self.get_microsecond().unwrap()) / 1_000_000f64, + self.get_time_zone_offset().unwrap(), ) } else if self.has_time() { DateTimeVariants::YMDhmTz( self.get_year(), - self.get_month(), - self.get_day(), - self.get_hour(), - self.get_minute(), - self.get_time_zone_offset(), + self.get_month().unwrap(), + self.get_day().unwrap(), + self.get_hour().unwrap(), + self.get_minute().unwrap(), + self.get_time_zone_offset().unwrap(), ) } else if self.has_day() { - DateTimeVariants::YMD(self.get_year(), self.get_month(), self.get_day()) + DateTimeVariants::YMD( + self.get_year(), + self.get_month().unwrap(), + self.get_day().unwrap(), + ) } else if self.has_month() { - DateTimeVariants::YM(self.get_year(), self.get_month()) + DateTimeVariants::YM(self.get_year(), self.get_month().unwrap()) } else if self.has_year() { DateTimeVariants::Y(self.get_year()) } else { @@ -152,7 +157,7 @@ impl TryFrom for DateTime { DateTimeVariants::YM(y, m) => DateTime::new_ym(y, m), DateTimeVariants::YMD(y, m, d) => DateTime::new_ymd(y, m, d), DateTimeVariants::YMDhmTz(y, m, d, h, mn, tz) => { - DateTime::new(tz, y, m, d, h, mn, -1f64) + DateTime::new(tz, y, m, d, h, mn, None) } DateTimeVariants::YMDhmsTz(y, m, d, h, mn, s, tz) => { DateTime::new(tz, y, m, d, h, mn, s) @@ -193,7 +198,7 @@ mod tests { res ); - let datetime = DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap(); + let datetime = DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap(); let res = ron::ser::to_string_pretty(&datetime, pretty_config.clone()); assert_eq!(Ok("YMDhmTz(2018, 5, 28, 16, 6, 2)".to_owned()), res,); @@ -232,7 +237,7 @@ mod tests { let datetime_de: DateTime = ron::de::from_str(datetime_ron).unwrap(); assert_eq!( datetime_de, - DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap() + DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap() ); let datetime_ron = "YMD(2018, 5, 28)"; @@ -257,7 +262,7 @@ mod tests { let datetime_de: DateTime = ron::de::from_str(datetime_ser.as_str()).unwrap(); assert_eq!(datetime_de, datetime); - let datetime = DateTime::new(2f32, 2018, 5, 28, 16, 6, -1f64).unwrap(); + let datetime = DateTime::new(2f32, 2018, 5, 28, 16, 6, None).unwrap(); let datetime_ser = ron::ser::to_string(&datetime).unwrap(); let datetime_de: DateTime = ron::de::from_str(datetime_ser.as_str()).unwrap(); assert_eq!(datetime_de, datetime);