This is an automated email from the ASF dual-hosted git repository. tison pushed a commit to branch fixup-vibe-coding in repository https://gitbox.apache.org/repos/asf/opendal.git
commit 2b707210cb2ac8230e2e164e1ecc5b85ccc8ecd1 Author: tison <[email protected]> AuthorDate: Tue Oct 14 14:05:56 2025 +0800 chore: fixup timestamp refactor Signed-off-by: tison <[email protected]> --- bindings/java/src/convert.rs | 20 ++++---- core/src/raw/mod.rs | 2 +- core/src/raw/time.rs | 84 ++++----------------------------- core/src/services/upyun/core.rs | 2 +- integrations/dav-server/src/metadata.rs | 9 ++-- integrations/fuse3/src/file_system.rs | 8 ++-- integrations/unftp-sbe/src/lib.rs | 23 ++++----- 7 files changed, 42 insertions(+), 106 deletions(-) diff --git a/bindings/java/src/convert.rs b/bindings/java/src/convert.rs index 124d6c42e..fc5bdc73a 100644 --- a/bindings/java/src/convert.rs +++ b/bindings/java/src/convert.rs @@ -136,17 +136,15 @@ pub(crate) fn read_instant_field_to_timestamp( .call_method(&result, "getEpochSecond", "()J", &[])? .j()?; let nano = env.call_method(&result, "getNano", "()I", &[])?.i()?; - - opendal::raw::Timestamp::from_second(epoch_second) - .map(Some) - .map_err(|err| { - Error::new( - ErrorKind::Unexpected, - format!("invalid timestamp: seconds={epoch_second}, nanos={nano}"), - ) - .set_source(err) - .into() - }) + match opendal::raw::Timestamp::new(epoch_second, nano) { + Ok(ts) => Ok(Some(ts)), + Err(err) => Err(Error::new( + ErrorKind::Unexpected, + format!("invalid timestamp: seconds={epoch_second}, nanos={nano}"), + ) + .set_source(err) + .into()), + } } pub(crate) fn offset_length_to_range(offset: i64, length: i64) -> Result<(Bound<u64>, Bound<u64>)> { diff --git a/core/src/raw/mod.rs b/core/src/raw/mod.rs index 7c6a62e71..768026850 100644 --- a/core/src/raw/mod.rs +++ b/core/src/raw/mod.rs @@ -72,7 +72,7 @@ mod serde_util; pub use serde_util::*; mod time; -pub use time::Timestamp; +pub use time::*; #[cfg(feature = "internal-tokio-rt")] mod tokio_util; diff --git a/core/src/raw/time.rs b/core/src/raw/time.rs index 3225f270a..9f9f0b3fe 100644 --- a/core/src/raw/time.rs +++ b/core/src/raw/time.rs @@ -70,16 +70,6 @@ impl Timestamp { Self(jiff::Timestamp::now()) } - /// Format the timestamp into date: `20220301` - pub fn format_date(self) -> String { - self.0.strftime("%Y%m%d").to_string() - } - - /// Format the timestamp into ISO8601: `20220313T072004Z` - pub fn format_iso8601(self) -> String { - self.0.strftime("%Y%m%dT%H%M%SZ").to_string() - } - /// Format the timestamp into http date: `Sun, 06 Nov 1994 08:49:37 GMT` /// /// ## Note @@ -92,16 +82,6 @@ impl Timestamp { self.0.strftime("%a, %d %b %Y %T GMT").to_string() } - /// Format the timestamp into RFC3339 in Zulu: `2022-03-13T07:20:04Z` - pub fn format_rfc3339_zulu(self) -> String { - self.0.strftime("%FT%TZ").to_string() - } - - /// Convert to `SystemTime`. - pub fn as_system_time(self) -> SystemTime { - SystemTime::from(self.0) - } - /// Creates a new instant in time from the number of seconds elapsed since the Unix epoch. /// /// When second is negative, it corresponds to an instant in time before the Unix epoch. @@ -170,27 +150,6 @@ impl Timestamp { } } - /// Parse the string format "2023-10-31 21:59:10.000000". - pub fn parse_datetime_utc(s: &str) -> Result<Timestamp> { - let dt = s.parse::<jiff::civil::DateTime>().map_err(|err| { - Error::new( - ErrorKind::Unexpected, - format!("parse '{s}' into datetime failed"), - ) - .set_source(err) - })?; - - let ts = jiff::tz::TimeZone::UTC.to_timestamp(dt).map_err(|err| { - Error::new( - ErrorKind::Unexpected, - format!("convert '{s}' into timestamp failed"), - ) - .set_source(err) - })?; - - Ok(Timestamp(ts)) - } - /// Convert to inner `jiff::Timestamp` for compatibility. /// /// This method is provided for accessing the underlying `jiff::Timestamp` @@ -198,28 +157,23 @@ impl Timestamp { pub fn into_inner(self) -> jiff::Timestamp { self.0 } +} - /// Format the timestamp using `strftime` format string. - /// - /// Common formats: - /// - `"%Y-%m-%d"` - Date like `2022-03-01` - /// - `"%a, %d %b %Y %H:%M:%S GMT"` - HTTP date - /// - /// For full format documentation, see [jiff::fmt::strtime](https://docs.rs/jiff/latest/jiff/fmt/strtime/index.html) - pub fn strftime(self, format: &str) -> String { - self.0.strftime(format).to_string() +impl From<Timestamp> for jiff::Timestamp { + fn from(t: Timestamp) -> Self { + t.0 } } -impl From<jiff::Timestamp> for Timestamp { - fn from(t: jiff::Timestamp) -> Self { - Timestamp(t) +impl From<Timestamp> for SystemTime { + fn from(t: Timestamp) -> Self { + t.0.into() } } -impl From<Timestamp> for jiff::Timestamp { - fn from(t: Timestamp) -> Self { - t.0 +impl From<jiff::Timestamp> for Timestamp { + fn from(t: jiff::Timestamp) -> Self { + Timestamp(t) } } @@ -279,30 +233,12 @@ mod tests { Timestamp("2022-03-01T08:12:34Z".parse().unwrap()) } - #[test] - fn test_format_date() { - let t = test_time(); - assert_eq!("20220301", t.format_date()) - } - - #[test] - fn test_format_iso8601() { - let t = test_time(); - assert_eq!("20220301T081234Z", t.format_iso8601()) - } - #[test] fn test_format_http_date() { let t = test_time(); assert_eq!("Tue, 01 Mar 2022 08:12:34 GMT", t.format_http_date()) } - #[test] - fn test_format_rfc3339() { - let t = test_time(); - assert_eq!("2022-03-01T08:12:34Z", t.format_rfc3339_zulu()) - } - #[test] fn test_parse_rfc3339() { let t = test_time(); diff --git a/core/src/services/upyun/core.rs b/core/src/services/upyun/core.rs index 2637a61c8..801e3f881 100644 --- a/core/src/services/upyun/core.rs +++ b/core/src/services/upyun/core.rs @@ -86,7 +86,7 @@ impl UpyunCore { pub fn sign(&self, req: &mut Request<Buffer>) -> Result<()> { // get rfc1123 date - let date = Timestamp::now().strftime("%a, %d %b %Y %H:%M:%S GMT"); + let date = Timestamp::now().format_http_date(); let authorization = self.signer .authorization(&date, req.method().as_str(), req.uri().path()); diff --git a/integrations/dav-server/src/metadata.rs b/integrations/dav-server/src/metadata.rs index 1286e9cb8..5112029c9 100644 --- a/integrations/dav-server/src/metadata.rs +++ b/integrations/dav-server/src/metadata.rs @@ -40,7 +40,7 @@ impl DavMetaData for OpendalMetaData { fn modified(&self) -> FsResult<SystemTime> { match self.metadata.last_modified() { - Some(t) => Ok(t.as_system_time()), + Some(t) => Ok(t.into()), None => Err(FsError::GeneralFailure), } } @@ -58,8 +58,9 @@ impl DavMetaData for OpendalMetaData { } fn status_changed(&self) -> FsResult<SystemTime> { - self.metadata - .last_modified() - .map_or(Err(FsError::GeneralFailure), |t| Ok(t.as_system_time())) + match self.metadata.last_modified() { + Some(t) => Ok(t.into()), + None => Err(FsError::GeneralFailure), + } } } diff --git a/integrations/fuse3/src/file_system.rs b/integrations/fuse3/src/file_system.rs index 7876fa9b6..4c44e3b53 100644 --- a/integrations/fuse3/src/file_system.rs +++ b/integrations/fuse3/src/file_system.rs @@ -776,10 +776,10 @@ const fn entry_mode2file_type(mode: EntryMode) -> FileType { } fn metadata2file_attr(metadata: &Metadata, atime: SystemTime, uid: u32, gid: u32) -> FileAttr { - let last_modified = metadata - .last_modified() - .map(|t| t.into_inner().into()) - .unwrap_or(atime); + let last_modified = match metadata.last_modified() { + None => atime, + Some(ts) => ts.into(), + }; let kind = entry_mode2file_type(metadata.mode()); FileAttr { size: metadata.content_length(), diff --git a/integrations/unftp-sbe/src/lib.rs b/integrations/unftp-sbe/src/lib.rs index 31c3994c2..915c13470 100644 --- a/integrations/unftp-sbe/src/lib.rs +++ b/integrations/unftp-sbe/src/lib.rs @@ -79,7 +79,7 @@ impl OpendalStorage { } } -/// A wrapper around [`opendal::Metadata`] to implement [`libunftp::storage::Metadata`]. +/// A wrapper around [`opendal::Metadata`] to implement [`storage::Metadata`]. #[derive(Debug, Clone, Eq, PartialEq)] pub struct OpendalMetadata(opendal::Metadata); @@ -101,12 +101,13 @@ impl storage::Metadata for OpendalMetadata { } fn modified(&self) -> storage::Result<std::time::SystemTime> { - self.0 - .last_modified() - .map(|t| t.into_inner().into()) - .ok_or_else(|| { - storage::Error::new(storage::ErrorKind::LocalError, "no last modified time") - }) + match self.0.last_modified() { + Some(ts) => Ok(ts.into()), + None => Err(Error::new( + storage::ErrorKind::LocalError, + "no last modified time", + )), + } } fn gid(&self) -> u32 { @@ -118,19 +119,19 @@ impl storage::Metadata for OpendalMetadata { } } -fn convert_err(err: opendal::Error) -> storage::Error { +fn convert_err(err: opendal::Error) -> Error { let kind = match err.kind() { opendal::ErrorKind::NotFound => storage::ErrorKind::PermanentFileNotAvailable, opendal::ErrorKind::AlreadyExists => storage::ErrorKind::PermanentFileNotAvailable, opendal::ErrorKind::PermissionDenied => storage::ErrorKind::PermissionDenied, _ => storage::ErrorKind::LocalError, }; - storage::Error::new(kind, err) + Error::new(kind, err) } fn convert_path(path: &Path) -> storage::Result<&str> { path.to_str().ok_or_else(|| { - storage::Error::new( + Error::new( storage::ErrorKind::LocalError, "Path is not a valid UTF-8 string", ) @@ -273,7 +274,7 @@ impl<User: UserDetail> StorageBackend<User> for OpendalStorage { match self.op.stat(convert_path(path.as_ref())?).await { Ok(_) => Ok(()), - Err(e) if matches!(e.kind(), NotFound | NotADirectory) => Err(storage::Error::new( + Err(e) if matches!(e.kind(), NotFound | NotADirectory) => Err(Error::new( storage::ErrorKind::PermanentDirectoryNotAvailable, e, )),
