diff --git a/sdk/core/Cargo.toml b/sdk/core/Cargo.toml index cc6605cf0ba..b8f82aa3393 100644 --- a/sdk/core/Cargo.toml +++ b/sdk/core/Cargo.toml @@ -16,7 +16,7 @@ edition = "2021" async-trait = "0.1" base64 = "0.13" bytes = "1.0" -chrono = "0.4" +time = { version = "0.3", features = ["serde-well-known", "macros", "local-offset"] } dyn-clone = "1.0" futures = "0.3" http-types = { version = "2.12", default-features = false } diff --git a/sdk/core/src/auth.rs b/sdk/core/src/auth.rs index bf5252d6e24..75bb66188b9 100644 --- a/sdk/core/src/auth.rs +++ b/sdk/core/src/auth.rs @@ -1,8 +1,8 @@ //! Azure authentication and authorization. -use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::{borrow::Cow, fmt::Debug}; +use time::OffsetDateTime; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct AccessToken(Cow<'static, str>); @@ -26,12 +26,12 @@ pub struct TokenResponse { /// Get the access token value. pub token: AccessToken, /// Gets the time when the provided token expires. - pub expires_on: DateTime, + pub expires_on: OffsetDateTime, } impl TokenResponse { /// Create a new `TokenResponse`. - pub fn new(token: AccessToken, expires_on: DateTime) -> Self { + pub fn new(token: AccessToken, expires_on: OffsetDateTime) -> Self { Self { token, expires_on } } } diff --git a/sdk/core/src/date/mod.rs b/sdk/core/src/date/mod.rs new file mode 100644 index 00000000000..586bfa3550f --- /dev/null +++ b/sdk/core/src/date/mod.rs @@ -0,0 +1,195 @@ +//! Azure date and time parsing and formatting + +// RFC 3339 vs ISO 8601 +// https://ijmacd.github.io/rfc3339-iso8601/ + +use crate::error::{ErrorKind, ResultExt}; +use std::time::Duration; +use time::{ + format_description::{well_known::Rfc3339, FormatItem}, + macros::format_description, + OffsetDateTime, PrimitiveDateTime, UtcOffset, +}; + +// Serde modules +pub use time::serde::rfc3339; +pub use time::serde::timestamp; +pub mod rfc1123; + +/// RFC 3339: Date and Time on the Internet: Timestamps +/// +/// https://www.rfc-editor.org/rfc/rfc3339 +/// +/// In Azure REST API specifications it is specified as `"format": "date-time"`. +/// +/// 1985-04-12T23:20:50.52Z +pub fn parse_rfc3339(s: &str) -> crate::Result { + OffsetDateTime::parse(s, &Rfc3339).with_context(ErrorKind::DataConversion, || { + format!("unable to parse rfc3339 date '{s}") + }) +} + +/// RFC 3339: Date and Time on the Internet: Timestamps +/// +/// https://www.rfc-editor.org/rfc/rfc3339 +/// +/// In Azure REST API specifications it is specified as `"format": "date-time"`. +/// +/// 1985-04-12T23:20:50.52Z +pub fn to_rfc3339(date: &OffsetDateTime) -> String { + // known format does not panic + date.format(&Rfc3339).unwrap() +} + +/// RFC 1123: Requirements for Internet Hosts - Application and Support +/// +/// https://www.rfc-editor.org/rfc/rfc1123 +/// +/// In Azure REST API specifications it is specified as `"format": "date-time-rfc1123"`. +/// +/// In .NET it is the `rfc1123pattern`. +/// https://docs.microsoft.com/dotnet/api/system.globalization.datetimeformatinfo.rfc1123pattern +/// +/// This format is also the preferred HTTP date format. +/// https://httpwg.org/specs/rfc9110.html#http.date +/// +/// Sun, 06 Nov 1994 08:49:37 GMT +pub fn parse_rfc1123(s: &str) -> crate::Result { + Ok(PrimitiveDateTime::parse(s, RFC1123_FORMAT) + .with_context(ErrorKind::DataConversion, || { + format!("unable to parse rfc1123 date '{s}") + })? + .assume_utc()) +} + +const RFC1123_FORMAT: &[FormatItem] = format_description!( + "[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[second] GMT" +); + +/// RFC 1123: Requirements for Internet Hosts - Application and Support +/// +/// https://www.rfc-editor.org/rfc/rfc1123 +/// +/// In Azure REST API specifications it is specified as `"format": "date-time-rfc1123"`. +/// +/// In .NET it is the `rfc1123pattern`. +/// https://docs.microsoft.com/dotnet/api/system.globalization.datetimeformatinfo.rfc1123pattern +/// +/// This format is also the preferred HTTP date format. +/// https://httpwg.org/specs/rfc9110.html#http.date +/// +/// Sun, 06 Nov 1994 08:49:37 GMT +pub fn to_rfc1123(date: &OffsetDateTime) -> String { + date.to_offset(UtcOffset::UTC); + // known format does not panic + date.format(&RFC1123_FORMAT).unwrap() +} + +/// Similar to RFC 1123, but includes milliseconds. +/// +/// https://docs.microsoft.com/rest/api/cosmos-db/patch-a-document +/// +/// x-ms-last-state-change-utc: Fri, 25 Mar 2016 21:27:20.035 GMT +pub fn parse_last_state_change(s: &str) -> crate::Result { + Ok(PrimitiveDateTime::parse(s, LAST_STATE_CHANGE_FORMAT) + .with_context(ErrorKind::DataConversion, || { + format!("unable to parse last state change date '{s}") + })? + .assume_utc()) +} + +const LAST_STATE_CHANGE_FORMAT: &[FormatItem] = format_description!( + "[weekday repr:short], [day] [month repr:short] [year] [hour]:[minute]:[second].[subsecond digits:3] GMT" +); + +/// Similar to preferred HTTP date format, but includes milliseconds +/// +/// https://docs.microsoft.com/rest/api/cosmos-db/patch-a-document +/// +/// x-ms-last-state-change-utc: Fri, 25 Mar 2016 21:27:20.035 GMT +pub fn to_last_state_change(date: &OffsetDateTime) -> String { + date.to_offset(UtcOffset::UTC); + // known format does not panic + date.format(LAST_STATE_CHANGE_FORMAT).unwrap() +} + +/// Assumes the local offset. Default to UTC if unable to get local offset. +pub fn assume_local(date: &PrimitiveDateTime) -> OffsetDateTime { + date.assume_offset(UtcOffset::current_local_offset().unwrap_or(UtcOffset::UTC)) +} + +// Create a duration from the number of minutes. +pub fn duration_from_minutes(minutes: u64) -> Duration { + Duration::from_secs(minutes * 60) +} + +// Create a duration from the number of hours. +pub fn duration_from_hours(hours: u64) -> Duration { + Duration::from_secs(hours * 3_600) +} + +// Create a duration from the number of days. +pub fn duration_from_days(days: u64) -> Duration { + Duration::from_secs(days * 86_400) +} + +/// Get the difference between two dates. +pub fn diff(first: OffsetDateTime, second: OffsetDateTime) -> Duration { + (first - second).unsigned_abs() +} + +#[cfg(test)] +mod tests { + use super::*; + use time::macros::datetime; + + #[test] + fn test_roundtrip_rfc3339() -> crate::Result<()> { + let s = "2019-10-12T07:20:50.52Z"; + let dt = parse_rfc3339(s)?; + assert_eq!(s, to_rfc3339(&dt)); + Ok(()) + } + + #[test] + fn test_device_update_dates() -> crate::Result<()> { + let created = parse_rfc3339("1999-09-10T21:59:22Z")?; + let last_action = parse_rfc3339("1999-09-10T03:05:07.3845533+01:00")?; + assert_eq!(created, datetime!(1999-09-10 21:59:22 UTC)); + assert_eq!(last_action, datetime!(1999-09-10 03:05:07.3845533 +01)); + Ok(()) + } + + #[test] + fn test_to_rfc1123() -> crate::Result<()> { + let dt = datetime!(1994-11-06 08:49:37 UTC); + assert_eq!("Sun, 06 Nov 1994 08:49:37 GMT", to_rfc1123(&dt)); + Ok(()) + } + + #[test] + fn test_parse_rfc1123() -> crate::Result<()> { + let dt = datetime!(1994-11-06 08:49:37 UTC); + assert_eq!(parse_rfc1123("Sun, 06 Nov 1994 08:49:37 GMT")?, dt); + Ok(()) + } + + #[test] + fn test_parse_last_state_change() -> crate::Result<()> { + assert_eq!( + datetime!(2020-01-15 23:39:44.369 UTC), + parse_last_state_change("Wed, 15 Jan 2020 23:39:44.369 GMT")? + ); + Ok(()) + } + + #[test] + fn test_list_blob_creation_time() -> crate::Result<()> { + let creation_time = "Thu, 01 Jul 2021 10:45:02 GMT"; + assert_eq!( + datetime!(2021-07-01 10:45:02 UTC), + parse_rfc1123(creation_time)? + ); + Ok(()) + } +} diff --git a/sdk/core/src/date/rfc1123.rs b/sdk/core/src/date/rfc1123.rs new file mode 100644 index 00000000000..f1bac8db5e5 --- /dev/null +++ b/sdk/core/src/date/rfc1123.rs @@ -0,0 +1,46 @@ +use serde::{self, Deserialize, Deserializer, Serializer}; +use time::OffsetDateTime; + +use crate::date::*; +use serde::de; + +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + parse_rfc1123(&s).map_err(de::Error::custom) +} + +pub fn serialize(date: &OffsetDateTime, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&to_rfc1123(date)) +} + +pub mod option { + use crate::date::*; + use serde::{Deserialize, Deserializer, Serializer}; + use time::OffsetDateTime; + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let s: Option = Option::deserialize(deserializer)?; + s.map(|s| parse_rfc1123(&s).map_err(serde::de::Error::custom)) + .transpose() + } + + pub fn serialize(date: &Option, serializer: S) -> Result + where + S: Serializer, + { + if let Some(date) = date { + serializer.serialize_str(&to_rfc1123(date)) + } else { + serializer.serialize_none() + } + } +} diff --git a/sdk/core/src/headers/utilities.rs b/sdk/core/src/headers/utilities.rs index 5e8515c836d..c78cb7939f8 100644 --- a/sdk/core/src/headers/utilities.rs +++ b/sdk/core/src/headers/utilities.rs @@ -1,32 +1,8 @@ use super::*; -use crate::error::{Error, ErrorKind}; use crate::prelude::Continuation; use crate::request_options::LeaseId; -use crate::{RequestId, SessionToken}; -use chrono::{DateTime, FixedOffset, Utc}; - -pub fn parse_date_from_str(date: &str, fmt: &str) -> crate::Result> { - DateTime::parse_from_str(date, fmt).map_err(|e| { - Error::full( - ErrorKind::DataConversion, - e, - format!( - "failed to parse date '{}' with format string {:?}", - date, fmt - ), - ) - }) -} - -pub fn parse_date_from_rfc2822(date: &str) -> crate::Result> { - DateTime::parse_from_rfc2822(date).map_err(|e| { - Error::full( - ErrorKind::DataConversion, - e, - format!("failed to parse date '{}' with as rfc2822", date), - ) - }) -} +use crate::{date, RequestId, SessionToken}; +use time::OffsetDateTime; pub fn lease_id_from_headers(headers: &Headers) -> crate::Result { headers.get_as(&LEASE_ID) @@ -42,29 +18,27 @@ pub fn client_request_id_from_headers_optional(headers: &Headers) -> Option crate::Result>> { - headers.get_optional_as(&LAST_MODIFIED) +) -> crate::Result> { + headers + .get_optional_str(&LAST_MODIFIED) + .map(date::parse_rfc1123) + .transpose() } -pub fn date_from_headers(headers: &Headers) -> crate::Result> { - rfc2822_from_headers_mandatory(headers, &DATE) +pub fn date_from_headers(headers: &Headers) -> crate::Result { + rfc1123_from_headers_mandatory(headers, &DATE) } -pub fn last_modified_from_headers(headers: &Headers) -> crate::Result> { - rfc2822_from_headers_mandatory(headers, &LAST_MODIFIED) +pub fn last_modified_from_headers(headers: &Headers) -> crate::Result { + rfc1123_from_headers_mandatory(headers, &LAST_MODIFIED) } -pub fn rfc2822_from_headers_mandatory( +pub fn rfc1123_from_headers_mandatory( headers: &Headers, header_name: &HeaderName, -) -> crate::Result> { +) -> crate::Result { let date = headers.get_str(header_name)?; - utc_date_from_rfc2822(date) -} - -pub fn utc_date_from_rfc2822(date: &str) -> crate::Result> { - let date = parse_date_from_rfc2822(date)?; - Ok(DateTime::from_utc(date.naive_utc(), Utc)) + date::parse_rfc1123(date) } pub fn continuation_token_from_headers_optional( diff --git a/sdk/core/src/lib.rs b/sdk/core/src/lib.rs index 0e1d6dee6da..6647ad2cb01 100644 --- a/sdk/core/src/lib.rs +++ b/sdk/core/src/lib.rs @@ -14,6 +14,7 @@ mod macros; mod bytes_stream; mod constants; mod context; +pub mod date; pub mod error; mod http_client; mod models; diff --git a/sdk/core/src/parsing.rs b/sdk/core/src/parsing.rs index f0853269eaa..b5ba28f35e7 100644 --- a/sdk/core/src/parsing.rs +++ b/sdk/core/src/parsing.rs @@ -1,5 +1,6 @@ //! Parser helper utilities. +use crate::date; use crate::error::{Error, ErrorKind, ResultExt}; pub trait FromStringOptional { @@ -30,91 +31,38 @@ impl FromStringOptional for bool { } } -impl FromStringOptional> for chrono::DateTime { - fn from_str_optional(s: &str) -> crate::Result> { +impl FromStringOptional for time::OffsetDateTime { + fn from_str_optional(s: &str) -> crate::Result { from_azure_time(s).with_context(ErrorKind::DataConversion, || { format!("error parsing date time '{s}'") }) } } -#[inline] #[cfg(not(feature = "azurite_workaround"))] -pub fn from_azure_time(s: &str) -> crate::Result> { - let dt = chrono::DateTime::parse_from_rfc2822(s).map_kind(ErrorKind::DataConversion)?; - let dt_utc: chrono::DateTime = dt.with_timezone(&chrono::Utc); - Ok(dt_utc) +pub fn from_azure_time(s: &str) -> crate::Result { + date::parse_rfc1123(s) } -pub mod rfc2822_time_format { - use super::from_azure_time; - use chrono::{DateTime, Utc}; - use serde::{self, Deserialize, Deserializer, Serializer}; - - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - from_azure_time(&s).map_err(serde::de::Error::custom) - } - - pub fn serialize(date: &DateTime, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&date.to_rfc2822()) - } -} - -pub mod rfc2822_time_format_optional { - use super::from_azure_time; - use chrono::{DateTime, Utc}; - use serde::{self, Deserialize, Deserializer, Serializer}; - - pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> - where - D: Deserializer<'de>, - { - let s: Option = Option::deserialize(deserializer)?; - s.map(|s| from_azure_time(&s).map_err(serde::de::Error::custom)) - .transpose() - } - - pub fn serialize(date: &Option>, serializer: S) -> Result - where - S: Serializer, - { - if let Some(date) = date { - serializer.serialize_str(&date.to_rfc2822()) - } else { - serializer.serialize_none() - } - } -} - -#[inline] #[cfg(feature = "azurite_workaround")] -pub fn from_azure_time(s: &str) -> crate::Result> { - if let Ok(dt) = chrono::DateTime::parse_from_rfc2822(s) { - let dt_utc: chrono::DateTime = dt.with_timezone(&chrono::Utc); - Ok(dt_utc) +pub fn from_azure_time(s: &str) -> crate::Result { + if let Ok(dt) = date::parse_rfc1123(s) { + Ok(dt) } else { log::warn!("Received an invalid date: {}, returning now()", s); - Ok(chrono::Utc::now()) + Ok(time::OffsetDateTime::now_utc()) } } #[cfg(test)] mod test { - use chrono::{Datelike, Timelike}; #[test] fn test_from_azure_time() { let t = super::from_azure_time("Sun, 27 Sep 2009 17:26:40 GMT").unwrap(); assert_eq!(t.day(), 27); - assert_eq!(t.month(), 9); + assert_eq!(t.month(), time::Month::September); assert_eq!(t.hour(), 17); assert_eq!(t.second(), 40); } diff --git a/sdk/core/src/policies/retry_policies/exponential_retry.rs b/sdk/core/src/policies/retry_policies/exponential_retry.rs index 801ba78b257..444b2162e4f 100644 --- a/sdk/core/src/policies/retry_policies/exponential_retry.rs +++ b/sdk/core/src/policies/retry_policies/exponential_retry.rs @@ -1,5 +1,5 @@ -use chrono::{DateTime, Local}; use std::time::Duration; +use time::OffsetDateTime; /// Retry policy with exponential back-off. /// @@ -26,20 +26,16 @@ impl ExponentialRetryPolicy { } impl super::RetryPolicy for ExponentialRetryPolicy { - fn is_expired(&self, first_retry_time: &mut Option>, retry_count: u32) -> bool { + fn is_expired(&self, first_retry_time: &mut Option, retry_count: u32) -> bool { if retry_count > self.max_retries { return true; } - - let first_retry_time = first_retry_time.get_or_insert_with(Local::now); - let max_delay = chrono::Duration::from_std(self.max_delay) - .unwrap_or_else(|_| chrono::Duration::max_value()); - - Local::now() > *first_retry_time + max_delay + let first_retry_time = first_retry_time.get_or_insert_with(OffsetDateTime::now_utc); + OffsetDateTime::now_utc() > *first_retry_time + self.max_delay } fn sleep_duration(&self, retry_count: u32) -> Duration { - let sleep_ms = self.delay.as_millis() as u64 * u64::pow(2u64, retry_count - 1) + let sleep_ms = self.delay.as_millis() as u64 * u64::pow(2, retry_count - 1) + u64::from(rand::random::()); Duration::from_millis(sleep_ms) } diff --git a/sdk/core/src/policies/retry_policies/fixed_retry.rs b/sdk/core/src/policies/retry_policies/fixed_retry.rs index 8f25489fb64..6752c4ff4b9 100644 --- a/sdk/core/src/policies/retry_policies/fixed_retry.rs +++ b/sdk/core/src/policies/retry_policies/fixed_retry.rs @@ -1,5 +1,5 @@ -use chrono::{DateTime, Local}; use std::time::Duration; +use time::OffsetDateTime; /// Retry policy with fixed back-off. /// @@ -25,16 +25,12 @@ impl FixedRetryPolicy { } impl super::RetryPolicy for FixedRetryPolicy { - fn is_expired(&self, first_retry_time: &mut Option>, retry_count: u32) -> bool { + fn is_expired(&self, first_retry_time: &mut Option, retry_count: u32) -> bool { if retry_count > self.max_retries { return true; } - - let first_retry_time = first_retry_time.get_or_insert_with(Local::now); - let max_delay = chrono::Duration::from_std(self.max_delay) - .unwrap_or_else(|_| chrono::Duration::max_value()); - - Local::now() > *first_retry_time + max_delay + let first_retry_time = first_retry_time.get_or_insert_with(OffsetDateTime::now_utc); + OffsetDateTime::now_utc() > *first_retry_time + self.max_delay } fn sleep_duration(&self, _retry_count: u32) -> Duration { diff --git a/sdk/core/src/policies/retry_policies/retry_policy.rs b/sdk/core/src/policies/retry_policies/retry_policy.rs index 3f3d6b84ee4..7bd8ddae416 100644 --- a/sdk/core/src/policies/retry_policies/retry_policy.rs +++ b/sdk/core/src/policies/retry_policies/retry_policy.rs @@ -2,9 +2,9 @@ use crate::error::{Error, ErrorKind, HttpError}; use crate::policies::{Policy, PolicyResult, Request}; use crate::sleep::sleep; use crate::{Context, StatusCode}; -use chrono::{DateTime, Local}; use std::sync::Arc; use std::time::Duration; +use time::OffsetDateTime; /// A retry policy. /// @@ -15,7 +15,7 @@ pub trait RetryPolicy { /// Determine if no more retries should be performed. /// /// Must return true if no more retries should be attempted. - fn is_expired(&self, first_retry_time: &mut Option>, retry_count: u32) -> bool; + fn is_expired(&self, first_retry_time: &mut Option, retry_count: u32) -> bool; /// Determine how long before the next retry should be attempted. fn sleep_duration(&self, retry_count: u32) -> Duration; } @@ -51,7 +51,7 @@ where let error = match next[0].send(ctx, request, &next[1..]).await { Ok(response) if response.status().is_success() => { log::trace!( - "Succesful response. Request={:?} response={:?}", + "Successful response. Request={:?} response={:?}", request, response ); diff --git a/sdk/core/src/request_options/if_modified_since.rs b/sdk/core/src/request_options/if_modified_since.rs index 6340ce72afa..8ce086fc991 100644 --- a/sdk/core/src/request_options/if_modified_since.rs +++ b/sdk/core/src/request_options/if_modified_since.rs @@ -1,11 +1,14 @@ -use crate::headers::{self, Header}; -use chrono::{DateTime, Utc}; +use crate::{ + date, + headers::{self, Header}, +}; +use time::OffsetDateTime; #[derive(Debug, Clone, Copy)] -pub struct IfModifiedSince(DateTime); +pub struct IfModifiedSince(OffsetDateTime); impl IfModifiedSince { - pub fn new(time: DateTime) -> Self { + pub fn new(time: OffsetDateTime) -> Self { Self(time) } } @@ -16,12 +19,12 @@ impl Header for IfModifiedSince { } fn value(&self) -> headers::HeaderValue { - self.0.to_rfc2822().into() + date::to_rfc1123(&self.0).into() } } -impl From> for IfModifiedSince { - fn from(time: DateTime) -> Self { +impl From for IfModifiedSince { + fn from(time: OffsetDateTime) -> Self { Self::new(time) } } diff --git a/sdk/core/src/request_options/if_modified_since_condition.rs b/sdk/core/src/request_options/if_modified_since_condition.rs index ac6932f86e8..bcff5568c1e 100644 --- a/sdk/core/src/request_options/if_modified_since_condition.rs +++ b/sdk/core/src/request_options/if_modified_since_condition.rs @@ -1,25 +1,27 @@ -use crate::headers::{self, Header}; -use chrono::{DateTime, Utc}; -use headers::{IF_MODIFIED_SINCE, IF_UNMODIFIED_SINCE}; +use crate::{ + date, + headers::{self, Header, HeaderName}, +}; +use time::OffsetDateTime; #[derive(Debug, Clone, Copy, PartialEq)] pub enum IfModifiedSinceCondition { - Modified(DateTime), - Unmodified(DateTime), + Modified(OffsetDateTime), + Unmodified(OffsetDateTime), } impl Header for IfModifiedSinceCondition { - fn name(&self) -> headers::HeaderName { + fn name(&self) -> HeaderName { match self { - IfModifiedSinceCondition::Modified(_) => IF_MODIFIED_SINCE, - IfModifiedSinceCondition::Unmodified(_) => IF_UNMODIFIED_SINCE, + IfModifiedSinceCondition::Modified(_) => headers::IF_MODIFIED_SINCE, + IfModifiedSinceCondition::Unmodified(_) => headers::IF_UNMODIFIED_SINCE, } } fn value(&self) -> headers::HeaderValue { match self { IfModifiedSinceCondition::Modified(date) - | IfModifiedSinceCondition::Unmodified(date) => date.to_rfc2822(), + | IfModifiedSinceCondition::Unmodified(date) => date::to_rfc1123(date), } .into() } diff --git a/sdk/core/src/request_options/if_source_modified_since_condition.rs b/sdk/core/src/request_options/if_source_modified_since_condition.rs index 5757aa93e08..e89e916870f 100644 --- a/sdk/core/src/request_options/if_source_modified_since_condition.rs +++ b/sdk/core/src/request_options/if_source_modified_since_condition.rs @@ -1,14 +1,17 @@ -use crate::headers::{self, Header}; -use chrono::{DateTime, Utc}; +use crate::{ + date, + headers::{self, Header, HeaderName}, +}; +use time::OffsetDateTime; #[derive(Debug, Clone, Copy, PartialEq)] pub enum IfSourceModifiedSinceCondition { - Modified(DateTime), - Unmodified(DateTime), + Modified(OffsetDateTime), + Unmodified(OffsetDateTime), } impl Header for IfSourceModifiedSinceCondition { - fn name(&self) -> headers::HeaderName { + fn name(&self) -> HeaderName { match self { IfSourceModifiedSinceCondition::Modified(_) => headers::SOURCE_IF_MODIFIED_SINCE, IfSourceModifiedSinceCondition::Unmodified(_) => headers::SOURCE_IF_UNMODIFIED_SINCE, @@ -18,7 +21,7 @@ impl Header for IfSourceModifiedSinceCondition { fn value(&self) -> headers::HeaderValue { match self { IfSourceModifiedSinceCondition::Modified(date) - | IfSourceModifiedSinceCondition::Unmodified(date) => date.to_rfc2822().into(), + | IfSourceModifiedSinceCondition::Unmodified(date) => date::to_rfc1123(date).into(), } } } diff --git a/sdk/core/src/util.rs b/sdk/core/src/util.rs index c91091707da..5ac66483a33 100644 --- a/sdk/core/src/util.rs +++ b/sdk/core/src/util.rs @@ -1,6 +1,5 @@ //! An assortment of helper utilities. -use chrono::{DateTime, FixedOffset, Utc}; use serde::{ de::{self, DeserializeOwned, Deserializer}, Deserialize, @@ -16,21 +15,3 @@ where .or_else(|_| T::deserialize(serde_json::Value::String(v.to_lowercase()))) .map_err(de::Error::custom) } - -pub fn deserialize_utc_date_from_rfc2822<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - crate::headers::utc_date_from_rfc2822(&s).map_err(serde::de::Error::custom) -} - -pub fn deserialize_date_from_rfc3339<'de, D>( - deserializer: D, -) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - DateTime::parse_from_rfc3339(&s).map_err(serde::de::Error::custom) -} diff --git a/sdk/data_cosmos/Cargo.toml b/sdk/data_cosmos/Cargo.toml index c9999b45e33..64aae654bba 100644 --- a/sdk/data_cosmos/Cargo.toml +++ b/sdk/data_cosmos/Cargo.toml @@ -18,7 +18,7 @@ edition = "2021" async-trait = "0.1" azure_core = { path = "../core", version = "0.3" } base64 = "0.13" -chrono = "0.4" +time = "0.3" futures = "0.3" log = "0.4" serde = { version = "1.0", features = ["derive"] } diff --git a/sdk/data_cosmos/README.md b/sdk/data_cosmos/README.md index 7208faade3d..648fd897bb0 100644 --- a/sdk/data_cosmos/README.md +++ b/sdk/data_cosmos/README.md @@ -71,7 +71,7 @@ async fn main() -> azure_core::Result<()> { id: format!("unique_id{}", i), a_string: "Something here".to_owned(), a_number: i * 100, // this is the partition key - a_timestamp: chrono::Utc::now().timestamp(), + a_timestamp: OffsetDateTime::now_utc().unix_timestamp(), }; // insert it diff --git a/sdk/data_cosmos/examples/attachments.rs b/sdk/data_cosmos/examples/attachments.rs index 21ac6b63674..401c7482f00 100644 --- a/sdk/data_cosmos/examples/attachments.rs +++ b/sdk/data_cosmos/examples/attachments.rs @@ -2,6 +2,7 @@ use azure_data_cosmos::prelude::*; use clap::Parser; use futures::StreamExt; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; // Now we create a sample struct. #[derive(Serialize, Deserialize, Clone, Debug)] @@ -49,7 +50,7 @@ async fn main() -> azure_core::Result<()> { id: format!("unique_id{}", 100), a_string: "Something here".into(), a_number: 100, - a_timestamp: chrono::Utc::now().timestamp(), + a_timestamp: OffsetDateTime::now_utc().unix_timestamp(), }; // let's add an entity. diff --git a/sdk/data_cosmos/examples/document.rs b/sdk/data_cosmos/examples/document.rs index a0081795c16..7d2f821dc98 100644 --- a/sdk/data_cosmos/examples/document.rs +++ b/sdk/data_cosmos/examples/document.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use azure_core::prelude::*; use azure_data_cosmos::prelude::*; +use time::OffsetDateTime; #[derive(Debug, Parser)] struct Args { @@ -121,7 +122,7 @@ async fn main() -> azure_core::Result<()> { id: "unique_id100".into(), a_string: "Something here".into(), a_number: 100, - a_timestamp: chrono::Utc::now().timestamp(), + a_timestamp: OffsetDateTime::now_utc().unix_timestamp(), }; // Now we store the struct in Azure Cosmos DB. diff --git a/sdk/data_cosmos/examples/document_entries.rs b/sdk/data_cosmos/examples/document_entries.rs index f5141477d9f..79a64cb33da 100644 --- a/sdk/data_cosmos/examples/document_entries.rs +++ b/sdk/data_cosmos/examples/document_entries.rs @@ -4,6 +4,7 @@ use azure_data_cosmos::prelude::*; use clap::Parser; use futures::stream::StreamExt; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; #[derive(Debug, Parser)] struct Args { @@ -54,7 +55,7 @@ async fn main() -> azure_core::Result<()> { id: format!("unique_id{}", i), a_string: "Something here".into(), a_number: i, - a_timestamp: chrono::Utc::now().timestamp(), + a_timestamp: OffsetDateTime::now_utc().unix_timestamp(), }; // let's add an entity. diff --git a/sdk/data_cosmos/examples/readme.rs b/sdk/data_cosmos/examples/readme.rs index 56c63be5290..dab833ac51a 100644 --- a/sdk/data_cosmos/examples/readme.rs +++ b/sdk/data_cosmos/examples/readme.rs @@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize}; use azure_data_cosmos::prelude::*; use clap::Parser; use futures::stream::StreamExt; +use time::OffsetDateTime; #[derive(Debug, Parser)] struct Args { @@ -73,7 +74,7 @@ async fn main() -> azure_core::Result<()> { id: format!("unique_id{i}"), string: "Something here".into(), number: i * 100, - timestamp: chrono::Utc::now().timestamp(), + timestamp: OffsetDateTime::now_utc().unix_timestamp(), }; // Insert the document and store the returned session token for later use in the cosmos consistency level! diff --git a/sdk/data_cosmos/src/authorization_policy.rs b/sdk/data_cosmos/src/authorization_policy.rs index 2541eb2feee..2fa57d59b87 100644 --- a/sdk/data_cosmos/src/authorization_policy.rs +++ b/sdk/data_cosmos/src/authorization_policy.rs @@ -1,13 +1,13 @@ use crate::headers::{HEADER_DATE, HEADER_VERSION}; use crate::resources::permission::AuthorizationToken; use crate::resources::ResourceType; -use crate::TimeNonce; use azure_core::headers::{HeaderValue, AUTHORIZATION}; -use azure_core::{Context, Policy, PolicyResult, Request}; +use azure_core::{date, Context, Policy, PolicyResult, Request}; use hmac::{Hmac, Mac}; use sha2::Sha256; use std::borrow::Cow; use std::sync::Arc; +use time::OffsetDateTime; use url::form_urlencoded; const AZURE_VERSION: &str = "2018-12-31"; @@ -55,7 +55,7 @@ impl Policy for AuthorizationPolicy { "Authorization policies cannot be the last policy of a pipeline" ); - let time_nonce = TimeNonce::new(); + let time_nonce = OffsetDateTime::now_utc(); let auth = { let resource_link = generate_resource_link(request); @@ -145,7 +145,7 @@ fn generate_authorization( http_method: &azure_core::Method, resource_type: &ResourceType, resource_link: &str, - time_nonce: TimeNonce, + time_nonce: OffsetDateTime, ) -> String { let (authorization_type, signature) = match auth_token { AuthorizationToken::Primary(key) => { @@ -178,7 +178,7 @@ fn string_to_sign( http_method: &azure_core::Method, rt: &ResourceType, resource_link: &str, - time_nonce: TimeNonce, + time_nonce: OffsetDateTime, ) -> String { // From official docs: // StringToSign = @@ -216,13 +216,13 @@ fn string_to_sign( ResourceType::Triggers => "triggers", }, resource_link, - time_nonce.to_string().to_lowercase() + date::to_rfc1123(&time_nonce).to_lowercase() ) } /// This function HMAC_SHA256 signs the passed string, given the supplied key. The passed string /// will be encoded as per its UTF-8 representation. The resulting byte array is then base64 -/// encoded and returned to the caller. Possibile optimization: profile if the HMAC struct +/// encoded and returned to the caller. Possible optimization: profile if the HMAC struct /// initialization is expensive and, if so, cache it somehow to avoid recreating it at every /// request. fn encode_str_to_sign(data: &str, key: &[u8]) -> String { @@ -235,12 +235,11 @@ fn encode_str_to_sign(data: &str, key: &[u8]) -> String { #[cfg(test)] mod tests { use super::*; + use azure_core::date; #[test] fn string_to_sign_00() { - let time = - chrono::DateTime::parse_from_rfc3339("1900-01-01T01:00:00.000000000+00:00").unwrap(); - let time = time.with_timezone(&chrono::Utc).into(); + let time = date::parse_rfc3339("1900-01-01T01:00:00.000000000+00:00").unwrap(); let ret = string_to_sign( &azure_core::Method::Get, @@ -261,9 +260,7 @@ mon, 01 jan 1900 01:00:00 gmt #[test] fn generate_authorization_00() { - let time = - chrono::DateTime::parse_from_rfc3339("1900-01-01T01:00:00.000000000+00:00").unwrap(); - let time = time.with_timezone(&chrono::Utc).into(); + let time = date::parse_rfc3339("1900-01-01T01:00:00.000000000+00:00").unwrap(); let auth_token = AuthorizationToken::primary_from_base64( "8F8xXXOptJxkblM1DBXW7a6NMI5oE8NnwPGYBmwxLCKfejOK7B7yhcCHMGvN3PBrlMLIOeol1Hv9RCdzAZR5sg==", @@ -285,9 +282,7 @@ mon, 01 jan 1900 01:00:00 gmt #[test] fn generate_authorization_01() { - let time = - chrono::DateTime::parse_from_rfc3339("2017-04-27T00:51:12.000000000+00:00").unwrap(); - let time = time.with_timezone(&chrono::Utc).into(); + let time = date::parse_rfc3339("2017-04-27T00:51:12.000000000+00:00").unwrap(); let auth_token = AuthorizationToken::primary_from_base64( "dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5JiwvW0EndXdDku/dkKBp8/ufDToSxL", diff --git a/sdk/data_cosmos/src/headers/from_headers.rs b/sdk/data_cosmos/src/headers/from_headers.rs index 0dae033b16c..d59905dfd62 100644 --- a/sdk/data_cosmos/src/headers/from_headers.rs +++ b/sdk/data_cosmos/src/headers/from_headers.rs @@ -3,9 +3,10 @@ use crate::resource_quota::resource_quotas_from_str; use crate::resources::document::IndexingDirective; use crate::ResourceQuota; +use azure_core::date::{parse_last_state_change, parse_rfc1123}; use azure_core::error::{Error, ErrorKind}; use azure_core::headers::{self, Headers}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; pub(crate) fn request_charge_from_headers(headers: &Headers) -> azure_core::Result { headers.get_as(&HEADER_REQUEST_CHARGE) @@ -169,24 +170,14 @@ pub(crate) fn media_storage_usage_mb_from_headers(headers: &Headers) -> azure_co headers.get_as(&HEADER_MEDIA_STORAGE_USAGE_MB) } -fn _date_from_headers( - headers: &Headers, - header_name: &HeaderName, -) -> azure_core::Result> { - let date = headers.get_str(header_name)?; - // since Azure returns "GMT" instead of +0000 as timezone we replace it ourselves. - // For example: Wed, 15 Jan 2020 23:39:44.369 GMT - let date = date.replace("GMT", "+0000"); - let date = headers::parse_date_from_str(&date, "%a, %e %h %Y %H:%M:%S%.f %z")?; - Ok(DateTime::from_utc(date.naive_utc(), Utc)) -} - pub(crate) fn last_state_change_from_headers( headers: &Headers, -) -> azure_core::Result> { - _date_from_headers(headers, &HEADER_LAST_STATE_CHANGE_UTC) +) -> azure_core::Result { + let s = headers.get_str(&HEADER_LAST_STATE_CHANGE_UTC)?; + parse_last_state_change(s) } -pub(crate) fn date_from_headers(headers: &Headers) -> azure_core::Result> { - _date_from_headers(headers, &headers::DATE) +pub(crate) fn date_from_headers(headers: &Headers) -> azure_core::Result { + let s = headers.get_str(&headers::DATE)?; + parse_rfc1123(s) } diff --git a/sdk/data_cosmos/src/lib.rs b/sdk/data_cosmos/src/lib.rs index b4a6d744899..6edef788289 100644 --- a/sdk/data_cosmos/src/lib.rs +++ b/sdk/data_cosmos/src/lib.rs @@ -104,10 +104,8 @@ mod consistency_level; mod cosmos_entity; mod headers; mod resource_quota; -mod time_nonce; pub(crate) use authorization_policy::AuthorizationPolicy; -pub(crate) use time_nonce::TimeNonce; pub use consistency_level::ConsistencyLevel; pub use cosmos_entity::CosmosEntity; diff --git a/sdk/data_cosmos/src/operations/create_collection.rs b/sdk/data_cosmos/src/operations/create_collection.rs index 8552da947cd..e0e7e52bc2a 100644 --- a/sdk/data_cosmos/src/operations/create_collection.rs +++ b/sdk/data_cosmos/src/operations/create_collection.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use crate::resources::collection::{IndexingPolicy, PartitionKey}; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { CreateCollection, @@ -60,7 +60,7 @@ pub struct CreateCollectionResponse { pub activity_id: uuid::Uuid, pub etag: String, pub session_token: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub schema_version: String, pub service_version: String, pub gateway_version: String, diff --git a/sdk/data_cosmos/src/operations/create_database.rs b/sdk/data_cosmos/src/operations/create_database.rs index 409ab6bf13a..1e430cbd841 100644 --- a/sdk/data_cosmos/src/operations/create_database.rs +++ b/sdk/data_cosmos/src/operations/create_database.rs @@ -4,7 +4,7 @@ use crate::resources::Database; use crate::ResourceQuota; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { CreateDatabase, @@ -46,7 +46,7 @@ pub struct CreateDatabaseResponse { pub charge: f64, pub etag: String, pub session_token: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub quorum_acked_lsn: u64, diff --git a/sdk/data_cosmos/src/operations/create_document.rs b/sdk/data_cosmos/src/operations/create_document.rs index f6b20686c36..57895cb474d 100644 --- a/sdk/data_cosmos/src/operations/create_document.rs +++ b/sdk/data_cosmos/src/operations/create_document.rs @@ -5,9 +5,9 @@ use crate::resources::document::DocumentAttributes; use crate::ResourceQuota; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::{prelude::*, StatusCode}; -use chrono::{DateTime, Utc}; use serde::Serialize; use std::convert::TryFrom; +use time::OffsetDateTime; use azure_core::{collect_pinned_stream, Response as HttpResponse}; @@ -83,7 +83,7 @@ impl CreateDocumentBuilder { pub struct CreateDocumentResponse { pub document_attributes: DocumentAttributes, pub is_update: bool, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub etag: String, pub resource_quota: Vec, pub resource_usage: Vec, @@ -105,7 +105,7 @@ pub struct CreateDocumentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl CreateDocumentResponse { diff --git a/sdk/data_cosmos/src/operations/create_or_replace_attachment.rs b/sdk/data_cosmos/src/operations/create_or_replace_attachment.rs index f7f5025e417..528217478bc 100644 --- a/sdk/data_cosmos/src/operations/create_or_replace_attachment.rs +++ b/sdk/data_cosmos/src/operations/create_or_replace_attachment.rs @@ -6,7 +6,7 @@ use crate::ResourceQuota; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::SessionToken; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { CreateOrReplaceAttachment, @@ -68,7 +68,7 @@ pub struct CreateOrReplaceAttachmentResponse { pub attachment: Attachment, pub max_media_storage_usage_mb: u64, pub media_storage_usage_mb: u64, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub etag: String, pub resource_quota: Vec, pub resource_usage: Vec, @@ -88,7 +88,7 @@ pub struct CreateOrReplaceAttachmentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl CreateOrReplaceAttachmentResponse { diff --git a/sdk/data_cosmos/src/operations/create_or_replace_slug_attachment.rs b/sdk/data_cosmos/src/operations/create_or_replace_slug_attachment.rs index 42aacb5271a..841b5391277 100644 --- a/sdk/data_cosmos/src/operations/create_or_replace_slug_attachment.rs +++ b/sdk/data_cosmos/src/operations/create_or_replace_slug_attachment.rs @@ -11,7 +11,7 @@ use azure_core::SessionToken; use azure_core::{collect_pinned_stream, headers}; use azure_core::{content_type, prelude::*}; use bytes::Bytes; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { CreateOrReplaceSlugAttachment, @@ -79,7 +79,7 @@ pub struct CreateOrReplaceSlugAttachmentResponse { pub attachment: Attachment, pub max_media_storage_usage_mb: u64, pub media_storage_usage_mb: u64, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub etag: String, pub resource_quota: Vec, pub resource_usage: Vec, @@ -98,7 +98,7 @@ pub struct CreateOrReplaceSlugAttachmentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl CreateOrReplaceSlugAttachmentResponse { diff --git a/sdk/data_cosmos/src/operations/create_or_replace_trigger.rs b/sdk/data_cosmos/src/operations/create_or_replace_trigger.rs index d38e06d70ae..57c08ab09b8 100644 --- a/sdk/data_cosmos/src/operations/create_or_replace_trigger.rs +++ b/sdk/data_cosmos/src/operations/create_or_replace_trigger.rs @@ -6,7 +6,7 @@ use crate::ResourceQuota; use azure_core::collect_pinned_stream; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::Response as HttpResponse; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { CreateOrReplaceTrigger, @@ -67,7 +67,7 @@ impl CreateOrReplaceTriggerBuilder { pub struct CreateOrReplaceTriggerResponse { pub trigger: Trigger, pub server: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub etag: String, pub resource_quota: Vec, pub resource_usage: Vec, @@ -89,7 +89,7 @@ pub struct CreateOrReplaceTriggerResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl CreateOrReplaceTriggerResponse { diff --git a/sdk/data_cosmos/src/operations/create_or_replace_user_defined_function.rs b/sdk/data_cosmos/src/operations/create_or_replace_user_defined_function.rs index 4f9bbaf1bb2..e75a50d0a6e 100644 --- a/sdk/data_cosmos/src/operations/create_or_replace_user_defined_function.rs +++ b/sdk/data_cosmos/src/operations/create_or_replace_user_defined_function.rs @@ -5,7 +5,7 @@ use crate::ResourceQuota; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { CreateOrReplaceUserDefinedFunction, @@ -55,7 +55,7 @@ impl CreateOrReplaceUserDefinedFunctionBuilder { pub struct CreateOrReplaceUserDefinedFunctionResponse { pub user_defined_function: UserDefinedFunction, pub server: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub etag: String, pub resource_quota: Vec, pub resource_usage: Vec, @@ -77,7 +77,7 @@ pub struct CreateOrReplaceUserDefinedFunctionResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl CreateOrReplaceUserDefinedFunctionResponse { diff --git a/sdk/data_cosmos/src/operations/create_stored_procedure.rs b/sdk/data_cosmos/src/operations/create_stored_procedure.rs index d9087378cdc..44722159f5d 100644 --- a/sdk/data_cosmos/src/operations/create_stored_procedure.rs +++ b/sdk/data_cosmos/src/operations/create_stored_procedure.rs @@ -4,7 +4,7 @@ use crate::resources::StoredProcedure; use crate::ResourceQuota; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { CreateStoredProcedure, @@ -57,7 +57,7 @@ pub struct CreateStoredProcedureResponse { pub activity_id: uuid::Uuid, pub etag: String, pub session_token: String, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub quorum_acked_lsn: u64, diff --git a/sdk/data_cosmos/src/operations/delete_attachment.rs b/sdk/data_cosmos/src/operations/delete_attachment.rs index 14e0fbee6d0..7db761d9508 100644 --- a/sdk/data_cosmos/src/operations/delete_attachment.rs +++ b/sdk/data_cosmos/src/operations/delete_attachment.rs @@ -6,7 +6,7 @@ use azure_core::headers::session_token_from_headers; use azure_core::prelude::*; use azure_core::Response as HttpResponse; use azure_core::SessionToken; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { DeleteAttachment, @@ -47,7 +47,7 @@ impl DeleteAttachmentBuilder { pub struct DeleteAttachmentResponse { pub max_media_storage_usage_mb: u64, pub media_storage_usage_mb: u64, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub lsn: u64, @@ -66,7 +66,7 @@ pub struct DeleteAttachmentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl DeleteAttachmentResponse { diff --git a/sdk/data_cosmos/src/operations/delete_collection.rs b/sdk/data_cosmos/src/operations/delete_collection.rs index 58953e8b2ba..83b6f818e7c 100644 --- a/sdk/data_cosmos/src/operations/delete_collection.rs +++ b/sdk/data_cosmos/src/operations/delete_collection.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use crate::{headers::from_headers::*, ResourceQuota}; use azure_core::headers::{content_type_from_headers, session_token_from_headers}; use azure_core::Response as HttpResponse; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { DeleteCollection, @@ -35,7 +35,7 @@ impl DeleteCollectionBuilder { #[derive(Debug, Clone)] pub struct DeleteCollectionResponse { - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub collection_partition_index: u64, @@ -52,7 +52,7 @@ pub struct DeleteCollectionResponse { pub gateway_version: String, pub cosmos_llsn: u64, pub lsn: u64, - pub date: DateTime, + pub date: OffsetDateTime, pub transport_request_id: u64, pub xp_role: u32, pub server: String, diff --git a/sdk/data_cosmos/src/operations/delete_stored_procedure.rs b/sdk/data_cosmos/src/operations/delete_stored_procedure.rs index 1a7a0fcf2cf..5324e05d79d 100644 --- a/sdk/data_cosmos/src/operations/delete_stored_procedure.rs +++ b/sdk/data_cosmos/src/operations/delete_stored_procedure.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use crate::ResourceQuota; use azure_core::headers::session_token_from_headers; use azure_core::Response as HttpResponse; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { DeleteStoredProcedure, @@ -41,7 +41,7 @@ pub struct DeleteStoredProcedureResponse { pub charge: f64, pub activity_id: uuid::Uuid, pub session_token: String, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, } diff --git a/sdk/data_cosmos/src/operations/delete_trigger.rs b/sdk/data_cosmos/src/operations/delete_trigger.rs index 13bdc954ca9..0e260fbfb4e 100644 --- a/sdk/data_cosmos/src/operations/delete_trigger.rs +++ b/sdk/data_cosmos/src/operations/delete_trigger.rs @@ -4,7 +4,7 @@ use crate::ResourceQuota; use azure_core::headers::session_token_from_headers; use azure_core::Response as HttpResponse; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { DeleteTrigger, @@ -39,7 +39,7 @@ impl DeleteTriggerBuilder { pub struct DeleteTriggerResponse { pub content_location: String, pub server: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub lsn: u64, @@ -60,7 +60,7 @@ pub struct DeleteTriggerResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl DeleteTriggerResponse { pub async fn try_from(response: HttpResponse) -> azure_core::Result { diff --git a/sdk/data_cosmos/src/operations/delete_user_defined_function.rs b/sdk/data_cosmos/src/operations/delete_user_defined_function.rs index 61ee3f85f74..03239b567ae 100644 --- a/sdk/data_cosmos/src/operations/delete_user_defined_function.rs +++ b/sdk/data_cosmos/src/operations/delete_user_defined_function.rs @@ -4,7 +4,7 @@ use crate::ResourceQuota; use azure_core::headers::session_token_from_headers; use azure_core::Response as HttpResponse; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { DeleteUserDefinedFunction, @@ -41,7 +41,7 @@ impl DeleteUserDefinedFunctionBuilder { pub struct DeleteUserDefinedFunctionResponse { pub content_location: String, pub server: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub lsn: u64, @@ -62,7 +62,7 @@ pub struct DeleteUserDefinedFunctionResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl DeleteUserDefinedFunctionResponse { diff --git a/sdk/data_cosmos/src/operations/execute_stored_procedure.rs b/sdk/data_cosmos/src/operations/execute_stored_procedure.rs index 53389475f54..5faae94dda8 100644 --- a/sdk/data_cosmos/src/operations/execute_stored_procedure.rs +++ b/sdk/data_cosmos/src/operations/execute_stored_procedure.rs @@ -8,8 +8,8 @@ use azure_core::headers::session_token_from_headers; use azure_core::prelude::*; use azure_core::{Response as HttpResponse, SessionToken}; use bytes::Bytes; -use chrono::{DateTime, Utc}; use serde::de::DeserializeOwned; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct ExecuteStoredProcedureBuilder { @@ -108,7 +108,7 @@ where { pub payload: T, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub schema_version: String, pub alt_content_path: String, pub content_path: String, @@ -126,7 +126,7 @@ where pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl ExecuteStoredProcedureResponse diff --git a/sdk/data_cosmos/src/operations/get_attachment.rs b/sdk/data_cosmos/src/operations/get_attachment.rs index 7f9b1ab0b0b..a6c5b2be3fb 100644 --- a/sdk/data_cosmos/src/operations/get_attachment.rs +++ b/sdk/data_cosmos/src/operations/get_attachment.rs @@ -8,7 +8,7 @@ use azure_core::headers::{ }; use azure_core::SessionToken; use azure_core::{collect_pinned_stream, prelude::*, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { GetAttachment, @@ -51,7 +51,7 @@ pub struct GetAttachmentResponse { pub content_type: String, pub content_location: String, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub etag: String, pub resource_quota: Vec, pub resource_usage: Vec, @@ -70,7 +70,7 @@ pub struct GetAttachmentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl GetAttachmentResponse { diff --git a/sdk/data_cosmos/src/operations/get_collection.rs b/sdk/data_cosmos/src/operations/get_collection.rs index 9e66dc78bbe..39f2d0884a4 100644 --- a/sdk/data_cosmos/src/operations/get_collection.rs +++ b/sdk/data_cosmos/src/operations/get_collection.rs @@ -5,7 +5,7 @@ use azure_core::headers::{ content_type_from_headers, etag_from_headers, session_token_from_headers, }; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { GetCollection, @@ -39,7 +39,7 @@ impl GetCollectionBuilder { #[derive(Debug, Clone)] pub struct GetCollectionResponse { pub collection: Collection, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub etag: String, pub collection_partition_index: u64, pub collection_service_index: u64, @@ -62,7 +62,7 @@ pub struct GetCollectionResponse { pub xp_role: u32, pub content_type: String, pub content_location: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl GetCollectionResponse { diff --git a/sdk/data_cosmos/src/operations/get_database.rs b/sdk/data_cosmos/src/operations/get_database.rs index 3b03931c93c..999ce20c85b 100644 --- a/sdk/data_cosmos/src/operations/get_database.rs +++ b/sdk/data_cosmos/src/operations/get_database.rs @@ -4,7 +4,7 @@ use crate::ResourceQuota; use azure_core::headers::{etag_from_headers, session_token_from_headers}; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { GetDatabase, @@ -37,7 +37,7 @@ pub struct GetDatabaseResponse { pub activity_id: uuid::Uuid, pub session_token: String, pub etag: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub schema_version: String, diff --git a/sdk/data_cosmos/src/operations/get_document.rs b/sdk/data_cosmos/src/operations/get_document.rs index f8f586afb77..efd7929b6a5 100644 --- a/sdk/data_cosmos/src/operations/get_document.rs +++ b/sdk/data_cosmos/src/operations/get_document.rs @@ -7,8 +7,8 @@ use crate::ResourceQuota; use azure_core::headers::{etag_from_headers, session_token_from_headers, Headers}; use azure_core::{collect_pinned_stream, Response as HttpResponse, SessionToken}; use azure_core::{prelude::*, StatusCode}; -use chrono::{DateTime, Utc}; use serde::de::DeserializeOwned; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct GetDocumentBuilder { @@ -35,7 +35,7 @@ impl GetDocumentBuilder { setters! { consistency_level: ConsistencyLevel => Some(consistency_level), if_match_condition: IfMatchCondition => Some(if_match_condition), - if_modified_since: DateTime => Some(IfModifiedSince::new(if_modified_since)), + if_modified_since: OffsetDateTime => Some(IfModifiedSince::new(if_modified_since)), context: Context => context, } } @@ -126,7 +126,7 @@ where pub struct FoundDocumentResponse { pub document: Document, pub content_location: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub etag: String, pub resource_quota: Vec, pub resource_usage: Vec, @@ -146,7 +146,7 @@ pub struct FoundDocumentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl FoundDocumentResponse @@ -186,7 +186,7 @@ where #[derive(Debug, Clone)] pub struct NotFoundDocumentResponse { pub content_location: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub lsn: u64, pub schema_version: String, pub current_write_quorum: Option, @@ -202,7 +202,7 @@ pub struct NotFoundDocumentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl NotFoundDocumentResponse { diff --git a/sdk/data_cosmos/src/operations/get_partition_key_ranges.rs b/sdk/data_cosmos/src/operations/get_partition_key_ranges.rs index c66027f01fd..a80ad1f584f 100644 --- a/sdk/data_cosmos/src/operations/get_partition_key_ranges.rs +++ b/sdk/data_cosmos/src/operations/get_partition_key_ranges.rs @@ -3,7 +3,7 @@ use crate::prelude::*; use crate::resources::ResourceType; use azure_core::headers::{item_count_from_headers, session_token_from_headers}; use azure_core::{collect_pinned_stream, prelude::*, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { GetPartitionKeyRanges, @@ -52,7 +52,7 @@ pub struct GetPartitionKeyRangesResponse { pub rid: String, pub content_location: String, pub server: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub lsn: u64, pub item_count: u32, pub schema_version: String, @@ -67,7 +67,7 @@ pub struct GetPartitionKeyRangesResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, pub partition_key_ranges: Vec, } diff --git a/sdk/data_cosmos/src/operations/list_attachments.rs b/sdk/data_cosmos/src/operations/list_attachments.rs index 1c8394b2551..fcb362a1dbe 100644 --- a/sdk/data_cosmos/src/operations/list_attachments.rs +++ b/sdk/data_cosmos/src/operations/list_attachments.rs @@ -9,7 +9,7 @@ use azure_core::headers::{ }; use azure_core::prelude::*; use azure_core::{Pageable, Response as HttpResponse, SessionToken}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { #[stream] @@ -84,7 +84,7 @@ pub struct ListAttachmentsResponse { pub max_media_storage_usage_mb: u64, pub media_storage_usage_mb: u64, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub lsn: u64, @@ -100,7 +100,7 @@ pub struct ListAttachmentsResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, pub continuation_token: Option, } diff --git a/sdk/data_cosmos/src/operations/list_collections.rs b/sdk/data_cosmos/src/operations/list_collections.rs index ce80d0167d0..06d71cc77a8 100644 --- a/sdk/data_cosmos/src/operations/list_collections.rs +++ b/sdk/data_cosmos/src/operations/list_collections.rs @@ -6,7 +6,7 @@ use azure_core::headers::{continuation_token_from_headers_optional, session_toke use azure_core::prelude::*; use azure_core::Response as HttpResponse; use azure_core::{collect_pinned_stream, Pageable}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { #[stream] @@ -50,7 +50,7 @@ pub struct ListCollectionsResponse { pub rid: String, pub collections: Vec, pub count: u32, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub schema_version: String, diff --git a/sdk/data_cosmos/src/operations/list_databases.rs b/sdk/data_cosmos/src/operations/list_databases.rs index 886aac31c54..e7c54949c2c 100644 --- a/sdk/data_cosmos/src/operations/list_databases.rs +++ b/sdk/data_cosmos/src/operations/list_databases.rs @@ -5,7 +5,7 @@ use crate::ResourceQuota; use azure_core::headers::{continuation_token_from_headers_optional, session_token_from_headers}; use azure_core::{collect_pinned_stream, prelude::*, Pageable, Response}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { #[stream] @@ -52,7 +52,7 @@ pub struct ListDatabasesResponse { pub activity_id: uuid::Uuid, pub charge: f64, pub session_token: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub schema_version: String, diff --git a/sdk/data_cosmos/src/operations/list_documents.rs b/sdk/data_cosmos/src/operations/list_documents.rs index 2391be2aed6..de84118ea53 100644 --- a/sdk/data_cosmos/src/operations/list_documents.rs +++ b/sdk/data_cosmos/src/operations/list_documents.rs @@ -8,8 +8,8 @@ use azure_core::headers::{ }; use azure_core::{collect_pinned_stream, Response, SessionToken}; use azure_core::{prelude::*, Pageable}; -use chrono::{DateTime, Utc}; use serde::de::DeserializeOwned; +use time::OffsetDateTime; operation! { #[stream] @@ -78,7 +78,7 @@ pub struct ListDocumentsResponse { pub rid: String, pub documents: Vec>, pub content_location: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub lsn: u64, @@ -100,7 +100,7 @@ pub struct ListDocumentsResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, pub continuation_token: Option, } diff --git a/sdk/data_cosmos/src/operations/list_stored_procedures.rs b/sdk/data_cosmos/src/operations/list_stored_procedures.rs index a8734cbc569..df395bb62cf 100644 --- a/sdk/data_cosmos/src/operations/list_stored_procedures.rs +++ b/sdk/data_cosmos/src/operations/list_stored_procedures.rs @@ -7,7 +7,7 @@ use azure_core::collect_pinned_stream; use azure_core::headers::{continuation_token_from_headers_optional, session_token_from_headers}; use azure_core::prelude::*; use azure_core::{Pageable, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { #[stream] @@ -63,7 +63,7 @@ pub struct ListStoredProceduresResponse { pub charge: f64, pub activity_id: uuid::Uuid, pub session_token: String, - pub last_change: DateTime, + pub last_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub gateway_version: String, diff --git a/sdk/data_cosmos/src/operations/list_triggers.rs b/sdk/data_cosmos/src/operations/list_triggers.rs index a7777893161..0f558065229 100644 --- a/sdk/data_cosmos/src/operations/list_triggers.rs +++ b/sdk/data_cosmos/src/operations/list_triggers.rs @@ -7,7 +7,7 @@ use azure_core::headers::item_count_from_headers; use azure_core::headers::{continuation_token_from_headers_optional, session_token_from_headers}; use azure_core::prelude::*; use azure_core::{Pageable, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { #[stream] @@ -63,7 +63,7 @@ pub struct ListTriggersResponse { pub triggers: Vec, pub content_location: String, pub server: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub continuation_token: Option, pub resource_quota: Vec, pub resource_usage: Vec, @@ -82,7 +82,7 @@ pub struct ListTriggersResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl ListTriggersResponse { diff --git a/sdk/data_cosmos/src/operations/list_user_defined_functions.rs b/sdk/data_cosmos/src/operations/list_user_defined_functions.rs index c09440824c5..c5249325782 100644 --- a/sdk/data_cosmos/src/operations/list_user_defined_functions.rs +++ b/sdk/data_cosmos/src/operations/list_user_defined_functions.rs @@ -8,7 +8,7 @@ use azure_core::headers::{ continuation_token_from_headers_optional, item_count_from_headers, session_token_from_headers, }; use azure_core::{prelude::*, Pageable, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { #[stream] @@ -67,7 +67,7 @@ pub struct ListUserDefinedFunctionsResponse { pub user_defined_functions: Vec, pub content_location: String, pub server: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub continuation_token: Option, pub resource_quota: Vec, pub resource_usage: Vec, @@ -86,7 +86,7 @@ pub struct ListUserDefinedFunctionsResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl ListUserDefinedFunctionsResponse { diff --git a/sdk/data_cosmos/src/operations/query_documents.rs b/sdk/data_cosmos/src/operations/query_documents.rs index 957462a044e..3808da3e111 100644 --- a/sdk/data_cosmos/src/operations/query_documents.rs +++ b/sdk/data_cosmos/src/operations/query_documents.rs @@ -14,9 +14,9 @@ use azure_core::Method; use azure_core::Pageable; use azure_core::Response as HttpResponse; use azure_core::SessionToken; -use chrono::{DateTime, Utc}; use serde::de::DeserializeOwned; use serde_json::Value; +use time::OffsetDateTime; operation! { #[stream] @@ -108,7 +108,7 @@ pub type QueryDocuments = Pageable, azure_core::err pub struct QueryDocumentsResponse { pub query_response_meta: QueryResponseMeta, pub results: Vec<(T, Option)>, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub lsn: u64, @@ -130,7 +130,7 @@ pub struct QueryDocumentsResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, pub continuation_token: Option, } diff --git a/sdk/data_cosmos/src/operations/replace_collection.rs b/sdk/data_cosmos/src/operations/replace_collection.rs index 436d1759a7d..6a9c1b7e345 100644 --- a/sdk/data_cosmos/src/operations/replace_collection.rs +++ b/sdk/data_cosmos/src/operations/replace_collection.rs @@ -5,7 +5,7 @@ use azure_core::headers::{ content_type_from_headers, etag_from_headers, session_token_from_headers, }; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { ReplaceCollection, @@ -78,8 +78,8 @@ pub struct ReplaceCollectionResponse { pub alt_content_path: String, pub service_version: String, pub quorum_acked_lsn: u64, - pub last_state_change: DateTime, - pub date: DateTime, + pub last_state_change: OffsetDateTime, + pub date: OffsetDateTime, pub content_location: String, pub activity_id: uuid::Uuid, pub schema_version: String, diff --git a/sdk/data_cosmos/src/operations/replace_document.rs b/sdk/data_cosmos/src/operations/replace_document.rs index 3031f2f7e61..061c10209ed 100644 --- a/sdk/data_cosmos/src/operations/replace_document.rs +++ b/sdk/data_cosmos/src/operations/replace_document.rs @@ -8,8 +8,8 @@ use azure_core::headers::session_token_from_headers; use azure_core::prelude::*; use azure_core::SessionToken; use azure_core::{collect_pinned_stream, Response as HttpResponse}; -use chrono::{DateTime, Utc}; use serde::Serialize; +use time::OffsetDateTime; operation! { ReplaceDocument, @@ -70,7 +70,7 @@ impl ReplaceDocumentBuilder { pub struct ReplaceDocumentResponse { pub document_attributes: DocumentAttributes, pub content_location: String, - pub last_state_change: DateTime, + pub last_state_change: OffsetDateTime, pub resource_quota: Vec, pub resource_usage: Vec, pub lsn: u64, @@ -91,7 +91,7 @@ pub struct ReplaceDocumentResponse { pub service_version: String, pub activity_id: uuid::Uuid, pub gateway_version: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl ReplaceDocumentResponse { diff --git a/sdk/data_cosmos/src/time_nonce.rs b/sdk/data_cosmos/src/time_nonce.rs deleted file mode 100644 index d8c1a8ef359..00000000000 --- a/sdk/data_cosmos/src/time_nonce.rs +++ /dev/null @@ -1,32 +0,0 @@ -use chrono::{DateTime, Utc}; - -const TIME_FORMAT: &str = "%a, %d %h %Y %T GMT"; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub(crate) struct TimeNonce { - time: DateTime, -} - -impl TimeNonce { - pub fn new() -> Self { - Self { time: Utc::now() } - } -} - -impl From> for TimeNonce { - fn from(time: DateTime) -> Self { - Self { time } - } -} - -impl Default for TimeNonce { - fn default() -> Self { - Self::new() - } -} - -impl ToString for TimeNonce { - fn to_string(&self) -> String { - self.time.format(TIME_FORMAT).to_string() - } -} diff --git a/sdk/data_cosmos/tests/attachment_operations.rs b/sdk/data_cosmos/tests/attachment_operations.rs index ce53d6c8d03..5183a7de7d8 100644 --- a/sdk/data_cosmos/tests/attachment_operations.rs +++ b/sdk/data_cosmos/tests/attachment_operations.rs @@ -2,6 +2,7 @@ use azure_data_cosmos::prelude::*; use futures::StreamExt; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; mod setup; @@ -80,7 +81,7 @@ async fn attachment_operations() -> azure_core::Result<()> { id: id.clone(), a_string: "Something here".into(), a_number: 100, - a_timestamp: chrono::Utc::now().timestamp(), + a_timestamp: OffsetDateTime::now_utc().unix_timestamp(), }; // let's add an entity. diff --git a/sdk/data_tables/Cargo.toml b/sdk/data_tables/Cargo.toml index 71ccc7155b9..42c182325d5 100644 --- a/sdk/data_tables/Cargo.toml +++ b/sdk/data_tables/Cargo.toml @@ -16,7 +16,7 @@ edition = "2021" azure_core = { path = "../core", version = "0.3" } azure_storage = { path = "../storage", version = "0.4", default-features = false } bytes = "1.0" -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde"] } futures = "0.3" log = "0.4" serde = { version = "1.0" } diff --git a/sdk/device_update/Cargo.toml b/sdk/device_update/Cargo.toml index 0624f4de924..44e2579c394 100644 --- a/sdk/device_update/Cargo.toml +++ b/sdk/device_update/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" [dependencies] base64 = "0.13" reqwest = { version = "0.11", features = ["json"], default_features = false } -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde"] } const_format = "0.2" serde_json = "1.0" url = "2.2" diff --git a/sdk/device_update/src/device_update.rs b/sdk/device_update/src/device_update.rs index 353e0bbc0e7..5a5abb62a5e 100644 --- a/sdk/device_update/src/device_update.rs +++ b/sdk/device_update/src/device_update.rs @@ -3,12 +3,13 @@ use azure_core::{ error::{Error, ErrorKind, ResultExt}, sleep, }; -use chrono::{DateTime, Utc}; use getset::Getters; use log::debug; use serde::Deserialize; use serde_json::{Map, Value}; use std::fmt::Debug; +use std::time::Duration; +use time::OffsetDateTime; #[derive(Debug, Deserialize, Getters)] #[getset(get = "pub")] @@ -83,11 +84,13 @@ pub struct Instructions { #[serde(rename_all = "camelCase")] pub struct Update { compatibility: Vec>, - created_date_time: DateTime, + #[serde(with = "azure_core::date::rfc3339")] + created_date_time: OffsetDateTime, description: Option, etag: String, friendly_name: Option, - imported_date_time: DateTime, + #[serde(with = "azure_core::date::rfc3339")] + imported_date_time: OffsetDateTime, installed_criteria: Option, instructions: Option, is_deployable: bool, @@ -125,10 +128,12 @@ pub enum OperationStatus { #[getset(get = "pub")] #[serde(rename_all = "camelCase")] pub struct UpdateOperation { - pub created_date_time: DateTime, + #[serde(with = "azure_core::date::rfc3339")] + pub created_date_time: OffsetDateTime, pub error: Option, pub etag: String, - pub last_action_date_time: DateTime, + #[serde(with = "azure_core::date::rfc3339")] + pub last_action_date_time: OffsetDateTime, pub operation_id: String, pub resource_location: Option, pub status: OperationStatus, @@ -179,7 +184,7 @@ impl DeviceUpdateClient { debug!("Import response: {}", &resp_body); loop { - sleep(std::time::Duration::from_secs(5)).await; + sleep(Duration::from_secs(5)).await; let mut uri = self.device_update_url.clone(); uri.set_path(&resp_body); debug!("Requesting operational status: {}", &uri); @@ -503,7 +508,7 @@ impl DeviceUpdateClient { #[cfg(test)] mod tests { - use chrono::DateTime; + use azure_core::date; use mockito::{mock, Matcher}; use serde_json::json; @@ -553,11 +558,11 @@ mod tests { assert_eq!(update.operation_id, "some_op_id"); assert_eq!( update.created_date_time, - DateTime::parse_from_rfc3339("1999-09-10T21:59:22Z").unwrap() + date::parse_rfc3339("1999-09-10T21:59:22Z").unwrap() ); assert_eq!( update.last_action_date_time, - DateTime::parse_from_rfc3339("1999-09-10T02:05:07.3845533Z").unwrap() + date::parse_rfc3339("1999-09-10T02:05:07.3845533Z").unwrap() ); Ok(()) diff --git a/sdk/device_update/src/lib.rs b/sdk/device_update/src/lib.rs index 87e5389dca7..81d3ae88995 100644 --- a/sdk/device_update/src/lib.rs +++ b/sdk/device_update/src/lib.rs @@ -9,9 +9,10 @@ use crate::device_update::UpdateOperation; #[cfg(test)] mod tests { use azure_core::auth::{AccessToken, TokenCredential, TokenResponse}; + use azure_core::date; use azure_identity::AutoRefreshingTokenCredential; - use chrono::{Duration, Utc}; use std::sync::Arc; + use time::OffsetDateTime; pub(crate) fn mock_client() -> crate::client::DeviceUpdateClient { crate::client::DeviceUpdateClient { @@ -32,7 +33,7 @@ mod tests { ) -> Result { Ok(TokenResponse::new( AccessToken::new("TOKEN".to_owned()), - Utc::now() + Duration::days(14), + OffsetDateTime::now_utc() + date::duration_from_days(14), )) } } diff --git a/sdk/identity/Cargo.toml b/sdk/identity/Cargo.toml index 1476438e5b4..13ac8ba2f3f 100644 --- a/sdk/identity/Cargo.toml +++ b/sdk/identity/Cargo.toml @@ -19,7 +19,7 @@ oauth2 = { version = "4.0.0", default-features = false } url = "2.2" futures = "0.3" serde = { version = "1.0", features = ["derive"] } -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde", "macros", "local-offset"] } serde_json = "1.0" log = "0.4" async-timer = "1.0.0-beta.7" diff --git a/sdk/identity/examples/client_credentials_flow_blob.rs b/sdk/identity/examples/client_credentials_flow_blob.rs index 288e79086bf..a06c240c635 100644 --- a/sdk/identity/examples/client_credentials_flow_blob.rs +++ b/sdk/identity/examples/client_credentials_flow_blob.rs @@ -1,5 +1,7 @@ +use azure_core::date; use azure_identity::client_credentials_flow; use oauth2::{ClientId, ClientSecret}; +use time::OffsetDateTime; use std::env; use std::error::Error; @@ -37,8 +39,8 @@ async fn main() -> Result<(), Box> { println!("token received: {:?}", token); println!("token secret: {}", token.access_token().secret()); - let dt = chrono::Utc::now(); - let time = format!("{}", dt.format("%a, %d %h %Y %T GMT")); + let dt = OffsetDateTime::now_utc(); + let time = date::to_rfc1123(&dt); println!("x-ms-date ==> {}", time); let resp = reqwest::Client::new() diff --git a/sdk/identity/examples/code_flow_blob.rs b/sdk/identity/examples/code_flow_blob.rs index 8cbb9873aa5..98a22c20412 100644 --- a/sdk/identity/examples/code_flow_blob.rs +++ b/sdk/identity/examples/code_flow_blob.rs @@ -1,7 +1,9 @@ +use azure_core::date; use azure_identity::*; use oauth2::{ClientId, ClientSecret, TokenResponse}; use std::env; use std::error::Error; +use time::OffsetDateTime; use url::Url; #[tokio::main] @@ -48,8 +50,8 @@ async fn main() -> Result<(), Box> { println!("token secret: {}", token.access_token().secret()); - let dt = chrono::Utc::now(); - let time = format!("{}", dt.format("%a, %d %h %Y %T GMT")); + let dt = OffsetDateTime::now_utc(); + let time = date::to_rfc1123(&dt); println!("x-ms-date ==> {}", time); let resp = reqwest::Client::new() diff --git a/sdk/identity/src/client_credentials_flow/login_response.rs b/sdk/identity/src/client_credentials_flow/login_response.rs index 0bd3180a8d7..5c33e7fe174 100644 --- a/sdk/identity/src/client_credentials_flow/login_response.rs +++ b/sdk/identity/src/client_credentials_flow/login_response.rs @@ -1,6 +1,6 @@ use azure_core::auth::AccessToken; -use chrono::{DateTime, TimeZone, Utc}; use serde::{de, Deserialize, Deserializer}; +use time::OffsetDateTime; #[derive(Debug, Clone, Deserialize)] struct _LoginResponse { @@ -18,8 +18,8 @@ pub struct LoginResponse { pub token_type: String, pub expires_in: u64, pub ext_expires_in: u64, - pub expires_on: Option>, - pub not_before: Option>, + pub expires_on: Option, + pub not_before: Option, pub resource: Option, pub access_token: AccessToken, } @@ -40,14 +40,14 @@ impl LoginResponse { } fn from_base_response(r: _LoginResponse) -> Result { - let expires_on: Option> = match r.expires_on { - Some(d) => Some(Utc.timestamp(d.parse()?, 0)), - None => None, - }; - let not_before: Option> = match r.not_before { - Some(d) => Some(Utc.timestamp(d.parse()?, 0)), - None => None, - }; + let expires_on: Option = r.expires_on.map(|d| { + OffsetDateTime::from_unix_timestamp(d.parse::().unwrap_or(0)) + .unwrap_or(OffsetDateTime::UNIX_EPOCH) + }); + let not_before: Option = r.not_before.map(|d| { + OffsetDateTime::from_unix_timestamp(d.parse::().unwrap_or(0)) + .unwrap_or(OffsetDateTime::UNIX_EPOCH) + }); Ok(LoginResponse { token_type: r.token_type, diff --git a/sdk/identity/src/device_code_flow/mod.rs b/sdk/identity/src/device_code_flow/mod.rs index dec9eb8a79f..ab59b864ac6 100644 --- a/sdk/identity/src/device_code_flow/mod.rs +++ b/sdk/identity/src/device_code_flow/mod.rs @@ -16,7 +16,8 @@ pub use device_code_responses::*; use futures::stream::unfold; use oauth2::ClientId; use serde::Deserialize; -use std::{borrow::Cow, sync::Arc, time::Duration}; +use std::time::Duration; +use std::{borrow::Cow, sync::Arc}; use url::{form_urlencoded, Url}; /// Start the device authorization grant flow. diff --git a/sdk/identity/src/token_credentials/auto_refreshing_credentials.rs b/sdk/identity/src/token_credentials/auto_refreshing_credentials.rs index c3b2e68f309..8138d4033a9 100644 --- a/sdk/identity/src/token_credentials/auto_refreshing_credentials.rs +++ b/sdk/identity/src/token_credentials/auto_refreshing_credentials.rs @@ -1,11 +1,12 @@ use async_lock::RwLock; use azure_core::auth::{TokenCredential, TokenResponse}; use azure_core::error::{Error, ErrorKind}; -use chrono::{Duration, Utc}; use std::sync::Arc; +use std::time::Duration; +use time::OffsetDateTime; fn is_expired(token: &TokenResponse) -> bool { - token.expires_on < Utc::now() + Duration::seconds(20) + token.expires_on < OffsetDateTime::now_utc() + Duration::from_secs(20) } #[derive(Clone)] diff --git a/sdk/identity/src/token_credentials/azure_cli_credentials.rs b/sdk/identity/src/token_credentials/azure_cli_credentials.rs index 7259cc594c4..e17f8af7858 100644 --- a/sdk/identity/src/token_credentials/azure_cli_credentials.rs +++ b/sdk/identity/src/token_credentials/azure_cli_credentials.rs @@ -1,26 +1,36 @@ use azure_core::auth::{AccessToken, TokenCredential, TokenResponse}; use azure_core::error::{Error, ErrorKind, ResultExt}; -use chrono::{DateTime, Utc}; use serde::Deserialize; use std::process::Command; use std::str; +use time::OffsetDateTime; mod az_cli_date_format { - use chrono::{DateTime, Local, TimeZone, Utc}; + use azure_core::date; + use azure_core::error::{ErrorKind, ResultExt}; use serde::{self, Deserialize, Deserializer}; + use time::format_description::FormatItem; + use time::macros::format_description; + use time::{OffsetDateTime, PrimitiveDateTime}; - const FORMAT: &str = "%Y-%m-%d %H:%M:%S.%6f"; + const FORMAT: &[FormatItem] = + format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:6]"); - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + pub fn parse(s: &str) -> azure_core::Result { + // expiresOn from azure cli uses the local timezone and needs to be converted to UTC + let dt = PrimitiveDateTime::parse(s, FORMAT) + .with_context(ErrorKind::DataConversion, || { + format!("unable to parse expiresOn '{s}") + })?; + Ok(date::assume_local(&dt)) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; - // expiresOn from azure cli uses the local timezone and needs to be converted to UTC - let local_datetime = Local - .datetime_from_str(&s, FORMAT) - .map_err(serde::de::Error::custom)?; - Ok(local_datetime.with_timezone(&Utc)) + parse(&s).map_err(serde::de::Error::custom) } } @@ -29,7 +39,7 @@ mod az_cli_date_format { struct CliTokenResponse { pub access_token: AccessToken, #[serde(with = "az_cli_date_format")] - pub expires_on: DateTime, + pub expires_on: OffsetDateTime, pub subscription: String, pub tenant: String, #[allow(unused)] @@ -74,7 +84,7 @@ impl AzureCliCredential { Ok(az_output) => { let output = String::from_utf8_lossy(&az_output.stderr); Err(Error::with_message(ErrorKind::Credential, || { - format!("az account get-access-token command failed: {output}") + format!("'az account get-access-token' command failed: {output}") })) } Err(e) => match e.kind() { @@ -112,26 +122,17 @@ impl TokenCredential for AzureCliCredential { #[cfg(test)] mod tests { - use chrono::TimeZone; - use serde_test::{assert_de_tokens, Token}; - use super::*; + use azure_core::date; + use time::macros::datetime; - #[derive(Debug, Deserialize)] - struct AzureDateTime { - #[serde(with = "az_cli_date_format")] - date: DateTime, - } #[test] - fn can_parse_cli_datetime() { - let s = "2020-11-16T04:25:03Z"; - let utc = Utc.ymd(2020, 11, 16).and_hms(4, 25, 3); - let dt = AzureDateTime { date: utc }; - assert_de_tokens(&dt.date, &[Token::Str(s)]); - - let s = "2020-11-16 04:25:03Z"; - let utc = Utc.ymd(2020, 11, 16).and_hms(4, 25, 3); - let dt = AzureDateTime { date: utc }; - assert_de_tokens(&dt.date, &[Token::Str(s)]); + fn can_parse_expires_on() -> azure_core::Result<()> { + let expires_on = "2022-07-30 12:12:53.919110"; + assert_eq!( + az_cli_date_format::parse(expires_on)?, + date::assume_local(&datetime!(2022-07-30 12:12:53.919110)) + ); + Ok(()) } } diff --git a/sdk/identity/src/token_credentials/client_certificate_credentials.rs b/sdk/identity/src/token_credentials/client_certificate_credentials.rs index 9a56c488c1b..1b11e67b27e 100644 --- a/sdk/identity/src/token_credentials/client_certificate_credentials.rs +++ b/sdk/identity/src/token_credentials/client_certificate_credentials.rs @@ -12,7 +12,8 @@ use openssl::{ x509::X509, }; use serde::Deserialize; -use std::{str, time::Duration}; +use std::str; +use std::time::Duration; /// Refresh time to use in seconds const DEFAULT_REFRESH_TIME: i64 = 300; @@ -161,7 +162,7 @@ impl TokenCredential for ClientCertificateCredential { .map_err(ClientCertificateCredentialError::OpensslError)?; let uuid = uuid::Uuid::new_v4(); - let current_time = Utc::now().timestamp(); + let current_time = OffsetDateTime::now_utc().unix_timestamp(); let expiry_time = current_time + DEFAULT_REFRESH_TIME; let x5t = base64::encode(&thumbprint); @@ -224,8 +225,7 @@ impl TokenCredential for ClientCertificateCredential { Ok(TokenResponse::new( AccessToken::new(response.access_token.to_string()), - Utc::now() - + chrono::Duration::from_std(Duration::from_secs(response.expires_in)).unwrap(), + OffsetDateTime::now_utc() + Duration::from_secs(response.expires_in), )) } } diff --git a/sdk/identity/src/token_credentials/client_secret_credentials.rs b/sdk/identity/src/token_credentials/client_secret_credentials.rs index 7940c681280..b1c776cbd71 100644 --- a/sdk/identity/src/token_credentials/client_secret_credentials.rs +++ b/sdk/identity/src/token_credentials/client_secret_credentials.rs @@ -1,8 +1,8 @@ use azure_core::auth::{AccessToken, TokenCredential, TokenResponse}; use azure_core::error::{ErrorKind, ResultExt}; -use chrono::Utc; use oauth2::{basic::BasicClient, reqwest::async_http_client, AuthType, AuthUrl, Scope, TokenUrl}; -use std::{str, time::Duration}; +use std::str; +use time::OffsetDateTime; use url::Url; /// Provides options to configure how the Identity library makes authentication @@ -141,11 +141,7 @@ impl TokenCredential for ClientSecretCredential { use oauth2::TokenResponse as _; TokenResponse::new( AccessToken::new(r.access_token().secret().to_owned()), - Utc::now() - + chrono::Duration::from_std( - r.expires_in().unwrap_or_else(|| Duration::from_secs(0)), - ) - .unwrap(), + OffsetDateTime::now_utc() + r.expires_in().unwrap_or_default(), ) }) .context(ErrorKind::Credential, "request token error")?; diff --git a/sdk/identity/src/token_credentials/imds_managed_identity_credentials.rs b/sdk/identity/src/token_credentials/imds_managed_identity_credentials.rs index ca487debc9f..245441fd749 100644 --- a/sdk/identity/src/token_credentials/imds_managed_identity_credentials.rs +++ b/sdk/identity/src/token_credentials/imds_managed_identity_credentials.rs @@ -3,13 +3,13 @@ use azure_core::{ error::{Error, ErrorKind, ResultExt}, HttpClient, Method, Request, StatusCode, }; -use chrono::{DateTime, TimeZone, Utc}; use serde::{ de::{self, Deserializer}, Deserialize, }; use std::str; use std::sync::Arc; +use time::OffsetDateTime; use url::Url; const MSI_ENDPOINT_ENV_KEY: &str = "IDENTITY_ENDPOINT"; @@ -154,13 +154,13 @@ impl TokenCredential for ImdsManagedIdentityCredential { } } -fn expires_on_string<'de, D>(deserializer: D) -> std::result::Result, D::Error> +fn expires_on_string<'de, D>(deserializer: D) -> std::result::Result where D: Deserializer<'de>, { let v = String::deserialize(deserializer)?; let as_i64 = v.parse::().map_err(de::Error::custom)?; - Ok(Utc.timestamp(as_i64, 0)) + OffsetDateTime::from_unix_timestamp(as_i64).map_err(de::Error::custom) } // NOTE: expires_on is a String version of unix epoch time, not an integer. @@ -170,7 +170,7 @@ where struct MsiTokenResponse { pub access_token: AccessToken, #[serde(deserialize_with = "expires_on_string")] - pub expires_on: DateTime, + pub expires_on: OffsetDateTime, pub token_type: String, pub resource: String, } @@ -178,17 +178,18 @@ struct MsiTokenResponse { #[cfg(test)] mod tests { use super::*; + use time::macros::datetime; #[derive(Debug, Deserialize)] struct TestExpires { #[serde(deserialize_with = "expires_on_string")] - date: DateTime, + date: OffsetDateTime, } #[test] fn check_expires_on_string() { let as_string = r#"{"date": "1586984735"}"#; - let expected = Utc.ymd(2020, 4, 15).and_hms(21, 5, 35); + let expected = datetime!(2020-4-15 21:5:35 UTC); let parsed: TestExpires = serde_json::from_str(as_string).expect("deserialize should succeed"); assert_eq!(expected, parsed.date); diff --git a/sdk/iot_hub/Cargo.toml b/sdk/iot_hub/Cargo.toml index 3c8786dc7b8..b1ab9ecc681 100644 --- a/sdk/iot_hub/Cargo.toml +++ b/sdk/iot_hub/Cargo.toml @@ -10,7 +10,7 @@ license = "MIT" azure_core = { path = "../core", version = "0.3", default_features = false } base64 = "0.13" bytes = "1.0" -chrono = "0.4" +time = "0.3" hmac = "0.12" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/sdk/iot_hub/src/service/mod.rs b/sdk/iot_hub/src/service/mod.rs index 37b1fc71f6d..6ae5050879b 100644 --- a/sdk/iot_hub/src/service/mod.rs +++ b/sdk/iot_hub/src/service/mod.rs @@ -5,6 +5,8 @@ use base64::{decode, encode_config}; use hmac::{Hmac, Mac}; use sha2::Sha256; use std::sync::Arc; +use std::time::Duration; +use time::OffsetDateTime; /// Contains any operation that the IoT Hub service client can perform. pub mod operations; @@ -79,11 +81,11 @@ impl ServiceClient { iot_hub_name: &str, key_name: &str, private_key: &str, - expires_in_seconds: i64, + expires_in_seconds: u64, ) -> azure_core::Result { type HmacSHA256 = Hmac; - let expiry_date = chrono::Utc::now() + chrono::Duration::seconds(expires_in_seconds); - let expiry_date_seconds = expiry_date.timestamp(); + let expiry_date = OffsetDateTime::now_utc() + Duration::from_secs(expires_in_seconds); + let expiry_date_seconds = expiry_date.unix_timestamp(); let data = format!( "{}.azure-devices.net\n{}", iot_hub_name, &expiry_date_seconds @@ -134,7 +136,7 @@ impl ServiceClient { iot_hub_name: S, key_name: T, private_key: U, - expires_in_seconds: i64, + expires_in_seconds: u64, ) -> azure_core::Result where S: Into, @@ -174,7 +176,7 @@ impl ServiceClient { pub fn from_connection_string( http_client: Arc, connection_string: S, - expires_in_seconds: i64, + expires_in_seconds: u64, ) -> azure_core::Result where S: AsRef, diff --git a/sdk/messaging_eventgrid/Cargo.toml b/sdk/messaging_eventgrid/Cargo.toml index 04089f61115..e03050b9a5d 100644 --- a/sdk/messaging_eventgrid/Cargo.toml +++ b/sdk/messaging_eventgrid/Cargo.toml @@ -14,7 +14,7 @@ edition = "2021" [dependencies] azure_core = { path = "../core", version = "0.3", default_features = false } -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde", "macros"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "1.0", features = ["v4"] } @@ -24,4 +24,4 @@ url = "2.2" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } [features] -default = ["azure_core/default"] \ No newline at end of file +default = ["azure_core/default"] diff --git a/sdk/messaging_eventgrid/src/event.rs b/sdk/messaging_eventgrid/src/event.rs index 78ae9485046..505c558414d 100644 --- a/sdk/messaging_eventgrid/src/event.rs +++ b/sdk/messaging_eventgrid/src/event.rs @@ -1,5 +1,5 @@ -use chrono::{DateTime, Utc}; use serde::{self, Serialize}; +use time::OffsetDateTime; use uuid::Uuid; #[derive(Serialize, Debug)] @@ -14,7 +14,8 @@ where pub id: String, pub event_type: String, pub subject: String, - pub event_time: DateTime, + #[serde(with = "azure_core::date::rfc3339")] + pub event_time: OffsetDateTime, pub data: Option, pub data_version: String, pub metadata_version: Option, @@ -52,7 +53,7 @@ where subject: subject.to_owned(), data_version: data_version.unwrap_or_else(|| String::from("0.1")), data: Some(data), - event_time: Utc::now(), + event_time: OffsetDateTime::now_utc(), topic: None, metadata_version: None, } @@ -62,8 +63,8 @@ where #[cfg(test)] mod tests { use super::*; - use chrono::{DateTime, NaiveDate, Utc}; use serde::{self, Serialize}; + use time::macros::datetime; #[derive(Serialize)] struct Data { @@ -79,8 +80,7 @@ mod tests { Data { number: 42 }, Some(String::from("1.0")), ); - event.event_time = - DateTime::::from_utc(NaiveDate::from_ymd(2020, 12, 21).and_hms(14, 53, 41), Utc); + event.event_time = datetime!(2020-12-21 14:53:41 UTC); assert_eq!( serde_json::to_string(&event).unwrap(), diff --git a/sdk/messaging_servicebus/Cargo.toml b/sdk/messaging_servicebus/Cargo.toml index 3e518e6853d..bf7f9acd510 100644 --- a/sdk/messaging_servicebus/Cargo.toml +++ b/sdk/messaging_servicebus/Cargo.toml @@ -17,7 +17,7 @@ edition = "2021" [dependencies] azure_core = { path = "../core", version = "0.3" } base64 = "0.13" -chrono = "0.4" +time = "0.3" log = "0.4" url = "2.2" hmac = "0.12" diff --git a/sdk/messaging_servicebus/src/service_bus/client.rs b/sdk/messaging_servicebus/src/service_bus/client.rs index 559a2e9ffaa..16868d1cf09 100644 --- a/sdk/messaging_servicebus/src/service_bus/client.rs +++ b/sdk/messaging_servicebus/src/service_bus/client.rs @@ -7,8 +7,8 @@ use crate::{ }, utils::body_bytes_to_utf8, }; -use chrono::Duration; use ring::hmac::Key; +use std::time::Duration; use azure_core::{error::Error, HttpClient}; diff --git a/sdk/messaging_servicebus/src/service_bus/mod.rs b/sdk/messaging_servicebus/src/service_bus/mod.rs index 1c654c2379d..f6d95ef6ccf 100644 --- a/sdk/messaging_servicebus/src/service_bus/mod.rs +++ b/sdk/messaging_servicebus/src/service_bus/mod.rs @@ -1,8 +1,9 @@ use azure_core::{error::Error, headers, CollectedResponse, HttpClient, Request, Url}; use azure_core::{Method, StatusCode}; -use chrono::Duration; use ring::hmac; +use std::time::Duration; use std::{ops::Add, sync::Arc}; +use time::OffsetDateTime; use url::form_urlencoded::{self, Serializer}; mod client; @@ -12,7 +13,7 @@ use crate::utils::{body_bytes_to_utf8, craft_peek_lock_url}; pub use self::client::Client; /// Default duration for the SAS token in days — We might want to make this configurable at some point -const DEFAULT_SAS_DURATION: i64 = 1; +const DEFAULT_SAS_DURATION: u64 = 3_600; // seconds = 1 hour /// Prepares an HTTP request fn finalize_request( @@ -27,7 +28,7 @@ fn finalize_request( policy_name, signing_key, url, - Duration::hours(DEFAULT_SAS_DURATION), + Duration::from_secs(DEFAULT_SAS_DURATION), ); // create request builder @@ -56,7 +57,7 @@ fn generate_signature( ttl: Duration, ) -> String { let sr: String = form_urlencoded::byte_serialize(url.as_bytes()).collect(); // .servicebus.windows.net - let se = ::chrono::Utc::now().add(ttl).timestamp(); // token expiry instant + let se = OffsetDateTime::now_utc().add(ttl).unix_timestamp(); // token expiry instant let str_to_sign = format!("{}\n{}", sr, se); let sig = hmac::sign(signing_key, str_to_sign.as_bytes()); // shared access key diff --git a/sdk/messaging_servicebus/src/utils.rs b/sdk/messaging_servicebus/src/utils.rs index 74f17e4089e..d1a83112bb6 100644 --- a/sdk/messaging_servicebus/src/utils.rs +++ b/sdk/messaging_servicebus/src/utils.rs @@ -1,5 +1,5 @@ use azure_core::error::{Error, ErrorKind, ResultExt}; -use chrono::Duration; +use std::time::Duration; use url::Url; pub fn craft_peek_lock_url( @@ -19,7 +19,7 @@ pub fn craft_peek_lock_url( // add timeout, if given if let Some(t) = lock_expiry { url.query_pairs_mut() - .append_pair("timeout", &t.num_seconds().to_string()); + .append_pair("timeout", &t.as_secs().to_string()); }; Ok(url) diff --git a/sdk/messaging_servicebus/tests/service_bus.rs b/sdk/messaging_servicebus/tests/service_bus.rs index de2a9887514..1a121b384a4 100644 --- a/sdk/messaging_servicebus/tests/service_bus.rs +++ b/sdk/messaging_servicebus/tests/service_bus.rs @@ -2,7 +2,7 @@ extern crate log; use azure_messaging_servicebus::service_bus::Client; -use chrono::Duration; +use std::time::Duration; #[tokio::test] async fn send_message_test() { @@ -61,7 +61,7 @@ async fn renew_message_lock_test() { let client = create_client().unwrap(); send_message_test(); // send message to ensure we can receive something client - .peek_lock_message2(Some(Duration::seconds(60))) + .peek_lock_message2(Some(Duration::from_secs(60))) .await .expect("Failed to receive message") .renew_message_lock() diff --git a/sdk/security_keyvault/Cargo.toml b/sdk/security_keyvault/Cargo.toml index 3af7d25bf20..b2a1ebc6023 100644 --- a/sdk/security_keyvault/Cargo.toml +++ b/sdk/security_keyvault/Cargo.toml @@ -16,7 +16,7 @@ edition = "2021" futures = "0.3" base64 = "0.13" reqwest = { version = "0.11", features = ["json"] } -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde"] } const_format = "0.2.13" serde_json = "1.0" url = "2.2" diff --git a/sdk/security_keyvault/examples/update_secret.rs b/sdk/security_keyvault/examples/update_secret.rs index b4f2ccc507f..40c067faeaa 100644 --- a/sdk/security_keyvault/examples/update_secret.rs +++ b/sdk/security_keyvault/examples/update_secret.rs @@ -1,9 +1,9 @@ +use azure_core::date; use azure_identity::{ClientSecretCredential, TokenCredentialOptions}; use azure_security_keyvault::SecretClient; -use chrono::prelude::*; -use chrono::Duration; use std::env; use std::sync::Arc; +use time::OffsetDateTime; #[tokio::main] async fn main() -> Result<(), Box> { @@ -31,7 +31,7 @@ async fn main() -> Result<(), Box> { .version(secret_version) .enabled(false) .recovery_level("Purgeable") - .expiration(Utc::now() + Duration::days(14)) + .expiration(OffsetDateTime::now_utc() + date::duration_from_days(14)) .into_future() .await?; diff --git a/sdk/security_keyvault/src/certificates/models.rs b/sdk/security_keyvault/src/certificates/models.rs index d1d9ff8a8b4..c6b871b9fb3 100644 --- a/sdk/security_keyvault/src/certificates/models.rs +++ b/sdk/security_keyvault/src/certificates/models.rs @@ -1,20 +1,19 @@ -use chrono::serde::{ts_seconds, ts_seconds_option}; -use chrono::{DateTime, Utc}; use serde::Deserialize; +use time::OffsetDateTime; #[derive(Deserialize, Debug)] pub(crate) struct KeyVaultCertificateBaseIdentifierAttributedRaw { pub enabled: bool, #[serde(default)] - #[serde(with = "ts_seconds_option")] - pub exp: Option>, + #[serde(with = "azure_core::date::timestamp::option")] + pub exp: Option, #[serde(default)] - #[serde(with = "ts_seconds_option")] - pub nbf: Option>, - #[serde(with = "ts_seconds")] - pub created: DateTime, - #[serde(with = "ts_seconds")] - pub updated: DateTime, + #[serde(with = "azure_core::date::timestamp::option")] + pub nbf: Option, + #[serde(with = "azure_core::date::timestamp")] + pub created: OffsetDateTime, + #[serde(with = "azure_core::date::timestamp")] + pub updated: OffsetDateTime, } #[derive(Deserialize, Debug)] @@ -47,15 +46,15 @@ pub(crate) struct KeyVaultGetCertificateResponse { pub(crate) struct KeyVaultGetCertificateResponseAttributes { pub enabled: bool, #[serde(default)] - #[serde(with = "ts_seconds_option")] - pub exp: Option>, + #[serde(with = "azure_core::date::timestamp::option")] + pub exp: Option, #[serde(default)] - #[serde(with = "ts_seconds_option")] - pub nbf: Option>, - #[serde(with = "ts_seconds")] - pub created: DateTime, - #[serde(with = "ts_seconds")] - pub updated: DateTime, + #[serde(with = "azure_core::date::timestamp::option")] + pub nbf: Option, + #[serde(with = "azure_core::date::timestamp")] + pub created: OffsetDateTime, + #[serde(with = "azure_core::date::timestamp")] + pub updated: OffsetDateTime, #[serde(rename = "recoveryLevel")] #[allow(unused)] pub recovery_level: String, @@ -104,10 +103,10 @@ pub(crate) struct KeyVaultGetCertificateResponsePolicyIssuer { #[allow(unused)] pub(crate) struct KeyVaultGetCertificateResponsePolicyAttributes { pub enabled: bool, - #[serde(with = "ts_seconds")] - pub created: DateTime, - #[serde(with = "ts_seconds")] - pub updated: DateTime, + #[serde(with = "azure_core::date::timestamp")] + pub created: OffsetDateTime, + #[serde(with = "azure_core::date::timestamp")] + pub updated: OffsetDateTime, } #[derive(Deserialize, Debug)] @@ -130,9 +129,9 @@ pub struct CertificateProperties { pub id: String, pub name: String, pub version: String, - pub not_before: Option>, - pub expires_on: Option>, - pub created_on: DateTime, - pub updated_on: DateTime, + pub not_before: Option, + pub expires_on: Option, + pub created_on: OffsetDateTime, + pub updated_on: OffsetDateTime, pub enabled: bool, } diff --git a/sdk/security_keyvault/src/certificates/operations/update_properties.rs b/sdk/security_keyvault/src/certificates/operations/update_properties.rs index ef69b40cd70..a991e9e7a79 100644 --- a/sdk/security_keyvault/src/certificates/operations/update_properties.rs +++ b/sdk/security_keyvault/src/certificates/operations/update_properties.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::error::{ErrorKind, ResultExt}; -use chrono::{serde::ts_seconds_option, DateTime, Utc}; use serde::Serialize; +use time::OffsetDateTime; operation! { UpdateCertificateProperties, @@ -9,18 +9,18 @@ operation! { name: String, ?version: String, ?enabled: bool, - ?not_before: DateTime, - ?expiration: DateTime + ?not_before: OffsetDateTime, + ?expiration: OffsetDateTime } #[derive(Serialize, Debug)] #[serde(rename_all = "camelCase")] struct Attributes { enabled: Option, - #[serde(with = "ts_seconds_option", rename = "exp")] - expiration: Option>, - #[serde(with = "ts_seconds_option", rename = "nbf")] - not_before: Option>, + #[serde(with = "azure_core::date::timestamp::option", rename = "exp")] + expiration: Option, + #[serde(with = "azure_core::date::timestamp::option", rename = "nbf")] + not_before: Option, } #[derive(Serialize, Debug)] diff --git a/sdk/security_keyvault/src/clients/certificate_client.rs b/sdk/security_keyvault/src/clients/certificate_client.rs index 561c93985a5..7c55c1bea03 100644 --- a/sdk/security_keyvault/src/clients/certificate_client.rs +++ b/sdk/security_keyvault/src/clients/certificate_client.rs @@ -216,22 +216,16 @@ mod tests { use crate::mock_client; use crate::prelude::*; use crate::tests::MockCredential; - use chrono::{DateTime, Duration, Utc}; + use azure_core::date; use mockito::{mock, Matcher}; use serde_json::json; - - fn diff(first: DateTime, second: DateTime) -> Duration { - if first > second { - first - second - } else { - second - first - } - } + use std::time::Duration; + use time::OffsetDateTime; #[tokio::test] async fn get_certificate() { - let time_created = Utc::now() - Duration::days(7); - let time_updated = Utc::now(); + let time_created = OffsetDateTime::now_utc() - date::duration_from_days(7); + let time_updated = OffsetDateTime::now_utc(); let _m = mock("GET", "/certificates/test-certificate/") .match_query(Matcher::UrlEncoded("api-version".into(), API_VERSION.into())) .with_header("content-type", "application/json") @@ -244,8 +238,8 @@ mod tests { "cer": "MIICODCCAeagAwIBAgIQqHmpBAv+CY9IJFoUhlbziTAJBgUrDgMCHQUAMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5MB4XDTE1MDQyOTIxNTM0MVoXDTM5MTIzMTIzNTk1OVowFzEVMBMGA1UEAxMMS2V5VmF1bHRUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5bVAT73zr4+N4WVv2+SvTunAw08ksS4BrJW/nNliz3S9XuzMBMXvmYzU5HJ8TtEgluBiZZYd5qsMJD+OXHSNbsLdmMhni0jYX09h3XlC2VJw2sGKeYF+xEaavXm337aZZaZyjrFBrrUl51UePaN+kVFXNlBb3N3TYpqa7KokXenJQuR+i9Gv9a77c0UsSsDSryxppYhKK7HvTZCpKrhVtulF5iPMswWe9np3uggfMamyIsK/0L7X9w9B2qN7993RR0A00nOk4H6CnkuwO77dSsD0KJsk6FyAoZBzRXDZh9+d9R76zCL506NcQy/jl0lCiQYwsUX73PG5pxOh02OwKwIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwCQYFKw4DAh0FAANBAGqIjo2geVagzuzaZOe1ClGKhZeiCKfWAxklaGN+qlGUbVS4IN4V1lot3VKnzabasmkEHeNxPwLn1qvSD0cX9CE=", "attributes": { "enabled": true, - "created": time_created.timestamp(), - "updated": time_updated.timestamp(), + "created": time_created.unix_timestamp(), + "updated": time_updated.unix_timestamp(), "recoveryLevel": "Recoverable+Purgeable" }, "policy": { @@ -295,16 +289,20 @@ mod tests { "https://test-keyvault.vault.azure.net/keys/test-certificate/002ade539442463aba45c0efb42e3e84", certificate.key_id ); - assert!(diff(time_created, certificate.properties.created_on) < Duration::seconds(1)); - assert!(diff(time_updated, certificate.properties.updated_on) < Duration::seconds(1)); + assert!( + date::diff(time_created, certificate.properties.created_on) < Duration::from_secs(1) + ); + assert!( + date::diff(time_updated, certificate.properties.updated_on) < Duration::from_secs(1) + ); } #[tokio::test] async fn get_certificate_versions() { - let time_created_1 = Utc::now() - Duration::days(7); - let time_updated_1 = Utc::now(); - let time_created_2 = Utc::now() - Duration::days(9); - let time_updated_2 = Utc::now() - Duration::days(2); + let time_created_1 = OffsetDateTime::now_utc() - date::duration_from_days(7); + let time_updated_1 = OffsetDateTime::now_utc(); + let time_created_2 = OffsetDateTime::now_utc() - date::duration_from_days(9); + let time_updated_2 = OffsetDateTime::now_utc() - date::duration_from_days(2); let _m1 = mock("GET", "/certificates/test-certificate/versions") .match_query(Matcher::AllOf(vec![ @@ -318,8 +316,8 @@ mod tests { "x5t": "fLi3U52HunIVNXubkEnf8tP6Wbo", "attributes": { "enabled": true, - "created": time_created_1.timestamp(), - "updated": time_updated_1.timestamp(), + "created": time_created_1.unix_timestamp(), + "updated": time_updated_1.unix_timestamp(), } }], "nextLink": format!("{}/certificates/text-certificate/versions?api-version={}&maxresults=1&$skiptoken=SKIP_TOKEN_MOCK", mockito::server_url(), API_VERSION) @@ -343,8 +341,8 @@ mod tests { "x5t": "fLi3U52HunIVNXubkEnf8tP6Wbo", "attributes": { "enabled": true, - "created": time_created_2.timestamp(), - "updated": time_updated_2.timestamp(), + "created": time_created_2.unix_timestamp(), + "updated": time_updated_2.unix_timestamp(), } }], "nextLink": null @@ -369,15 +367,15 @@ mod tests { "https://test-keyvault.vault.azure.net/certificates/test-certificate/VERSION_1", certificate_1.id ); - assert!(diff(time_created_1, certificate_1.created_on) < Duration::seconds(1)); - assert!(diff(time_updated_1, certificate_1.updated_on) < Duration::seconds(1)); + assert!(date::diff(time_created_1, certificate_1.created_on) < Duration::from_secs(1)); + assert!(date::diff(time_updated_1, certificate_1.updated_on) < Duration::from_secs(1)); let certificate_2 = &certificate_versions[1]; assert_eq!( "https://test-keyvault.vault.azure.net/certificates/test-certificate/VERSION_2", certificate_2.id ); - assert!(diff(time_created_2, certificate_2.created_on) < Duration::seconds(1)); - assert!(diff(time_updated_2, certificate_2.updated_on) < Duration::seconds(1)); + assert!(date::diff(time_created_2, certificate_2.created_on) < Duration::from_secs(1)); + assert!(date::diff(time_updated_2, certificate_2.updated_on) < Duration::from_secs(1)); } } diff --git a/sdk/security_keyvault/src/clients/key_client.rs b/sdk/security_keyvault/src/clients/key_client.rs index 6e5e73f2d32..da15cf80f94 100644 --- a/sdk/security_keyvault/src/clients/key_client.rs +++ b/sdk/security_keyvault/src/clients/key_client.rs @@ -71,26 +71,18 @@ impl KeyClient { #[cfg(test)] mod tests { use super::*; - - use chrono::{DateTime, Duration, Utc}; - use mockito::{mock, Matcher}; - use serde_json::json; - use crate::mock_client; use crate::tests::MockCredential; - - fn diff(first: DateTime, second: DateTime) -> Duration { - if first > second { - first - second - } else { - second - first - } - } + use azure_core::date; + use mockito::{mock, Matcher}; + use serde_json::json; + use std::time::Duration; + use time::OffsetDateTime; #[tokio::test] async fn can_get_key() -> azure_core::Result<()> { - let time_created = Utc::now() - Duration::days(7); - let time_updated = Utc::now(); + let time_created = OffsetDateTime::now_utc() - date::duration_from_days(7); + let time_updated = OffsetDateTime::now_utc(); let _m = mock("GET", "/keys/test-key/78deebed173b48e48f55abf87ed4cf71") .match_query(Matcher::UrlEncoded("api-version".into(), API_VERSION.into())) .with_header("content-type", "application/json") @@ -113,8 +105,8 @@ mod tests { }, "attributes": { "enabled": true, - "created": time_created.timestamp(), - "updated": time_updated.timestamp(), + "created": time_created.unix_timestamp(), + "updated": time_updated.unix_timestamp(), "recoveryLevel": "Recoverable+Purgeable" }, "tags": { @@ -158,8 +150,8 @@ mod tests { assert!(managed.is_none()); assert_eq!(tags.unwrap().get("purpose").unwrap(), "unit test"); assert!(enabled.unwrap()); - assert!(diff(time_created, created_on.unwrap()) < Duration::seconds(1)); - assert!(diff(time_updated, updated_on.unwrap()) < Duration::seconds(1)); + assert!(date::diff(time_created, created_on.unwrap()) < Duration::from_secs(1)); + assert!(date::diff(time_updated, updated_on.unwrap()) < Duration::from_secs(1)); Ok(()) } diff --git a/sdk/security_keyvault/src/clients/keyvault_client.rs b/sdk/security_keyvault/src/clients/keyvault_client.rs index 7a87ca8db7e..7a578c3cf73 100644 --- a/sdk/security_keyvault/src/clients/keyvault_client.rs +++ b/sdk/security_keyvault/src/clients/keyvault_client.rs @@ -3,6 +3,7 @@ use azure_core::auth::{TokenCredential, TokenResponse}; use azure_core::error::{Error, ErrorKind, ResultExt}; use const_format::formatcp; use std::sync::Arc; +use time::OffsetDateTime; use url::Url; pub const API_VERSION: &str = "7.0"; @@ -99,7 +100,7 @@ impl KeyvaultClient { pub(crate) async fn get_token(&mut self) -> azure_core::Result<&str> { if self.token.is_none() - || matches!(&self.token, Some(token) if token.expires_on < chrono::Utc::now()) + || matches!(&self.token, Some(token) if token.expires_on < OffsetDateTime::now_utc()) { let token = self .token_credential diff --git a/sdk/security_keyvault/src/clients/secret_client.rs b/sdk/security_keyvault/src/clients/secret_client.rs index 7ef5718f5f7..6821edc4f6b 100644 --- a/sdk/security_keyvault/src/clients/secret_client.rs +++ b/sdk/security_keyvault/src/clients/secret_client.rs @@ -247,26 +247,19 @@ impl SecretClient { #[cfg(test)] #[allow(unused_must_use)] mod tests { - use chrono::{DateTime, Duration, Utc}; - use mockito::{mock, Matcher}; - use serde_json::json; - use crate::mock_client; use crate::prelude::API_VERSION; use crate::tests::MockCredential; - - fn diff(first: DateTime, second: DateTime) -> Duration { - if first > second { - first - second - } else { - second - first - } - } + use azure_core::date; + use mockito::{mock, Matcher}; + use serde_json::json; + use std::time::Duration; + use time::OffsetDateTime; #[tokio::test] async fn get_secret() -> azure_core::Result<()> { - let time_created = Utc::now() - Duration::days(7); - let time_updated = Utc::now(); + let time_created = OffsetDateTime::now_utc() - date::duration_from_days(7); + let time_updated = OffsetDateTime::now_utc(); let _m = mock("GET", "/secrets/test-secret/") .match_query(Matcher::UrlEncoded("api-version".into(), API_VERSION.into())) .with_header("content-type", "application/json") @@ -276,8 +269,8 @@ mod tests { "id": "https://test-keyvault.vault.azure.net/secrets/test-secret/4387e9f3d6e14c459867679a90fd0f79", "attributes": { "enabled": true, - "created": time_created.timestamp(), - "updated": time_updated.timestamp(), + "created": time_created.unix_timestamp(), + "updated": time_updated.unix_timestamp(), "recoveryLevel": "Recoverable+Purgeable" } }) @@ -298,17 +291,17 @@ mod tests { "https://test-keyvault.vault.azure.net/secrets/test-secret/4387e9f3d6e14c459867679a90fd0f79", secret.id ); - assert!(diff(time_created, secret.created_on) < Duration::seconds(1)); - assert!(diff(time_updated, secret.updated_on) < Duration::seconds(1)); + assert!(date::diff(time_created, secret.created_on) < Duration::from_secs(1)); + assert!(date::diff(time_updated, secret.updated_on) < Duration::from_secs(1)); Ok(()) } #[tokio::test] async fn get_secret_versions() -> azure_core::Result<()> { - let time_created_1 = Utc::now() - Duration::days(7); - let time_updated_1 = Utc::now(); - let time_created_2 = Utc::now() - Duration::days(9); - let time_updated_2 = Utc::now() - Duration::days(2); + let time_created_1 = OffsetDateTime::now_utc() - date::duration_from_days(7); + let time_updated_1 = OffsetDateTime::now_utc(); + let time_created_2 = OffsetDateTime::now_utc() - date::duration_from_days(9); + let time_updated_2 = OffsetDateTime::now_utc() - date::duration_from_days(2); let _m1 = mock("GET", "/secrets/test-secret/versions") .match_query(Matcher::AllOf(vec![ @@ -322,8 +315,8 @@ mod tests { "id": "https://test-keyvault.vault.azure.net/secrets/test-secret/VERSION_1", "attributes": { "enabled": true, - "created": time_created_1.timestamp(), - "updated": time_updated_1.timestamp(), + "created": time_created_1.unix_timestamp(), + "updated": time_updated_1.unix_timestamp(), } }], "nextLink": format!("{}/secrets/text-secret/versions?api-version={}&maxresults=1&$skiptoken=SKIP_TOKEN_MOCK", mockito::server_url(), API_VERSION) @@ -346,8 +339,8 @@ mod tests { "id": "https://test-keyvault.vault.azure.net/secrets/test-secret/VERSION_2", "attributes": { "enabled": true, - "created": time_created_2.timestamp(), - "updated": time_updated_2.timestamp(), + "created": time_created_2.unix_timestamp(), + "updated": time_updated_2.unix_timestamp(), } }], "nextLink": null @@ -370,16 +363,16 @@ mod tests { "https://test-keyvault.vault.azure.net/secrets/test-secret/VERSION_1", secret_1.id ); - assert!(diff(time_created_1, secret_1.created_on) < Duration::seconds(1)); - assert!(diff(time_updated_1, secret_1.updated_on) < Duration::seconds(1)); + assert!(date::diff(time_created_1, secret_1.created_on) < Duration::from_secs(1)); + assert!(date::diff(time_updated_1, secret_1.updated_on) < Duration::from_secs(1)); let secret_2 = &secret_versions[1]; assert_eq!( "https://test-keyvault.vault.azure.net/secrets/test-secret/VERSION_2", secret_2.id ); - assert!(diff(time_created_2, secret_2.created_on) < Duration::seconds(1)); - assert!(diff(time_updated_2, secret_2.updated_on) < Duration::seconds(1)); + assert!(date::diff(time_created_2, secret_2.created_on) < Duration::from_secs(1)); + assert!(date::diff(time_updated_2, secret_2.updated_on) < Duration::from_secs(1)); Ok(()) } } diff --git a/sdk/security_keyvault/src/keys/models.rs b/sdk/security_keyvault/src/keys/models.rs index a955bbc6e0a..6c79917f2e8 100644 --- a/sdk/security_keyvault/src/keys/models.rs +++ b/sdk/security_keyvault/src/keys/models.rs @@ -1,10 +1,9 @@ use azure_core::error::{Error, ErrorKind}; use base64::{CharacterSet, Config}; -use chrono::serde::ts_seconds_option; -use chrono::{DateTime, Utc}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_json::{Map, Value}; use std::fmt::{Debug, Display}; +use time::OffsetDateTime; /// A KeyBundle consisting of a WebKey plus its attributes. #[derive(Debug, Deserialize)] @@ -29,23 +28,31 @@ pub struct KeyProperties { #[serde(rename_all = "camelCase")] pub struct KeyAttributes { /// Creation time in UTC. - #[serde(rename = "created", with = "ts_seconds_option", default)] - pub created_on: Option>, + #[serde( + rename = "created", + with = "azure_core::date::timestamp::option", + default + )] + pub created_on: Option, /// Determines whether the object is enabled. pub enabled: Option, /// Expiry date in UTC. - #[serde(rename = "exp", with = "ts_seconds_option", default)] - pub expires_on: Option>, + #[serde(rename = "exp", with = "azure_core::date::timestamp::option", default)] + pub expires_on: Option, /// Not before date in UTC. - #[serde(rename = "nbf", with = "ts_seconds_option", default)] - pub not_before: Option>, + #[serde(rename = "nbf", with = "azure_core::date::timestamp::option", default)] + pub not_before: Option, /// softDelete data retention days. Value should be >=7 and <=90 when softDelete enabled, otherwise 0. pub recoverable_days: Option, /// Reflects the deletion recovery level currently in effect for keys in the current vault. If it contains 'Purgeable' the key can be permanently deleted by a privileged user; otherwise, only the system can purge the key, at the end of the retention interval. pub recovery_level: Option, /// Last updated time in UTC. - #[serde(rename = "updated", with = "ts_seconds_option", default)] - pub updated_on: Option>, + #[serde( + rename = "updated", + with = "azure_core::date::timestamp::option", + default + )] + pub updated_on: Option, } #[derive(Debug, Serialize, Deserialize)] diff --git a/sdk/security_keyvault/src/lib.rs b/sdk/security_keyvault/src/lib.rs index e33bc2545d1..94cc7985ab8 100644 --- a/sdk/security_keyvault/src/lib.rs +++ b/sdk/security_keyvault/src/lib.rs @@ -14,7 +14,8 @@ pub use clients::*; mod tests { use azure_core::auth::AccessToken; use azure_core::auth::{TokenCredential, TokenResponse}; - use chrono::{Duration, Utc}; + use azure_core::date; + use time::OffsetDateTime; #[macro_export] macro_rules! mock_client { @@ -44,7 +45,7 @@ mod tests { ) -> Result { Ok(TokenResponse::new( AccessToken::new("TOKEN".to_owned()), - Utc::now() + Duration::days(14), + OffsetDateTime::now_utc() + date::duration_from_days(14), )) } } diff --git a/sdk/security_keyvault/src/secrets/models.rs b/sdk/security_keyvault/src/secrets/models.rs index 3872e6cf3d2..e4abb47f65a 100644 --- a/sdk/security_keyvault/src/secrets/models.rs +++ b/sdk/security_keyvault/src/secrets/models.rs @@ -1,14 +1,13 @@ -use chrono::serde::{ts_seconds, ts_seconds_option}; -use chrono::{DateTime, Utc}; use serde::Deserialize; +use time::OffsetDateTime; #[derive(Deserialize, Debug)] pub(crate) struct KeyVaultSecretBaseIdentifierAttributedRaw { pub enabled: bool, - #[serde(with = "ts_seconds")] - pub created: DateTime, - #[serde(with = "ts_seconds")] - pub updated: DateTime, + #[serde(with = "azure_core::date::timestamp")] + pub created: OffsetDateTime, + #[serde(with = "azure_core::date::timestamp")] + pub updated: OffsetDateTime, } #[derive(Deserialize, Debug)] @@ -35,12 +34,12 @@ pub(crate) struct KeyVaultGetSecretResponse { pub(crate) struct KeyVaultGetSecretResponseAttributes { pub enabled: bool, #[serde(default)] - #[serde(with = "ts_seconds_option")] - pub exp: Option>, - #[serde(with = "ts_seconds")] - pub created: DateTime, - #[serde(with = "ts_seconds")] - pub updated: DateTime, + #[serde(with = "azure_core::date::timestamp::option")] + pub exp: Option, + #[serde(with = "azure_core::date::timestamp")] + pub created: OffsetDateTime, + #[serde(with = "azure_core::date::timestamp")] + pub updated: OffsetDateTime, #[serde(rename = "recoveryLevel")] #[allow(unused)] pub recovery_level: String, @@ -56,8 +55,8 @@ pub struct KeyVaultSecretBaseIdentifier { pub id: String, pub name: String, pub enabled: bool, - pub created_on: DateTime, - pub updated_on: DateTime, + pub created_on: OffsetDateTime, + pub updated_on: OffsetDateTime, } #[derive(Debug)] @@ -65,7 +64,7 @@ pub struct KeyVaultSecret { pub id: String, pub value: String, pub enabled: bool, - pub expires_on: Option>, - pub created_on: DateTime, - pub updated_on: DateTime, + pub expires_on: Option, + pub created_on: OffsetDateTime, + pub updated_on: OffsetDateTime, } diff --git a/sdk/security_keyvault/src/secrets/operations/update_secret.rs b/sdk/security_keyvault/src/secrets/operations/update_secret.rs index 12ac17ff639..ca50daffb89 100644 --- a/sdk/security_keyvault/src/secrets/operations/update_secret.rs +++ b/sdk/security_keyvault/src/secrets/operations/update_secret.rs @@ -1,8 +1,8 @@ use crate::prelude::*; use azure_core::error::{ErrorKind, ResultExt}; -use chrono::{serde::ts_seconds_option, DateTime, Utc}; use serde::Serialize; use std::collections::HashMap; +use time::OffsetDateTime; operation! { UpdateSecret, @@ -11,8 +11,8 @@ operation! { ?version: String, ?enabled: bool, ?content_type: String, - ?expiration: DateTime, - ?not_before: DateTime, + ?expiration: OffsetDateTime, + ?not_before: OffsetDateTime, ?recoverable_days: usize, ?tags: HashMap, ?recovery_level: String @@ -22,10 +22,10 @@ operation! { #[serde(rename_all = "camelCase")] struct Attributes { enabled: Option, - #[serde(with = "ts_seconds_option", rename = "exp")] - expiration: Option>, - #[serde(with = "ts_seconds_option", rename = "nbf")] - not_before: Option>, + #[serde(with = "azure_core::date::timestamp::option", rename = "exp")] + expiration: Option, + #[serde(with = "azure_core::date::timestamp::option", rename = "nbf")] + not_before: Option, recovery_level: Option, } diff --git a/sdk/storage/Cargo.toml b/sdk/storage/Cargo.toml index b9509b3ea5e..5bfa143f6cf 100644 --- a/sdk/storage/Cargo.toml +++ b/sdk/storage/Cargo.toml @@ -16,7 +16,7 @@ edition = "2021" async-trait = "0.1" azure_core = { path = "../core", version = "0.3" } base64 = "0.13" -chrono = "0.4" +time = { version = "0.3", features = ["serde-well-known"] } futures = "0.3" log = "0.4" serde = "1.0" diff --git a/sdk/storage/src/core/clients/storage_client.rs b/sdk/storage/src/core/clients/storage_client.rs index c926b669268..fbb9685c0d9 100644 --- a/sdk/storage/src/core/clients/storage_client.rs +++ b/sdk/storage/src/core/clients/storage_client.rs @@ -5,6 +5,7 @@ use crate::shared_access_signature::account_sas::{ }; use crate::ConnectionString; use crate::TimeoutPolicy; +use azure_core::date; use azure_core::{ auth::TokenCredential, error::{Error, ErrorKind, ResultExt}, @@ -12,8 +13,8 @@ use azure_core::{ prelude::Timeout, Body, ClientOptions, Context, Method, Pipeline, Request, Response, }; -use chrono::{DateTime, Utc}; use std::sync::Arc; +use time::OffsetDateTime; use url::Url; /// The well-known account used by Azurite and the legacy Azure Storage Emulator. @@ -371,8 +372,8 @@ impl StorageClient { headers: Headers, request_body: Option, ) -> azure_core::Result { - let dt = chrono::Utc::now(); - let time = format!("{}", dt.format("%a, %d %h %Y %T GMT")); + let dt = OffsetDateTime::now_utc(); + let time = date::to_rfc1123(&dt); let mut request = Request::new(url, method); for (k, v) in headers { @@ -425,7 +426,7 @@ impl StorageClient { &self, resource: AccountSasResource, resource_type: AccountSasResourceType, - expiry: DateTime, + expiry: OffsetDateTime, permissions: AccountSasPermissions, ) -> azure_core::Result { match &self.storage_credentials { diff --git a/sdk/storage/src/core/headers/mod.rs b/sdk/storage/src/core/headers/mod.rs index 0b3048f4753..fdf361b324f 100644 --- a/sdk/storage/src/core/headers/mod.rs +++ b/sdk/storage/src/core/headers/mod.rs @@ -5,15 +5,15 @@ use azure_core::headers::{ server_from_headers, version_from_headers, HeaderName, Headers, CONTENT_MD5, }; use azure_core::RequestId; -use chrono::{DateTime, Utc}; use std::convert::TryFrom; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct CommonStorageResponseHeaders { pub request_id: RequestId, pub client_request_id: Option, pub version: String, - pub date: DateTime, + pub date: OffsetDateTime, pub server: String, } diff --git a/sdk/storage/src/core/shared_access_signature/account_sas.rs b/sdk/storage/src/core/shared_access_signature/account_sas.rs index bb58e908371..9bd6f601340 100644 --- a/sdk/storage/src/core/shared_access_signature/account_sas.rs +++ b/sdk/storage/src/core/shared_access_signature/account_sas.rs @@ -2,8 +2,8 @@ use crate::core::{ hmac::sign, shared_access_signature::{format_date, format_form, SasProtocol, SasToken}, }; -use chrono::{DateTime, Utc}; use std::fmt; +use time::OffsetDateTime; /// Service version of the shared access signature ([Azure documentation](https://docs.microsoft.com/rest/api/storageservices/create-service-sas#specifying-the-signed-version-field)). #[derive(Copy, Clone)] @@ -134,9 +134,9 @@ pub struct AccountSharedAccessSignature { version: AccountSasVersion, resource: AccountSasResource, resource_type: AccountSasResourceType, - expiry: DateTime, + expiry: OffsetDateTime, permissions: AccountSasPermissions, - start: Option>, + start: Option, ip: Option, protocol: Option, } @@ -147,7 +147,7 @@ impl AccountSharedAccessSignature { key: String, resource: AccountSasResource, resource_type: AccountSasResourceType, - expiry: DateTime, + expiry: OffsetDateTime, permissions: AccountSasPermissions, ) -> Self { Self { @@ -166,7 +166,7 @@ impl AccountSharedAccessSignature { setters! { version: AccountSasVersion => version, - start: DateTime => Some(start), + start: OffsetDateTime => Some(start), ip: String => Some(ip), protocol: SasProtocol => Some(protocol), } diff --git a/sdk/storage/src/core/shared_access_signature/mod.rs b/sdk/storage/src/core/shared_access_signature/mod.rs index 6563ba2385e..d33c7dd5c46 100644 --- a/sdk/storage/src/core/shared_access_signature/mod.rs +++ b/sdk/storage/src/core/shared_access_signature/mod.rs @@ -1,5 +1,5 @@ -use chrono::{DateTime, Utc}; use std::fmt; +use time::OffsetDateTime; use url::form_urlencoded; pub mod account_sas; @@ -9,8 +9,8 @@ pub trait SasToken { fn token(&self) -> String; } -pub(crate) fn format_date(d: DateTime) -> String { - d.format("%Y-%m-%dT%H:%M:%SZ").to_string() +pub(crate) fn format_date(d: OffsetDateTime) -> String { + azure_core::date::to_rfc3339(&d) } pub(crate) fn format_form(d: String) -> String { diff --git a/sdk/storage/src/core/shared_access_signature/service_sas.rs b/sdk/storage/src/core/shared_access_signature/service_sas.rs index 86d23768175..0f8676a203b 100644 --- a/sdk/storage/src/core/shared_access_signature/service_sas.rs +++ b/sdk/storage/src/core/shared_access_signature/service_sas.rs @@ -2,8 +2,8 @@ use crate::{ core::shared_access_signature::{format_date, format_form, SasProtocol, SasToken}, hmac, }; -use chrono::{DateTime, Utc}; use std::fmt; +use time::OffsetDateTime; const SERVICE_SAS_VERSION: &str = "2020-06-12"; @@ -95,8 +95,8 @@ pub struct BlobSharedAccessSignature { canonicalized_resource: String, resource: BlobSignedResource, permissions: BlobSasPermissions, // sp - expiry: DateTime, // se - start: Option>, // st + expiry: OffsetDateTime, // se + start: Option, // st identifier: Option, ip: Option, protocol: Option, @@ -107,7 +107,7 @@ impl BlobSharedAccessSignature { key: String, canonicalized_resource: String, permissions: BlobSasPermissions, - expiry: DateTime, + expiry: OffsetDateTime, resource: BlobSignedResource, ) -> Self { Self { @@ -124,7 +124,7 @@ impl BlobSharedAccessSignature { } setters! { - start: DateTime => Some(start), + start: OffsetDateTime => Some(start), identifier: String => Some(identifier), ip: String => Some(ip), protocol: SasProtocol => Some(protocol), diff --git a/sdk/storage/src/core/stored_access_policy.rs b/sdk/storage/src/core/stored_access_policy.rs index f70812f7eeb..7b0016fb259 100644 --- a/sdk/storage/src/core/stored_access_policy.rs +++ b/sdk/storage/src/core/stored_access_policy.rs @@ -1,7 +1,6 @@ -use azure_core::prelude::*; -use chrono::{DateTime, FixedOffset}; - use crate::xml::read_xml; +use azure_core::date; +use time::OffsetDateTime; #[derive(Debug, Clone, Default, PartialEq)] pub struct StoredAccessPolicyList { @@ -33,11 +32,11 @@ impl StoredAccessPolicyList { s.push_str("\n"); s.push_str("\t\t\t"); - s.push_str(&sa.start.format("%Y-%m-%dT%H:%M:%SZ").to_string()); + s.push_str(&date::to_rfc3339(&sa.start)); s.push_str("\n"); s.push_str("\t\t\t"); - s.push_str(&sa.expiry.format("%Y-%m-%dT%H:%M:%SZ").to_string()); + s.push_str(&date::to_rfc3339(&sa.expiry)); s.push_str("\n"); s.push_str("\t\t\t"); @@ -72,18 +71,13 @@ impl From for StoredAccessPolicyList { #[derive(Debug, Clone, PartialEq)] pub struct StoredAccessPolicy { pub id: String, - pub start: DateTime, - pub expiry: DateTime, + pub start: OffsetDateTime, + pub expiry: OffsetDateTime, pub permission: String, } impl StoredAccessPolicy { - pub fn new( - id: A, - start: DateTime, - expiry: DateTime, - permission: B, - ) -> Self + pub fn new(id: A, start: OffsetDateTime, expiry: OffsetDateTime, permission: B) -> Self where A: Into, B: Into, @@ -113,10 +107,10 @@ struct SignedIdentifier { #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] struct AccessPolicy { - #[serde(deserialize_with = "deserialize_date_from_rfc3339")] - start: DateTime, - #[serde(deserialize_with = "deserialize_date_from_rfc3339")] - expiry: DateTime, + #[serde(with = "azure_core::date::rfc3339")] + start: OffsetDateTime, + #[serde(with = "azure_core::date::rfc3339")] + expiry: OffsetDateTime, permission: String, } diff --git a/sdk/storage_blobs/Cargo.toml b/sdk/storage_blobs/Cargo.toml index f160aef610a..fe712359ed5 100644 --- a/sdk/storage_blobs/Cargo.toml +++ b/sdk/storage_blobs/Cargo.toml @@ -17,7 +17,7 @@ azure_core = { path = "../core", version = "0.3" } azure_storage = { path = "../storage", version = "0.4", default-features = false } base64 = "0.13" bytes = "1.0" -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde"] } futures = "0.3" log = "0.4" md5 = "0.7" diff --git a/sdk/storage_blobs/examples/container_01.rs b/sdk/storage_blobs/examples/container_01.rs index aa757d9160d..2b0d0b48a78 100644 --- a/sdk/storage_blobs/examples/container_01.rs +++ b/sdk/storage_blobs/examples/container_01.rs @@ -1,8 +1,8 @@ -use azure_core::prelude::*; +use azure_core::{date, prelude::*}; use azure_storage::core::prelude::*; use azure_storage_blobs::prelude::*; -use chrono::{FixedOffset, Utc}; -use std::{ops::Add, time::Duration}; +use std::time::Duration; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { @@ -38,9 +38,9 @@ async fn main() -> azure_core::Result<()> { let result = container_client.get_acl().into_future().await?; println!("\nget_acl() == {:?}", result); - // set stored acess policy list - let dt_start = Utc::now().with_timezone(&FixedOffset::east(0)); - let dt_end = dt_start.add(chrono::Duration::days(7)); + // set stored access policy list + let dt_start = OffsetDateTime::now_utc(); + let dt_end = dt_start + date::duration_from_days(7); let mut sapl = StoredAccessPolicyList::default(); sapl.stored_access diff --git a/sdk/storage_blobs/examples/copy_blob.rs b/sdk/storage_blobs/examples/copy_blob.rs index b03051dc0ad..36233c5ce7f 100644 --- a/sdk/storage_blobs/examples/copy_blob.rs +++ b/sdk/storage_blobs/examples/copy_blob.rs @@ -1,6 +1,7 @@ +use azure_core::date; use azure_storage::core::prelude::*; use azure_storage_blobs::prelude::*; -use chrono::{Duration, Utc}; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { @@ -40,8 +41,8 @@ async fn main() -> azure_core::Result<()> { // let's get a SAS key for the source let sas_url = { - let now = Utc::now(); - let later = now + Duration::hours(1); + let now = OffsetDateTime::now_utc(); + let later = now + date::duration_from_hours(1); let sas = source_storage_client .shared_access_signature( AccountSasResource::Blob, diff --git a/sdk/storage_blobs/examples/list_blobs_00.rs b/sdk/storage_blobs/examples/list_blobs_00.rs index 95c3442e8bd..85dd95929ab 100644 --- a/sdk/storage_blobs/examples/list_blobs_00.rs +++ b/sdk/storage_blobs/examples/list_blobs_00.rs @@ -2,7 +2,8 @@ use azure_core::{prelude::Timeout, Context}; use azure_storage::core::prelude::*; use azure_storage_blobs::prelude::*; use futures::StreamExt; -use std::{num::NonZeroU32, time::Duration}; +use std::num::NonZeroU32; +use std::time::Duration; #[tokio::main] async fn main() -> azure_core::Result<()> { diff --git a/sdk/storage_blobs/examples/sas00.rs_toreenable b/sdk/storage_blobs/examples/sas00.rs_toreenable index 74be9ee5ddd..833ebbe5d4e 100644 --- a/sdk/storage_blobs/examples/sas00.rs_toreenable +++ b/sdk/storage_blobs/examples/sas00.rs_toreenable @@ -6,8 +6,8 @@ pub fn main() { let access_key = std::env::var("STORAGE_ACCESS_KEY").expect("Set env variable STORAGE_ACCESS_KEY first!"); - let start = Utc::now() - Duration::days(1); - let end = Utc::now() + Duration::days(1); + let start = OffsetDateTime::now_utc() - date::duration_from_days(1); + let end = OffsetDateTime::now_utc() + date::duration_from_days(1); let path = Url::parse("https://azureskdforrust.blob.core.windows.net/test/ERRORLOG.1.cut").unwrap(); diff --git a/sdk/storage_blobs/examples/shared_access_signature.rs b/sdk/storage_blobs/examples/shared_access_signature.rs index 00ee9d2e380..78aa10ff33d 100644 --- a/sdk/storage_blobs/examples/shared_access_signature.rs +++ b/sdk/storage_blobs/examples/shared_access_signature.rs @@ -1,6 +1,7 @@ +use azure_core::date; use azure_storage::core::prelude::*; use azure_storage_blobs::prelude::*; -use chrono::{Duration, Utc}; +use time::OffsetDateTime; fn main() { env_logger::init(); @@ -22,8 +23,8 @@ fn code() -> azure_core::Result<()> { .expect("please specify blob name as command line parameter"); // allow for some time skew - let now = Utc::now() - Duration::minutes(15); - let later = now + Duration::hours(1); + let now = OffsetDateTime::now_utc() - date::duration_from_minutes(15); + let later = now + date::duration_from_hours(1); let storage_client = StorageClient::new_access_key(&account, &access_key); let container_client = storage_client.container_client(&container_name); diff --git a/sdk/storage_blobs/src/blob/mod.rs b/sdk/storage_blobs/src/blob/mod.rs index e7aa64f628d..d193356815f 100644 --- a/sdk/storage_blobs/src/blob/mod.rs +++ b/sdk/storage_blobs/src/blob/mod.rs @@ -19,23 +19,20 @@ pub use page_range_list::PageRangeList; use crate::options::{AccessTier, Tags}; use azure_core::{ - content_type, - error::{ErrorKind, ResultExt}, + content_type, date, headers::{self, Headers}, parsing::from_azure_time, Etag, LeaseDuration, LeaseState, LeaseStatus, }; use azure_storage::{ConsistencyCRC64, ConsistencyMD5, CopyId, CopyProgress}; -use chrono::{DateTime, Utc}; use std::collections::HashMap; +use time::OffsetDateTime; #[cfg(feature = "azurite_workaround")] -fn get_creation_time(h: &Headers) -> azure_core::Result>> { +fn get_creation_time(h: &Headers) -> azure_core::Result> { if let Some(creation_time) = h.get_optional_str(&headers::CREATION_TIME) { // Check that the creation time is valid - let creation_time = - DateTime::parse_from_rfc2822(creation_time).map_kind(ErrorKind::DataConversion)?; - let creation_time = DateTime::from_utc(creation_time.naive_utc(), Utc); + let creation_time = date::parse_rfc1123(creation_time).unwrap_or(OffsetDateTime::now_utc()); Ok(Some(creation_time)) } else { // Not having a creation time is ok @@ -91,7 +88,7 @@ where #[serde(rename_all = "PascalCase")] pub struct Blob { pub name: String, - pub snapshot: Option>, + pub snapshot: Option, pub version_id: Option, pub is_current_version: Option, pub deleted: Option, @@ -105,18 +102,18 @@ pub struct Blob { pub struct BlobProperties { #[cfg(not(feature = "azurite_workaround"))] #[serde(rename = "Creation-Time")] - #[serde(with = "azure_core::parsing::rfc2822_time_format")] - pub creation_time: DateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub creation_time: OffsetDateTime, #[cfg(feature = "azurite_workaround")] #[serde(rename = "Creation-Time")] - #[serde(with = "azure_core::parsing::rfc2822_time_format_optional")] - pub creation_time: Option>, + #[serde(with = "azure_core::date::rfc1123::option")] + pub creation_time: Option, #[serde(rename = "Last-Modified")] - #[serde(with = "azure_core::parsing::rfc2822_time_format")] - pub last_modified: DateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub last_modified: OffsetDateTime, #[serde(default)] - #[serde(with = "azure_core::parsing::rfc2822_time_format_optional")] - pub last_access_time: Option>, + #[serde(with = "azure_core::date::rfc1123::option")] + pub last_access_time: Option, pub etag: Etag, #[serde(rename = "Content-Length")] pub content_length: u64, @@ -143,8 +140,8 @@ pub struct BlobProperties { pub blob_type: BlobType, pub access_tier: Option, #[serde(default)] - #[serde(with = "azure_core::parsing::rfc2822_time_format_optional")] - pub access_tier_change_time: Option>, + #[serde(with = "azure_core::date::rfc1123::option")] + pub access_tier_change_time: Option, pub lease_status: LeaseStatus, pub lease_state: LeaseState, pub lease_duration: Option, @@ -153,8 +150,8 @@ pub struct BlobProperties { pub copy_source: Option, pub copy_progress: Option, #[serde(default)] - #[serde(with = "azure_core::parsing::rfc2822_time_format_optional")] - pub copy_completion_time: Option>, + #[serde(with = "azure_core::date::rfc1123::option")] + pub copy_completion_time: Option, pub copy_status_description: Option, pub server_encrypted: bool, pub customer_provided_key_sha256: Option, @@ -162,15 +159,15 @@ pub struct BlobProperties { pub incremental_copy: Option, pub access_tier_inferred: Option, #[serde(default)] - #[serde(with = "azure_core::parsing::rfc2822_time_format_optional")] - pub deleted_time: Option>, + #[serde(with = "azure_core::date::rfc1123::option")] + pub deleted_time: Option, pub remaining_retention_days: Option, pub tag_count: Option, pub rehydrate_priority: Option, #[serde(default)] #[serde(rename = "Expiry-Time")] - #[serde(with = "azure_core::parsing::rfc2822_time_format_optional")] - pub expiry_time: Option>, + #[serde(with = "azure_core::date::rfc1123::option")] + pub expiry_time: Option, #[serde(flatten)] extra: HashMap, // For debug purposes, should be compiled out in the future } @@ -183,9 +180,7 @@ impl Blob { #[cfg(not(feature = "azurite_workaround"))] let creation_time = { let creation_time = h.get_str(&headers::CREATION_TIME)?; - let creation_time = - DateTime::parse_from_rfc2822(creation_time).map_kind(ErrorKind::DataConversion)?; - DateTime::from_utc(creation_time.naive_utc(), Utc) + date::parse_rfc1123(creation_time)? }; #[cfg(feature = "azurite_workaround")] let creation_time = get_creation_time(h)?; @@ -214,14 +209,9 @@ impl Blob { let copy_status = h.get_optional_as(&headers::COPY_STATUS)?; let copy_source = h.get_optional_string(&headers::COPY_SOURCE); let copy_progress = h.get_optional_as(&headers::COPY_PROGRESS)?; - let copy_completion_time: Option> = h + let copy_completion_time: Option = h .get_optional_str(&headers::COPY_COMPLETION_TIME) - .and_then(|cct| { - Some(DateTime::from_utc( - DateTime::parse_from_rfc2822(cct).ok()?.naive_utc(), - Utc, - )) - }); + .and_then(|cct| date::parse_rfc1123(cct).ok()); let copy_status_description = h.get_optional_string(&headers::COPY_STATUS_DESCRIPTION); let server_encrypted = h.get_as(&headers::SERVER_ENCRYPTED)?; diff --git a/sdk/storage_blobs/src/blob/operations/acquire_lease.rs b/sdk/storage_blobs/src/blob/operations/acquire_lease.rs index 890889baa73..7c075ba55f7 100644 --- a/sdk/storage_blobs/src/blob/operations/acquire_lease.rs +++ b/sdk/storage_blobs/src/blob/operations/acquire_lease.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { AcquireLease, @@ -36,8 +36,8 @@ impl AcquireLeaseBuilder { azure_storage::response_from_headers!(AcquireLeaseResponse, etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, lease_id_from_headers => lease_id: LeaseId, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/blob/operations/break_lease.rs b/sdk/storage_blobs/src/blob/operations/break_lease.rs index 0624d6c13b5..d561cc84891 100644 --- a/sdk/storage_blobs/src/blob/operations/break_lease.rs +++ b/sdk/storage_blobs/src/blob/operations/break_lease.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { BreakLease, @@ -34,8 +34,8 @@ impl BreakLeaseBuilder { azure_storage::response_from_headers!(BreakLeaseResponse, etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, lease_time_from_headers => lease_time: u8, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/blob/operations/change_lease.rs b/sdk/storage_blobs/src/blob/operations/change_lease.rs index 2f50461fea0..47b99d9ea3f 100644 --- a/sdk/storage_blobs/src/blob/operations/change_lease.rs +++ b/sdk/storage_blobs/src/blob/operations/change_lease.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { ChangeLease, @@ -33,8 +33,8 @@ impl ChangeLeaseBuilder { azure_storage::response_from_headers!(ChangeLeaseResponse , etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, lease_id_from_headers => lease_id: LeaseId, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/blob/operations/clear_page.rs b/sdk/storage_blobs/src/blob/operations/clear_page.rs index 6ea2da4377c..d1e3e68c797 100644 --- a/sdk/storage_blobs/src/blob/operations/clear_page.rs +++ b/sdk/storage_blobs/src/blob/operations/clear_page.rs @@ -4,7 +4,7 @@ use azure_core::{ prelude::*, RequestId, }; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { ClearPage, @@ -45,8 +45,8 @@ impl ClearPageBuilder { azure_storage::response_from_headers!(ClearPageResponse, etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, sequence_number_from_headers => sequence_number: u64, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/blob/operations/copy_blob.rs b/sdk/storage_blobs/src/blob/operations/copy_blob.rs index f4f5435b101..e13c1a42eae 100644 --- a/sdk/storage_blobs/src/blob/operations/copy_blob.rs +++ b/sdk/storage_blobs/src/blob/operations/copy_blob.rs @@ -4,8 +4,8 @@ use crate::{ }; use azure_core::{headers::*, prelude::*, RequestId}; use azure_storage::core::{copy_id_from_headers, CopyId}; -use chrono::{DateTime, Utc}; use std::convert::{TryFrom, TryInto}; +use time::OffsetDateTime; use url::Url; operation! { @@ -64,11 +64,11 @@ impl CopyBlobBuilder { #[derive(Debug, Clone, PartialEq)] pub struct CopyBlobResponse { pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub request_id: RequestId, pub version: String, pub server: String, - pub date: DateTime, + pub date: OffsetDateTime, pub copy_id: CopyId, pub copy_status: CopyStatus, } diff --git a/sdk/storage_blobs/src/blob/operations/copy_blob_from_url.rs b/sdk/storage_blobs/src/blob/operations/copy_blob_from_url.rs index 422f0ecfd0c..1c52138ac73 100644 --- a/sdk/storage_blobs/src/blob/operations/copy_blob_from_url.rs +++ b/sdk/storage_blobs/src/blob/operations/copy_blob_from_url.rs @@ -8,8 +8,8 @@ use azure_storage::{ headers::content_md5_from_headers_optional, ConsistencyMD5, }; -use chrono::{DateTime, Utc}; use std::convert::{TryFrom, TryInto}; +use time::OffsetDateTime; use url::Url; operation! { @@ -63,14 +63,14 @@ impl CopyBlobFromUrlBuilder { #[derive(Debug, Clone, PartialEq)] pub struct CopyBlobFromUrlResponse { pub content_md5: Option, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub etag: String, pub server: String, pub request_id: RequestId, pub version: String, pub copy_id: CopyId, pub copy_status: CopyStatus, - pub date: DateTime, + pub date: OffsetDateTime, } impl TryFrom<&Headers> for CopyBlobFromUrlResponse { diff --git a/sdk/storage_blobs/src/blob/operations/delete_blob.rs b/sdk/storage_blobs/src/blob/operations/delete_blob.rs index a07a7f84834..d4807947bd1 100644 --- a/sdk/storage_blobs/src/blob/operations/delete_blob.rs +++ b/sdk/storage_blobs/src/blob/operations/delete_blob.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { DeleteBlob, @@ -41,12 +41,12 @@ impl DeleteBlobBuilder { azure_storage::response_from_headers!(DeleteBlobResponse , delete_type_permanent_from_headers => delete_type_permanent: bool, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); #[cfg(feature = "azurite_workaround")] azure_storage::response_from_headers!(DeleteBlobResponse , delete_type_permanent_from_headers => delete_type_permanent: Option, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/blob/operations/get_blob.rs b/sdk/storage_blobs/src/blob/operations/get_blob.rs index 7a59875ee77..b0d59be0e43 100644 --- a/sdk/storage_blobs/src/blob/operations/get_blob.rs +++ b/sdk/storage_blobs/src/blob/operations/get_blob.rs @@ -4,7 +4,7 @@ use azure_core::{ Response as AzureResponse, }; use bytes::Bytes; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; const DEFAULT_CHUNK_SIZE: u64 = 0x1000 * 0x1000; @@ -66,7 +66,7 @@ pub struct GetBlobResponse { pub request_id: RequestId, pub blob: Blob, pub data: Bytes, - pub date: DateTime, + pub date: OffsetDateTime, pub remaining_range: Option, } diff --git a/sdk/storage_blobs/src/blob/operations/get_block_list.rs b/sdk/storage_blobs/src/blob/operations/get_block_list.rs index 184e26f35c0..f8f187a326b 100644 --- a/sdk/storage_blobs/src/blob/operations/get_block_list.rs +++ b/sdk/storage_blobs/src/blob/operations/get_block_list.rs @@ -3,8 +3,8 @@ use crate::{ prelude::*, }; use azure_core::{collect_pinned_stream, headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; use std::str::from_utf8; +use time::OffsetDateTime; operation! { GetBlockList, @@ -48,9 +48,9 @@ impl GetBlockListBuilder { #[derive(Debug, Clone, PartialEq)] pub struct GetBlockListResponse { pub etag: Option, - pub last_modified: Option>, + pub last_modified: Option, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub block_with_size_list: BlockWithSizeList, } diff --git a/sdk/storage_blobs/src/blob/operations/get_metadata.rs b/sdk/storage_blobs/src/blob/operations/get_metadata.rs index eb292b3be8f..ad7d63930bd 100644 --- a/sdk/storage_blobs/src/blob/operations/get_metadata.rs +++ b/sdk/storage_blobs/src/blob/operations/get_metadata.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, Method, RequestId}; -use chrono::{DateTime, Utc}; use std::convert::{TryFrom, TryInto}; +use time::OffsetDateTime; operation! { GetMetadata, @@ -43,7 +43,7 @@ pub struct GetMetadataResponse { pub request_id: RequestId, pub etag: String, pub server: String, - pub date: DateTime, + pub date: OffsetDateTime, pub metadata: Metadata, } diff --git a/sdk/storage_blobs/src/blob/operations/get_page_ranges.rs b/sdk/storage_blobs/src/blob/operations/get_page_ranges.rs index f4a87354c96..d7a0b2d80e8 100644 --- a/sdk/storage_blobs/src/blob/operations/get_page_ranges.rs +++ b/sdk/storage_blobs/src/blob/operations/get_page_ranges.rs @@ -1,7 +1,7 @@ use crate::{blob::PageRangeList, prelude::*}; use azure_core::{collect_pinned_stream, headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; use std::str::from_utf8; +use time::OffsetDateTime; operation! { GetPageRanges, @@ -44,9 +44,9 @@ impl GetPageRangesBuilder { #[derive(Debug, Clone, PartialEq)] pub struct GetPageRangesResponse { pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub page_list: PageRangeList, } diff --git a/sdk/storage_blobs/src/blob/operations/get_properties.rs b/sdk/storage_blobs/src/blob/operations/get_properties.rs index 6da22abd61b..9edd3ae1833 100644 --- a/sdk/storage_blobs/src/blob/operations/get_properties.rs +++ b/sdk/storage_blobs/src/blob/operations/get_properties.rs @@ -1,6 +1,6 @@ use crate::{blob::Blob, prelude::*}; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { GetProperties, @@ -42,7 +42,7 @@ impl GetPropertiesBuilder { pub struct GetPropertiesResponse { pub blob: Blob, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, } impl GetPropertiesResponse { diff --git a/sdk/storage_blobs/src/blob/operations/get_tags.rs b/sdk/storage_blobs/src/blob/operations/get_tags.rs index 06c75071ce1..ec45e96206f 100644 --- a/sdk/storage_blobs/src/blob/operations/get_tags.rs +++ b/sdk/storage_blobs/src/blob/operations/get_tags.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::{collect_pinned_stream, headers::*, prelude::*, RequestId}; use azure_storage::xml::read_xml; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { GetTags, @@ -41,7 +41,7 @@ impl GetTagsBuilder { #[derive(Debug, Clone)] pub struct GetTagsResponse { pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub tags: Tags, } diff --git a/sdk/storage_blobs/src/blob/operations/put_append_blob.rs b/sdk/storage_blobs/src/blob/operations/put_append_blob.rs index 60af0196d74..9b3445d8989 100644 --- a/sdk/storage_blobs/src/blob/operations/put_append_blob.rs +++ b/sdk/storage_blobs/src/blob/operations/put_append_blob.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { PutAppendBlob, @@ -48,9 +48,9 @@ type PutAppendBlobResponse = PutBlobResponse; #[derive(Debug, Clone)] pub struct PutBlobResponse { pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub request_server_encrypted: bool, } diff --git a/sdk/storage_blobs/src/blob/operations/put_block.rs b/sdk/storage_blobs/src/blob/operations/put_block.rs index f59814ea74a..52d3f25086a 100644 --- a/sdk/storage_blobs/src/blob/operations/put_block.rs +++ b/sdk/storage_blobs/src/blob/operations/put_block.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, Body, RequestId}; use azure_storage::{headers::consistency_from_headers, ConsistencyCRC64, ConsistencyMD5}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { PutBlock, @@ -41,7 +41,7 @@ pub struct PutBlockResponse { pub content_md5: Option, pub content_crc64: Option, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub request_server_encrypted: bool, } diff --git a/sdk/storage_blobs/src/blob/operations/put_block_blob.rs b/sdk/storage_blobs/src/blob/operations/put_block_blob.rs index 34826f9373c..bbf2218daa2 100644 --- a/sdk/storage_blobs/src/blob/operations/put_block_blob.rs +++ b/sdk/storage_blobs/src/blob/operations/put_block_blob.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, Body, RequestId}; use azure_storage::{headers::consistency_from_headers, ConsistencyCRC64, ConsistencyMD5}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { PutBlockBlob, @@ -55,11 +55,11 @@ impl PutBlockBlobBuilder { #[derive(Debug, Clone)] pub struct PutBlockBlobResponse { pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub content_md5: Option, pub content_crc64: Option, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub request_server_encrypted: bool, } diff --git a/sdk/storage_blobs/src/blob/operations/put_block_list.rs b/sdk/storage_blobs/src/blob/operations/put_block_list.rs index 29ecd07a8ca..29ea6156d06 100644 --- a/sdk/storage_blobs/src/blob/operations/put_block_list.rs +++ b/sdk/storage_blobs/src/blob/operations/put_block_list.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, RequestId}; use azure_storage::{headers::content_md5_from_headers, ConsistencyMD5}; use bytes::Bytes; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { PutBlockList, @@ -68,10 +68,10 @@ impl PutBlockListBuilder { #[derive(Debug, Clone, PartialEq)] pub struct PutBlockListResponse { pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub content_md5: ConsistencyMD5, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub request_server_encrypted: bool, } diff --git a/sdk/storage_blobs/src/blob/operations/put_page.rs b/sdk/storage_blobs/src/blob/operations/put_page.rs index 24809efc19b..b3b9522caa6 100644 --- a/sdk/storage_blobs/src/blob/operations/put_page.rs +++ b/sdk/storage_blobs/src/blob/operations/put_page.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, Body, RequestId}; use azure_storage::{headers::content_md5_from_headers, ConsistencyMD5}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { PutPage, @@ -50,11 +50,11 @@ impl PutPageBuilder { #[derive(Debug, Clone, PartialEq)] pub struct PutPageResponse { pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub content_md5: ConsistencyMD5, pub sequence_number: u64, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub request_server_encrypted: bool, } diff --git a/sdk/storage_blobs/src/blob/operations/release_lease.rs b/sdk/storage_blobs/src/blob/operations/release_lease.rs index 260faf6f52a..87dc4f8da64 100644 --- a/sdk/storage_blobs/src/blob/operations/release_lease.rs +++ b/sdk/storage_blobs/src/blob/operations/release_lease.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use azure_core::{headers::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { ReleaseLease, @@ -31,7 +31,7 @@ impl ReleaseLeaseBuilder { azure_storage::response_from_headers!(ReleaseLeaseResponse , etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/blob/operations/renew_lease.rs b/sdk/storage_blobs/src/blob/operations/renew_lease.rs index 0f79709dbac..c434753ead4 100644 --- a/sdk/storage_blobs/src/blob/operations/renew_lease.rs +++ b/sdk/storage_blobs/src/blob/operations/renew_lease.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { RenewLease, @@ -31,8 +31,8 @@ impl RenewLeaseBuilder { azure_storage::response_from_headers!(RenewLeaseResponse, etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, lease_id_from_headers => lease_id: LeaseId, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/blob/operations/set_metadata.rs b/sdk/storage_blobs/src/blob/operations/set_metadata.rs index c19bb01c35a..fd6b7484750 100644 --- a/sdk/storage_blobs/src/blob/operations/set_metadata.rs +++ b/sdk/storage_blobs/src/blob/operations/set_metadata.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::{headers::*, prelude::*, Method, RequestId}; -use chrono::{DateTime, Utc}; use std::convert::{TryFrom, TryInto}; +use time::OffsetDateTime; operation! { SetMetadata, @@ -46,7 +46,7 @@ pub struct SetMetadataResponse { pub request_id: RequestId, pub etag: String, pub server: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl TryFrom<&Headers> for SetMetadataResponse { diff --git a/sdk/storage_blobs/src/blob/operations/set_properties.rs b/sdk/storage_blobs/src/blob/operations/set_properties.rs index 606fd3b7863..f33e1bddb7f 100644 --- a/sdk/storage_blobs/src/blob/operations/set_properties.rs +++ b/sdk/storage_blobs/src/blob/operations/set_properties.rs @@ -6,8 +6,8 @@ use azure_core::{ }, Method, RequestId, }; -use chrono::{DateTime, Utc}; use std::convert::{TryFrom, TryInto}; +use time::OffsetDateTime; operation! { SetProperties, @@ -82,7 +82,7 @@ pub struct SetPropertiesResponse { pub request_id: RequestId, pub etag: String, pub server: String, - pub date: DateTime, + pub date: OffsetDateTime, } impl TryFrom<&Headers> for SetPropertiesResponse { diff --git a/sdk/storage_blobs/src/blob/operations/set_tags.rs b/sdk/storage_blobs/src/blob/operations/set_tags.rs index e6fa4ff69ec..b1d94612b9f 100644 --- a/sdk/storage_blobs/src/blob/operations/set_tags.rs +++ b/sdk/storage_blobs/src/blob/operations/set_tags.rs @@ -4,8 +4,8 @@ use azure_core::{ headers::{date_from_headers, request_id_from_headers, Headers}, Method, RequestId, }; -use chrono::{DateTime, Utc}; use std::convert::{TryFrom, TryInto}; +use time::OffsetDateTime; operation! { SetTags, @@ -40,7 +40,7 @@ impl SetTagsBuilder { #[derive(Debug, Clone)] pub struct SetTagsResponse { pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, } impl TryFrom<&Headers> for SetTagsResponse { diff --git a/sdk/storage_blobs/src/clients/blob_client.rs b/sdk/storage_blobs/src/clients/blob_client.rs index 27ef430854d..9a8ed29f59d 100644 --- a/sdk/storage_blobs/src/clients/blob_client.rs +++ b/sdk/storage_blobs/src/clients/blob_client.rs @@ -17,8 +17,8 @@ use azure_storage::core::{ SasToken, }, }; -use chrono::{DateTime, Utc}; use futures::StreamExt; +use time::OffsetDateTime; use url::Url; /// A client for handling blobs @@ -88,7 +88,7 @@ impl BlobClient { SetBlobTierBuilder::new(self.clone(), access_tier) } - /// Set an expiry time on an existing blob. + /// Set an expiry time on an existing blob. /// /// This operation is only allowed on Hierarchical Namespace enabled /// accounts. @@ -208,7 +208,7 @@ impl BlobClient { pub fn shared_access_signature( &self, permissions: BlobSasPermissions, - expiry: DateTime, + expiry: OffsetDateTime, ) -> azure_core::Result { let canonicalized_resource = format!( "/blob/{}/{}/{}", diff --git a/sdk/storage_blobs/src/clients/container_client.rs b/sdk/storage_blobs/src/clients/container_client.rs index c68ef26d14e..50967facacd 100644 --- a/sdk/storage_blobs/src/clients/container_client.rs +++ b/sdk/storage_blobs/src/clients/container_client.rs @@ -13,7 +13,7 @@ use azure_storage::{ SasToken, }, }; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; pub trait AsContainerClient { fn container_client(&self, container_name: impl Into) -> ContainerClient; @@ -93,7 +93,7 @@ impl ContainerClient { pub fn shared_access_signature( &self, permissions: BlobSasPermissions, - expiry: DateTime, + expiry: OffsetDateTime, ) -> azure_core::Result { let canonicalized_resource = format!( "/blob/{}/{}", diff --git a/sdk/storage_blobs/src/container/mod.rs b/sdk/storage_blobs/src/container/mod.rs index d59c09a5ddb..10dec6e4b8c 100644 --- a/sdk/storage_blobs/src/container/mod.rs +++ b/sdk/storage_blobs/src/container/mod.rs @@ -1,4 +1,5 @@ use azure_core::{ + date, error::{Error, ErrorKind, ResultExt}, headers::{self, AsHeaders, Headers}, }; @@ -12,8 +13,8 @@ use azure_core::{ LeaseDuration, LeaseState, LeaseStatus, }; use azure_storage::parsing_xml::{cast_must, cast_optional, traverse}; -use chrono::{DateTime, Utc}; use std::collections::HashMap; +use time::OffsetDateTime; use xml::{Element, Xml}; create_enum!( @@ -45,7 +46,7 @@ pub(crate) fn public_access_from_header(header_map: &Headers) -> azure_core::Res #[derive(Debug, Clone)] pub struct Container { pub name: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub e_tag: String, pub lease_status: LeaseStatus, pub lease_state: LeaseState, @@ -66,7 +67,7 @@ impl Container { pub fn new(name: &str) -> Container { Container { name: name.to_owned(), - last_modified: Utc::now(), + last_modified: OffsetDateTime::now_utc(), e_tag: "".to_owned(), lease_status: LeaseStatus::Unlocked, lease_state: LeaseState::Available, @@ -86,9 +87,7 @@ impl Container { NAME: Into, { let last_modified = headers.get_str(&headers::LAST_MODIFIED)?; - let last_modified = - DateTime::parse_from_rfc2822(last_modified).map_kind(ErrorKind::DataConversion)?; - let last_modified = DateTime::from_utc(last_modified.naive_utc(), Utc); + let last_modified = date::parse_rfc1123(last_modified)?; let e_tag = headers.get_as(&headers::ETAG)?; diff --git a/sdk/storage_blobs/src/container/operations/acquire_lease.rs b/sdk/storage_blobs/src/container/operations/acquire_lease.rs index f305fa32f0c..1ec38827fbb 100644 --- a/sdk/storage_blobs/src/container/operations/acquire_lease.rs +++ b/sdk/storage_blobs/src/container/operations/acquire_lease.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::Method; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { AcquireLease, @@ -40,8 +40,8 @@ impl AcquireLeaseBuilder { azure_storage::response_from_headers!(AcquireLeaseResponse , etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, lease_id_from_headers => lease_id: LeaseId, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/container/operations/break_lease.rs b/sdk/storage_blobs/src/container/operations/break_lease.rs index a90698e0b28..8decc7de1f7 100644 --- a/sdk/storage_blobs/src/container/operations/break_lease.rs +++ b/sdk/storage_blobs/src/container/operations/break_lease.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::Method; use azure_core::{headers::*, prelude::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { BreakLease, @@ -36,8 +36,8 @@ impl BreakLeaseBuilder { azure_storage::response_from_headers!(BreakLeaseResponse, etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, lease_time_from_headers => lease_time: u8, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/container/operations/get_acl.rs b/sdk/storage_blobs/src/container/operations/get_acl.rs index 24ff41c75a8..39e7dd8a87d 100644 --- a/sdk/storage_blobs/src/container/operations/get_acl.rs +++ b/sdk/storage_blobs/src/container/operations/get_acl.rs @@ -3,14 +3,10 @@ use crate::{ prelude::*, }; use azure_core::{ - collect_pinned_stream, - error::{ErrorKind, ResultExt}, - headers::*, - prelude::*, - Method, RequestId, Response, + collect_pinned_stream, date, headers::*, prelude::*, Method, RequestId, Response, }; use azure_storage::core::StoredAccessPolicyList; -use chrono::{DateTime, FixedOffset}; +use time::OffsetDateTime; operation! { GetACL, @@ -40,9 +36,9 @@ impl GetACLBuilder { pub struct GetACLResponse { pub public_access: PublicAccess, pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, pub stored_access_policy_list: StoredAccessPolicyList, } @@ -58,13 +54,12 @@ impl GetACLResponse { let etag = headers.get_as(&ETAG)?; let last_modified = headers.get_str(&LAST_MODIFIED)?; - let last_modified = - DateTime::parse_from_rfc2822(last_modified).map_kind(ErrorKind::DataConversion)?; + let last_modified = date::parse_rfc1123(last_modified)?; let request_id = headers.get_as(&REQUEST_ID)?; let date = headers.get_str(&DATE)?; - let date = DateTime::parse_from_rfc2822(date).map_kind(ErrorKind::DataConversion)?; + let date = date::parse_rfc1123(date)?; let stored_access_policy_list = StoredAccessPolicyList::from_xml(&body)?; diff --git a/sdk/storage_blobs/src/container/operations/get_properties.rs b/sdk/storage_blobs/src/container/operations/get_properties.rs index 6bf4834b2e7..58252cf53ca 100644 --- a/sdk/storage_blobs/src/container/operations/get_properties.rs +++ b/sdk/storage_blobs/src/container/operations/get_properties.rs @@ -1,13 +1,12 @@ use crate::{container::Container, prelude::*}; -use azure_core::Method; +use azure_core::{date, Method}; use azure_core::{ - error::{ErrorKind, ResultExt}, headers::{self, Headers}, prelude::*, RequestId, }; -use chrono::{DateTime, FixedOffset}; use std::convert::{TryFrom, TryInto}; +use time::OffsetDateTime; operation! { GetProperties, @@ -40,7 +39,7 @@ impl GetPropertiesBuilder { pub struct GetPropertiesResponse { pub container: Container, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, } impl TryFrom<(&str, &Headers)> for GetPropertiesResponse { @@ -58,8 +57,7 @@ impl GetPropertiesResponse { ) -> azure_core::Result { let request_id = headers.get_as(&headers::REQUEST_ID)?; - let date = DateTime::parse_from_rfc2822(headers.get_str(&headers::DATE)?) - .map_kind(ErrorKind::DataConversion)?; + let date = date::parse_rfc1123(headers.get_str(&headers::DATE)?)?; let container = Container::from_response(container_name, headers)?; diff --git a/sdk/storage_blobs/src/container/operations/list_blobs.rs b/sdk/storage_blobs/src/container/operations/list_blobs.rs index b17f427fc11..c207c65d02b 100644 --- a/sdk/storage_blobs/src/container/operations/list_blobs.rs +++ b/sdk/storage_blobs/src/container/operations/list_blobs.rs @@ -8,7 +8,7 @@ use azure_core::{ Pageable, RequestId, Response as AzureResponse, }; use azure_storage::xml::read_xml; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { #[stream] @@ -97,7 +97,7 @@ pub struct ListBlobsResponse { pub next_marker: Option, pub blobs: Blobs, pub request_id: RequestId, - pub date: DateTime, + pub date: OffsetDateTime, } #[derive(Debug, Clone, PartialEq, Deserialize)] diff --git a/sdk/storage_blobs/src/container/operations/release_lease.rs b/sdk/storage_blobs/src/container/operations/release_lease.rs index bae407211ba..59ed247f38e 100644 --- a/sdk/storage_blobs/src/container/operations/release_lease.rs +++ b/sdk/storage_blobs/src/container/operations/release_lease.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use azure_core::Method; use azure_core::{headers::*, RequestId}; -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; operation! { ReleaseLease, @@ -33,7 +33,7 @@ impl ReleaseLeaseBuilder { azure_storage::response_from_headers!(ReleaseLeaseResponse , etag_from_headers => etag: String, - last_modified_from_headers => last_modified: DateTime, + last_modified_from_headers => last_modified: OffsetDateTime, request_id_from_headers => request_id: RequestId, - date_from_headers => date: DateTime + date_from_headers => date: OffsetDateTime ); diff --git a/sdk/storage_blobs/src/options/blob_expiry.rs b/sdk/storage_blobs/src/options/blob_expiry.rs index d5adb7353df..c1a386b5e4a 100644 --- a/sdk/storage_blobs/src/options/blob_expiry.rs +++ b/sdk/storage_blobs/src/options/blob_expiry.rs @@ -1,5 +1,5 @@ -use azure_core::headers::Headers; -use chrono::{DateTime, Utc}; +use azure_core::{date, headers::Headers}; +use time::OffsetDateTime; const EXPIRY_TIME: &str = "x-ms-expiry-time"; const EXPIRY_OPTION: &str = "x-ms-expiry-option"; @@ -8,7 +8,7 @@ const EXPIRY_OPTION: &str = "x-ms-expiry-option"; pub enum BlobExpiry { RelativeToCreation(u64), RelativeToNow(u64), - Absolute(DateTime), + Absolute(OffsetDateTime), NeverExpire, } @@ -26,7 +26,7 @@ impl BlobExpiry { } BlobExpiry::Absolute(date) => { headers.insert(EXPIRY_OPTION, "Abosolute"); - headers.insert(EXPIRY_TIME, date.to_rfc2822()); + headers.insert(EXPIRY_TIME, date::to_rfc1123(date)); } BlobExpiry::NeverExpire => { headers.insert(EXPIRY_OPTION, "NeverExpire"); diff --git a/sdk/storage_blobs/tests/blob.rs b/sdk/storage_blobs/tests/blob.rs index c2684467018..07c1dde598a 100644 --- a/sdk/storage_blobs/tests/blob.rs +++ b/sdk/storage_blobs/tests/blob.rs @@ -2,15 +2,14 @@ #[macro_use] extern crate log; +use azure_core::date; use azure_storage::core::prelude::*; use azure_storage_blobs::{blob::BlockListType, container::PublicAccess, prelude::*}; use bytes::Bytes; -use chrono::{FixedOffset, Utc}; use futures::StreamExt; -use std::{ - ops::{Add, Deref}, - time::Duration, -}; +use std::ops::{Add, Deref}; +use std::time::Duration; +use time::OffsetDateTime; use url::Url; use uuid::Uuid; @@ -32,8 +31,8 @@ async fn create_and_delete_container() -> azure_core::Result<()> { let _result = container.get_acl().into_future().await?; // set stored acess policy list - let dt_start = Utc::now().with_timezone(&FixedOffset::east(0)); - let dt_end = dt_start.add(chrono::Duration::days(7)); + let dt_start = OffsetDateTime::now_utc(); + let dt_end = dt_start.add(date::duration_from_days(7)); let mut sapl = StoredAccessPolicyList::default(); sapl.stored_access diff --git a/sdk/storage_datalake/Cargo.toml b/sdk/storage_datalake/Cargo.toml index cbd6ca7291f..bd7977e3ad4 100644 --- a/sdk/storage_datalake/Cargo.toml +++ b/sdk/storage_datalake/Cargo.toml @@ -19,7 +19,7 @@ azure_identity = { path = "../identity", default_features = false } azure_storage = { path = "../storage", version = "0.4", default_features = false } base64 = "0.13" bytes = "1.0" -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde"] } futures = "0.3" log = "0.4" serde = { version = "1.0" } diff --git a/sdk/storage_datalake/examples/directory.rs b/sdk/storage_datalake/examples/directory.rs index a2345ac0750..f743249433a 100644 --- a/sdk/storage_datalake/examples/directory.rs +++ b/sdk/storage_datalake/examples/directory.rs @@ -1,12 +1,15 @@ use azure_storage::storage_shared_key_credential::StorageSharedKeyCredential; use azure_storage_datalake::prelude::*; -use chrono::Utc; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { let data_lake_client = create_data_lake_client().await.unwrap(); - let file_system_name = format!("azurerustsdk-datalake-example00-{}", Utc::now().timestamp()); + let file_system_name = format!( + "azurerustsdk-datalake-example00-{}", + OffsetDateTime::now_utc().unix_timestamp() + ); let file_system_client = data_lake_client .clone() .into_file_system_client(file_system_name.to_string()); diff --git a/sdk/storage_datalake/examples/file_create_delete.rs b/sdk/storage_datalake/examples/file_create_delete.rs index b360a74056e..7d176f4eeb8 100644 --- a/sdk/storage_datalake/examples/file_create_delete.rs +++ b/sdk/storage_datalake/examples/file_create_delete.rs @@ -1,12 +1,15 @@ use azure_storage::storage_shared_key_credential::StorageSharedKeyCredential; use azure_storage_datalake::prelude::*; -use chrono::Utc; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { let data_lake_client = create_data_lake_client().await.unwrap(); - let file_system_name = format!("azurerustsdk-datalake-example01-{}", Utc::now().timestamp()); + let file_system_name = format!( + "azurerustsdk-datalake-example01-{}", + OffsetDateTime::now_utc().unix_timestamp() + ); let file_system_client = data_lake_client .clone() .into_file_system_client(file_system_name.to_string()); diff --git a/sdk/storage_datalake/examples/file_rename.rs b/sdk/storage_datalake/examples/file_rename.rs index 7047d49e6d0..f138f04ddd9 100644 --- a/sdk/storage_datalake/examples/file_rename.rs +++ b/sdk/storage_datalake/examples/file_rename.rs @@ -1,12 +1,15 @@ use azure_storage::storage_shared_key_credential::StorageSharedKeyCredential; use azure_storage_datalake::prelude::*; -use chrono::Utc; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { let data_lake_client = create_data_lake_client().await.unwrap(); - let file_system_name = format!("azurerustsdk-datalake-example01-{}", Utc::now().timestamp()); + let file_system_name = format!( + "azurerustsdk-datalake-example01-{}", + OffsetDateTime::now_utc().unix_timestamp() + ); let file_system_client = data_lake_client .clone() .into_file_system_client(file_system_name.to_string()); diff --git a/sdk/storage_datalake/examples/file_upload.rs b/sdk/storage_datalake/examples/file_upload.rs index 644d7496783..79b500f8caf 100644 --- a/sdk/storage_datalake/examples/file_upload.rs +++ b/sdk/storage_datalake/examples/file_upload.rs @@ -1,12 +1,15 @@ use azure_storage::storage_shared_key_credential::StorageSharedKeyCredential; use azure_storage_datalake::prelude::*; -use chrono::Utc; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { let data_lake_client = create_data_lake_client().await.unwrap(); - let file_system_name = format!("azurerustsdk-datalake-example01-{}", Utc::now().timestamp()); + let file_system_name = format!( + "azurerustsdk-datalake-example01-{}", + OffsetDateTime::now_utc().unix_timestamp() + ); let file_system_client = data_lake_client .clone() .into_file_system_client(file_system_name.to_string()); diff --git a/sdk/storage_datalake/examples/filesystem.rs b/sdk/storage_datalake/examples/filesystem.rs index 6585900603e..c08369574b1 100644 --- a/sdk/storage_datalake/examples/filesystem.rs +++ b/sdk/storage_datalake/examples/filesystem.rs @@ -1,14 +1,17 @@ use azure_storage::storage_shared_key_credential::StorageSharedKeyCredential; use azure_storage_datalake::prelude::*; -use chrono::Utc; use futures::stream::StreamExt; use std::num::NonZeroU32; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { let data_lake_client = create_data_lake_client().await.unwrap(); - let file_system_name = format!("azurerustsdk-datalake-example00-{}", Utc::now().timestamp()); + let file_system_name = format!( + "azurerustsdk-datalake-example00-{}", + OffsetDateTime::now_utc().unix_timestamp() + ); let file_system_client = data_lake_client .clone() .into_file_system_client(file_system_name.to_string()); diff --git a/sdk/storage_datalake/src/authorization_policies/shared_key.rs b/sdk/storage_datalake/src/authorization_policies/shared_key.rs index 52817fd7f41..67515e55a02 100644 --- a/sdk/storage_datalake/src/authorization_policies/shared_key.rs +++ b/sdk/storage_datalake/src/authorization_policies/shared_key.rs @@ -1,8 +1,9 @@ use azure_core::headers::{self, HeaderName, HeaderValue, Headers}; -use azure_core::Method; +use azure_core::{date, Method}; use azure_core::{Context, Policy, PolicyResult, Request}; use azure_storage::{core::storage_shared_key_credential::StorageSharedKeyCredential, hmac::sign}; use std::sync::Arc; +use time::OffsetDateTime; #[derive(Debug, Clone, PartialEq, Eq)] pub struct SharedKeyAuthorizationPolicy { @@ -31,10 +32,7 @@ impl Policy for SharedKeyAuthorizationPolicy { request.insert_header( azure_core::headers::MS_DATE, - HeaderValue::from(format!( - "{}", - chrono::Utc::now().format("%a, %d %h %Y %T GMT") - )), + HeaderValue::from(date::to_rfc1123(&OffsetDateTime::now_utc())), ); request.insert_header( azure_core::headers::VERSION, diff --git a/sdk/storage_datalake/src/file_system.rs b/sdk/storage_datalake/src/file_system.rs index b5bbb315396..d3278033910 100644 --- a/sdk/storage_datalake/src/file_system.rs +++ b/sdk/storage_datalake/src/file_system.rs @@ -1,15 +1,15 @@ use azure_core::Etag; use bytes::Bytes; -use chrono::{DateTime, Utc}; use serde::{self, Deserialize, Deserializer}; use std::convert::TryFrom; +use time::OffsetDateTime; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct FileSystem { pub name: String, - #[serde(with = "azure_core::parsing::rfc2822_time_format")] - pub last_modified: DateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub last_modified: OffsetDateTime, pub etag: Etag, } @@ -36,8 +36,8 @@ pub struct Path { pub group: String, #[serde(default, deserialize_with = "deserialize_bool")] pub is_directory: bool, - #[serde(with = "azure_core::parsing::rfc2822_time_format")] - pub last_modified: DateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub last_modified: OffsetDateTime, pub name: String, pub owner: String, pub permissions: String, diff --git a/sdk/storage_datalake/src/operations/file_system_create.rs b/sdk/storage_datalake/src/operations/file_system_create.rs index 44dec791f50..e98eb4ccde5 100644 --- a/sdk/storage_datalake/src/operations/file_system_create.rs +++ b/sdk/storage_datalake/src/operations/file_system_create.rs @@ -8,8 +8,8 @@ use azure_core::{ AppendToUrlQuery, Etag, Response as HttpResponse, }; use azure_storage::core::headers::CommonStorageResponseHeaders; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct CreateFileSystemBuilder { @@ -67,7 +67,7 @@ azure_core::future!(CreateFileSystem); pub struct CreateFileSystemResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, pub etag: Etag, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub namespace_enabled: bool, } diff --git a/sdk/storage_datalake/src/operations/file_system_get_properties.rs b/sdk/storage_datalake/src/operations/file_system_get_properties.rs index a5fe504aa67..15efc8e7480 100644 --- a/sdk/storage_datalake/src/operations/file_system_get_properties.rs +++ b/sdk/storage_datalake/src/operations/file_system_get_properties.rs @@ -6,8 +6,8 @@ use azure_core::{ }; use azure_core::{prelude::*, Request}; use azure_storage::core::headers::CommonStorageResponseHeaders; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct GetFileSystemPropertiesBuilder { @@ -61,7 +61,7 @@ azure_core::future!(GetFileSystemProperties); pub struct GetFileSystemPropertiesResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, pub etag: Etag, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub namespace_enabled: bool, pub properties: Properties, } diff --git a/sdk/storage_datalake/src/operations/file_system_set_properties.rs b/sdk/storage_datalake/src/operations/file_system_set_properties.rs index ad4f2e06319..d33b7ba1deb 100644 --- a/sdk/storage_datalake/src/operations/file_system_set_properties.rs +++ b/sdk/storage_datalake/src/operations/file_system_set_properties.rs @@ -6,8 +6,8 @@ use azure_core::{ }; use azure_core::{prelude::*, Request}; use azure_storage::core::headers::CommonStorageResponseHeaders; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct SetFileSystemPropertiesBuilder { @@ -69,7 +69,7 @@ azure_core::future!(SetFileSystemProperties); pub struct SetFileSystemPropertiesResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, pub etag: Etag, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, } impl SetFileSystemPropertiesResponse { diff --git a/sdk/storage_datalake/src/operations/path_get.rs b/sdk/storage_datalake/src/operations/path_get.rs index 6978855c4b1..56a671f308f 100644 --- a/sdk/storage_datalake/src/operations/path_get.rs +++ b/sdk/storage_datalake/src/operations/path_get.rs @@ -4,8 +4,8 @@ use azure_core::{collect_pinned_stream, AppendToUrlQuery, Response as HttpRespon use azure_core::{prelude::*, Request}; use azure_storage::core::headers::CommonStorageResponseHeaders; use bytes::Bytes; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct GetFileBuilder { @@ -79,7 +79,7 @@ azure_core::future!(GetFile); pub struct GetFileResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub data: Bytes, pub content_range: Option, } diff --git a/sdk/storage_datalake/src/operations/path_head.rs b/sdk/storage_datalake/src/operations/path_head.rs index dbf8cf4866b..ada9460df2d 100644 --- a/sdk/storage_datalake/src/operations/path_head.rs +++ b/sdk/storage_datalake/src/operations/path_head.rs @@ -3,8 +3,8 @@ use azure_core::headers::{self, etag_from_headers, last_modified_from_headers}; use azure_core::{prelude::*, Request}; use azure_core::{AppendToUrlQuery, Response as HttpResponse}; use azure_storage::core::headers::CommonStorageResponseHeaders; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct HeadPathBuilder @@ -85,7 +85,7 @@ pub struct HeadPathResponse { pub etag: String, pub content_length: Option, pub content_type: Option, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub properties: Option, pub acl: Option, } diff --git a/sdk/storage_datalake/src/operations/path_patch.rs b/sdk/storage_datalake/src/operations/path_patch.rs index 627d8c92152..33a30bcf75c 100644 --- a/sdk/storage_datalake/src/operations/path_patch.rs +++ b/sdk/storage_datalake/src/operations/path_patch.rs @@ -7,8 +7,8 @@ use azure_core::Request; use azure_core::{AppendToUrlQuery, Response as HttpResponse}; use azure_storage::core::headers::CommonStorageResponseHeaders; use bytes::Bytes; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct PatchPathBuilder @@ -116,7 +116,7 @@ azure_core::future!(PatchPath); pub struct PatchPathResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, pub etag: Option, - pub last_modified: Option>, + pub last_modified: Option, pub continuation: Option, } diff --git a/sdk/storage_datalake/src/operations/path_put.rs b/sdk/storage_datalake/src/operations/path_put.rs index aa38f610522..be040f00cf2 100644 --- a/sdk/storage_datalake/src/operations/path_put.rs +++ b/sdk/storage_datalake/src/operations/path_put.rs @@ -6,8 +6,8 @@ use azure_core::prelude::*; use azure_core::Request; use azure_core::{AppendToUrlQuery, Response as HttpResponse}; use azure_storage::core::headers::CommonStorageResponseHeaders; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct PutPathBuilder @@ -93,7 +93,7 @@ azure_core::future!(PutPath); pub struct PutPathResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, pub etag: String, - pub last_modified: DateTime, + pub last_modified: OffsetDateTime, pub continuation: Option, } diff --git a/sdk/storage_queues/Cargo.toml b/sdk/storage_queues/Cargo.toml index 8d52a72d60c..1a5672e1fe6 100644 --- a/sdk/storage_queues/Cargo.toml +++ b/sdk/storage_queues/Cargo.toml @@ -15,7 +15,7 @@ edition = "2021" [dependencies] azure_core = { path = "../core", version = "0.3", default-features=false } azure_storage = { path = "../storage", version = "0.4", default-features=false } -chrono = { version = "0.4", features = ["serde"] } +time = { version = "0.3", features = ["serde"] } futures = "0.3" log = "0.4" serde = { version = "1.0" } diff --git a/sdk/storage_queues/examples/get_messages.rs b/sdk/storage_queues/examples/get_messages.rs index 6ccfe3b388f..c971b10d10a 100644 --- a/sdk/storage_queues/examples/get_messages.rs +++ b/sdk/storage_queues/examples/get_messages.rs @@ -4,6 +4,7 @@ extern crate log; use azure_storage::core::prelude::*; use azure_storage_queues::prelude::*; use std::time::Duration; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { @@ -48,7 +49,7 @@ async fn main() -> azure_core::Result<()> { let response = pop_receipt .update( - format!("new body at {}", chrono::Utc::now()), + format!("new body at {}", OffsetDateTime::now_utc()), Duration::from_secs(4), ) .into_future() diff --git a/sdk/storage_queues/examples/put_message.rs b/sdk/storage_queues/examples/put_message.rs index ade27c64495..183d1de0022 100644 --- a/sdk/storage_queues/examples/put_message.rs +++ b/sdk/storage_queues/examples/put_message.rs @@ -3,6 +3,7 @@ extern crate log; use azure_storage::core::prelude::*; use azure_storage_queues::prelude::*; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { @@ -22,7 +23,10 @@ async fn main() -> azure_core::Result<()> { trace!("putting message"); let response = queue - .put_message(format!("Azure SDK for Rust rocks! {}", chrono::Utc::now())) + .put_message(format!( + "Azure SDK for Rust rocks! {}", + OffsetDateTime::now_utc() + )) .into_future() .await?; diff --git a/sdk/storage_queues/examples/queue_create.rs b/sdk/storage_queues/examples/queue_create.rs index f3523ec7b36..5e16c1db208 100644 --- a/sdk/storage_queues/examples/queue_create.rs +++ b/sdk/storage_queues/examples/queue_create.rs @@ -1,10 +1,10 @@ #[macro_use] extern crate log; -use azure_core::prelude::*; +use azure_core::{date, prelude::*}; use azure_storage::core::prelude::*; use azure_storage_queues::prelude::*; -use chrono::{Duration, Utc}; +use time::OffsetDateTime; #[tokio::main] async fn main() -> azure_core::Result<()> { @@ -30,9 +30,10 @@ async fn main() -> azure_core::Result<()> { metadata .as_mut() .insert("source".into(), "Azure SDK for Rust".into()); - metadata - .as_mut() - .insert("created".into(), format!("{:?}", Utc::now()).into()); + metadata.as_mut().insert( + "created".into(), + format!("{:?}", OffsetDateTime::now_utc()).into(), + ); let response = queue .create() @@ -43,7 +44,10 @@ async fn main() -> azure_core::Result<()> { // let's add some more metadata metadata.insert("version".to_owned(), "TBD".to_owned()); - metadata.insert("updated".to_owned(), format!("{:?}", Utc::now())); + metadata.insert( + "updated".to_owned(), + format!("{:?}", OffsetDateTime::now_utc()), + ); println!("metadata == {:#?}", metadata); @@ -58,15 +62,15 @@ async fn main() -> azure_core::Result<()> { let policies = vec![ QueueStoredAccessPolicy::new( "first_sap_read_process", - Utc::now() - Duration::hours(1), - Utc::now() + Duration::days(1), + OffsetDateTime::now_utc() - date::duration_from_hours(1), + OffsetDateTime::now_utc() + date::duration_from_days(1), ) .enable_read() .enable_process(), QueueStoredAccessPolicy::new( "sap_admin", - Utc::now() - chrono::Duration::hours(1), - Utc::now() + chrono::Duration::hours(5), + OffsetDateTime::now_utc() - date::duration_from_hours(1), + OffsetDateTime::now_utc() + date::duration_from_hours(5), ) .enable_all(), ]; diff --git a/sdk/storage_queues/src/operations/get_messages.rs b/sdk/storage_queues/src/operations/get_messages.rs index ce64a210bb2..b0cf4a27913 100644 --- a/sdk/storage_queues/src/operations/get_messages.rs +++ b/sdk/storage_queues/src/operations/get_messages.rs @@ -3,9 +3,9 @@ use azure_core::{ collect_pinned_stream, headers::Headers, prelude::*, Method, Response as AzureResponse, }; use azure_storage::core::{headers::CommonStorageResponseHeaders, xml::read_xml}; -use chrono::{DateTime, Utc}; use serde::Deserialize; use std::convert::TryInto; +use time::OffsetDateTime; operation! { GetMessages, @@ -47,12 +47,12 @@ pub struct GetMessagesResponse { pub struct Message { message_id: String, pop_receipt: String, - #[serde(deserialize_with = "deserialize_utc_date_from_rfc2822")] - pub insertion_time: DateTime, - #[serde(deserialize_with = "deserialize_utc_date_from_rfc2822")] - pub expiration_time: DateTime, - #[serde(deserialize_with = "deserialize_utc_date_from_rfc2822")] - pub time_next_visible: DateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub insertion_time: OffsetDateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub expiration_time: OffsetDateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub time_next_visible: OffsetDateTime, pub dequeue_count: u64, pub message_text: String, } diff --git a/sdk/storage_queues/src/operations/get_queue_service_stats.rs b/sdk/storage_queues/src/operations/get_queue_service_stats.rs index 595517fd7d8..0cb1c3f5c50 100644 --- a/sdk/storage_queues/src/operations/get_queue_service_stats.rs +++ b/sdk/storage_queues/src/operations/get_queue_service_stats.rs @@ -1,13 +1,13 @@ use crate::QueueServiceClient; use azure_core::{ - collect_pinned_stream, + collect_pinned_stream, date, error::{ErrorKind, ResultExt}, headers::Headers, Method, Response as AzureResponse, }; use azure_storage::core::{headers::CommonStorageResponseHeaders, xml::read_xml}; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; operation! { GetQueueServiceStats, @@ -52,7 +52,7 @@ pub enum Status { pub struct GetQueueServiceStatsResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, pub status: Status, - pub last_sync_time: Option>, + pub last_sync_time: Option, } #[derive(Debug, Clone, Deserialize)] @@ -81,10 +81,11 @@ impl GetQueueServiceStatsResponse { last_sync_time: response .geo_replication .last_sync_time - .map(|t| DateTime::parse_from_rfc2822(&t)) - .transpose() - .context(ErrorKind::DataConversion, "failed to parse last sync time")? - .map(|t| DateTime::from_utc(t.naive_utc(), Utc)), + .map(|t| { + date::parse_rfc1123(&t) + .context(ErrorKind::DataConversion, "failed to parse last sync time") + }) + .transpose()?, }) } } diff --git a/sdk/storage_queues/src/operations/peek_messages.rs b/sdk/storage_queues/src/operations/peek_messages.rs index 17b1661a507..f97245b7e5f 100644 --- a/sdk/storage_queues/src/operations/peek_messages.rs +++ b/sdk/storage_queues/src/operations/peek_messages.rs @@ -3,8 +3,8 @@ use azure_core::{ collect_pinned_stream, headers::Headers, prelude::*, Method, Response as AzureResponse, }; use azure_storage::core::{headers::CommonStorageResponseHeaders, xml::read_xml}; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; operation! { PeekMessages, @@ -50,10 +50,10 @@ pub struct PeekMessagesBody { #[serde(rename_all = "PascalCase")] pub struct PeekMessage { pub message_id: String, - #[serde(deserialize_with = "deserialize_utc_date_from_rfc2822")] - pub insertion_time: DateTime, - #[serde(deserialize_with = "deserialize_utc_date_from_rfc2822")] - pub expiration_time: DateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub insertion_time: OffsetDateTime, + #[serde(with = "azure_core::date::rfc1123")] + pub expiration_time: OffsetDateTime, pub dequeue_count: u64, pub message_text: String, } diff --git a/sdk/storage_queues/src/operations/put_message.rs b/sdk/storage_queues/src/operations/put_message.rs index 45729d2cf9e..f58e6bab7bf 100644 --- a/sdk/storage_queues/src/operations/put_message.rs +++ b/sdk/storage_queues/src/operations/put_message.rs @@ -1,11 +1,10 @@ use crate::prelude::*; use azure_core::{ - collect_pinned_stream, headers::utc_date_from_rfc2822, headers::Headers, prelude::*, Method, - Response as AzureResponse, + collect_pinned_stream, date, headers::Headers, prelude::*, Method, Response as AzureResponse, }; use azure_storage::{core::headers::CommonStorageResponseHeaders, xml::read_xml}; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; operation! { PutMessage, @@ -60,10 +59,10 @@ struct PutMessageResponseInternal { #[derive(Debug, Clone)] pub struct QueueMessage { pub message_id: String, - pub insertion_time: DateTime, - pub expiration_time: DateTime, + pub insertion_time: OffsetDateTime, + pub expiration_time: OffsetDateTime, pub pop_receipt: String, - pub time_next_visible: DateTime, + pub time_next_visible: OffsetDateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -90,10 +89,10 @@ impl PutMessageResponse { let queue_message = QueueMessage { message_id: queue_message.message_id, - insertion_time: utc_date_from_rfc2822(&queue_message.insertion_time)?, - expiration_time: utc_date_from_rfc2822(&queue_message.expiration_time)?, + insertion_time: date::parse_rfc1123(&queue_message.insertion_time)?, + expiration_time: date::parse_rfc1123(&queue_message.expiration_time)?, pop_receipt: queue_message.pop_receipt, - time_next_visible: utc_date_from_rfc2822(&queue_message.time_next_visible)?, + time_next_visible: date::parse_rfc1123(&queue_message.time_next_visible)?, }; Ok(Self { diff --git a/sdk/storage_queues/src/operations/update_message.rs b/sdk/storage_queues/src/operations/update_message.rs index bf4161c3344..a016b4ef648 100644 --- a/sdk/storage_queues/src/operations/update_message.rs +++ b/sdk/storage_queues/src/operations/update_message.rs @@ -2,13 +2,13 @@ use crate::{clients::PopReceiptClient, prelude::*}; use azure_core::{ error::Error, headers::Headers, - headers::{rfc2822_from_headers_mandatory, HeaderName}, + headers::{rfc1123_from_headers_mandatory, HeaderName}, prelude::*, Method, Response as AzureResponse, }; use azure_storage::core::headers::CommonStorageResponseHeaders; -use chrono::{DateTime, Utc}; use std::convert::TryInto; +use time::OffsetDateTime; operation! { UpdateMessage, @@ -49,7 +49,7 @@ impl UpdateMessageBuilder { #[derive(Debug, Clone)] pub struct UpdateMessageResponse { pub common_storage_response_headers: CommonStorageResponseHeaders, - pub time_next_visible: DateTime, + pub time_next_visible: OffsetDateTime, pub pop_receipt: String, } @@ -60,7 +60,7 @@ impl std::convert::TryFrom for UpdateMessageResponse { let headers = response.headers(); Ok(UpdateMessageResponse { common_storage_response_headers: response.headers().try_into()?, - time_next_visible: rfc2822_from_headers_mandatory( + time_next_visible: rfc1123_from_headers_mandatory( headers, &HeaderName::from_static("x-ms-time-next-visible"), )?, diff --git a/sdk/storage_queues/src/queue_stored_access_policy.rs b/sdk/storage_queues/src/queue_stored_access_policy.rs index e9cb9a7ebaf..aa49dc84178 100644 --- a/sdk/storage_queues/src/queue_stored_access_policy.rs +++ b/sdk/storage_queues/src/queue_stored_access_policy.rs @@ -1,13 +1,13 @@ use azure_core::error::{Error, ErrorKind}; use azure_storage::StoredAccessPolicy; -use chrono::{DateTime, FixedOffset}; use std::convert::TryFrom; +use time::OffsetDateTime; #[derive(Debug, Clone)] pub struct QueueStoredAccessPolicy { pub id: String, - pub start: DateTime, - pub expiry: DateTime, + pub start: OffsetDateTime, + pub expiry: OffsetDateTime, pub is_read_enabled: bool, pub is_add_enabled: bool, pub is_update_enabled: bool, @@ -17,8 +17,8 @@ pub struct QueueStoredAccessPolicy { impl QueueStoredAccessPolicy { pub fn new( id: impl Into, - start: impl Into>, - expiry: impl Into>, + start: impl Into, + expiry: impl Into, ) -> Self { Self { id: id.into(), diff --git a/sdk/storage_queues/tests/queue.rs b/sdk/storage_queues/tests/queue.rs index f6ae2555717..2cc34947fe8 100644 --- a/sdk/storage_queues/tests/queue.rs +++ b/sdk/storage_queues/tests/queue.rs @@ -1,10 +1,10 @@ #![cfg(all(test, feature = "test_e2e"))] -use azure_core::prelude::*; +use azure_core::{date, prelude::*}; use azure_storage::core::prelude::*; use azure_storage_queues::prelude::*; -use chrono::Utc; use futures::StreamExt; use std::time::Duration; +use time::OffsetDateTime; use uuid::Uuid; #[tokio::test] @@ -30,9 +30,10 @@ async fn queue_create_put_and_get() -> azure_core::Result<()> { metadata .as_mut() .insert("source".into(), "Azure SDK for Rust".into()); - metadata - .as_mut() - .insert("created".into(), format!("{:?}", Utc::now()).into()); + metadata.as_mut().insert( + "created".into(), + format!("{:?}", OffsetDateTime::now_utc()).into(), + ); let response = queue .create() @@ -43,7 +44,10 @@ async fn queue_create_put_and_get() -> azure_core::Result<()> { // let's add some more metadata metadata.insert("version".to_owned(), "TBD".to_owned()); - metadata.insert("updated".to_owned(), format!("{:?}", Utc::now())); + metadata.insert( + "updated".to_owned(), + format!("{:?}", OffsetDateTime::now_utc()), + ); println!("metadata == {:#?}", metadata); @@ -58,15 +62,15 @@ async fn queue_create_put_and_get() -> azure_core::Result<()> { let policies = vec![ QueueStoredAccessPolicy::new( "first_sap_read_process", - Utc::now() - chrono::Duration::hours(1), - Utc::now() + chrono::Duration::days(1), + OffsetDateTime::now_utc() - date::duration_from_hours(1), + OffsetDateTime::now_utc() + date::duration_from_days(1), ) .enable_read() .enable_process(), QueueStoredAccessPolicy::new( "sap_admin", - Utc::now() - chrono::Duration::hours(1), - Utc::now() + chrono::Duration::hours(5), + OffsetDateTime::now_utc() - date::duration_from_hours(1), + OffsetDateTime::now_utc() + date::duration_from_hours(5), ) .enable_all(), ]; @@ -88,7 +92,7 @@ async fn queue_create_put_and_get() -> azure_core::Result<()> { println!("putting message {}", i); let response = queue - .put_message(format!("Azure SDK for Rust {}", chrono::Utc::now())) + .put_message(format!("Azure SDK for Rust {}", OffsetDateTime::now_utc())) .into_future() .await?; @@ -108,7 +112,7 @@ async fn queue_create_put_and_get() -> azure_core::Result<()> { let response = pop_receipt .update( - format!("new body at {}", chrono::Utc::now()), + format!("new body at {}", OffsetDateTime::now_utc()), Duration::from_secs(4), ) .into_future()