This is an automated email from the ASF dual-hosted git repository.
tison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git
The following commit(s) were added to refs/heads/main by this push:
new dbc5e2532 chore: fixup timestamp refactor (#6663)
dbc5e2532 is described below
commit dbc5e2532a6f6b217c9ced7879b8d9465dd9c639
Author: tison <[email protected]>
AuthorDate: Tue Oct 14 15:02:42 2025 +0800
chore: fixup timestamp refactor (#6663)
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,
)),