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 6c8eddbf5 refactor!: migrate chrono to jiff (#6643)
6c8eddbf5 is described below

commit 6c8eddbf5b0649c3e4b955e560f2003af4b95903
Author: tison <[email protected]>
AuthorDate: Fri Oct 10 18:15:40 2025 +0800

    refactor!: migrate chrono to jiff (#6643)
    
    Signed-off-by: tison <[email protected]>
---
 bin/oay/Cargo.lock                            | 321 ++++++++++++++++++--------
 bin/oay/Cargo.toml                            |   8 +-
 bin/oay/src/bin/oay.rs                        |   2 +-
 bin/oay/src/bin/webdav.rs                     |   2 +-
 bin/oay/src/services/s3/service.rs            |   6 +-
 bin/oli/Cargo.lock                            |  54 ++++-
 bin/oli/tests/integration/test_utils.rs       |   4 +
 bindings/c/src/metadata.rs                    |   2 +-
 bindings/cpp/Cargo.toml                       |  10 +-
 bindings/cpp/src/types.rs                     |   5 +-
 bindings/dart/rust/src/api/opendal_api.rs     |   2 +-
 bindings/haskell/Cargo.toml                   |   2 +-
 bindings/haskell/src/types.rs                 |   3 +-
 bindings/java/Cargo.toml                      |   6 +-
 bindings/java/src/convert.rs                  |  23 +-
 bindings/java/src/lib.rs                      |   8 +-
 bindings/nodejs/src/lib.rs                    |   2 +-
 bindings/ocaml/src/operator/metadata.rs       |   2 +-
 bindings/python/Cargo.toml                    |   4 +-
 bindings/python/src/metadata.rs               |   8 +-
 bindings/python/src/options.rs                |  11 +-
 core/Cargo.lock                               |  12 +-
 core/Cargo.toml                               |   5 +-
 core/src/lib.rs                               |   4 +-
 core/src/raw/adapters/typed_kv/api.rs         |  14 +-
 core/src/raw/http_util/header.rs              |   5 +-
 core/src/raw/{chrono_util.rs => jiff_util.rs} |  82 ++++---
 core/src/raw/mod.rs                           |   4 +-
 core/src/raw/ops.rs                           |  33 ++-
 core/src/raw/std_io_util.rs                   |   2 +-
 core/src/services/aliyun_drive/backend.rs     |  18 +-
 core/src/services/aliyun_drive/core.rs        |   6 +-
 core/src/services/aliyun_drive/lister.rs      |  21 +-
 core/src/services/alluxio/core.rs             |   2 +-
 core/src/services/b2/core.rs                  |  14 +-
 core/src/services/cacache/backend.rs          |  14 +-
 core/src/services/cloudflare_kv/backend.rs    |  16 +-
 core/src/services/cloudflare_kv/writer.rs     |   6 +-
 core/src/services/compfs/backend.rs           |   4 +-
 core/src/services/dashmap/writer.rs           |   4 +-
 core/src/services/dbfs/backend.rs             |   2 +-
 core/src/services/dbfs/lister.rs              |   4 +-
 core/src/services/dropbox/builder.rs          |   6 +-
 core/src/services/dropbox/core.rs             |  27 +--
 core/src/services/fs/core.rs                  |  12 +-
 core/src/services/fs/writer.rs                |   8 +-
 core/src/services/ftp/backend.rs              |   2 +-
 core/src/services/ftp/lister.rs               |   2 +-
 core/src/services/gdrive/backend.rs           |  11 +-
 core/src/services/gdrive/builder.rs           |   8 +-
 core/src/services/gdrive/core.rs              |  25 +-
 core/src/services/github/core.rs              |   5 +-
 core/src/services/hdfs/backend.rs             |   2 +-
 core/src/services/hdfs/lister.rs              |   2 +-
 core/src/services/hdfs_native/backend.rs      |   2 +-
 core/src/services/hdfs_native/lister.rs       |   4 +-
 core/src/services/koofr/backend.rs            |   2 +-
 core/src/services/koofr/lister.rs             |   2 +-
 core/src/services/lakefs/backend.rs           |   5 +-
 core/src/services/lakefs/lister.rs            |   8 +-
 core/src/services/mini_moka/writer.rs         |   6 +-
 core/src/services/monoiofs/backend.rs         |  12 +-
 core/src/services/monoiofs/writer.rs          |  10 +-
 core/src/services/onedrive/builder.rs         |  12 +-
 core/src/services/onedrive/core.rs            |  18 +-
 core/src/services/onedrive/graph_model.rs     |   2 +-
 core/src/services/seafile/lister.rs           |   2 +-
 core/src/services/sftp/utils.rs               |   5 +-
 core/src/services/upyun/core.rs               |   5 +-
 core/src/services/upyun/lister.rs             |   2 +-
 core/src/services/webhdfs/backend.rs          |   2 +-
 core/src/services/webhdfs/lister.rs           |   2 +-
 core/src/types/metadata.rs                    |  14 +-
 core/src/types/operator/operator_futures.rs   |  38 ++-
 core/src/types/options.rs                     |  19 +-
 core/tests/behavior/async_read.rs             |  16 +-
 integrations/cloud_filter/src/lib.rs          |   2 +-
 integrations/object_store/Cargo.toml          |   2 +
 integrations/object_store/src/lib.rs          |   8 +
 integrations/object_store/src/service/core.rs |  16 +-
 integrations/object_store/src/store.rs        |  22 +-
 integrations/object_store/src/utils.rs        |   6 +-
 82 files changed, 637 insertions(+), 474 deletions(-)

diff --git a/bin/oay/Cargo.lock b/bin/oay/Cargo.lock
index 69607408b..ec05882b4 100644
--- a/bin/oay/Cargo.lock
+++ b/bin/oay/Cargo.lock
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "addr2line"
@@ -32,15 +32,6 @@ version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
-[[package]]
-name = "android_system_properties"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "anyhow"
 version = "1.0.100"
@@ -192,24 +183,14 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
 
 [[package]]
-name = "chrono"
-version = "0.4.42"
+name = "colored"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
 dependencies = [
- "iana-time-zone",
- "js-sys",
- "num-traits",
- "wasm-bindgen",
- "windows-link 0.2.1",
+ "windows-sys 0.52.0",
 ]
 
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.7"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
-
 [[package]]
 name = "cpufeatures"
 version = "0.2.17"
@@ -322,22 +303,23 @@ version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
 
-[[package]]
-name = "env_filter"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
-dependencies = [
- "log",
- "regex",
-]
-
 [[package]]
 name = "equivalent"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
 
+[[package]]
+name = "erased-serde"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b"
+dependencies = [
+ "serde",
+ "serde_core",
+ "typeid",
+]
+
 [[package]]
 name = "errno"
 version = "0.3.12"
@@ -667,30 +649,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "iana-time-zone"
-version = "0.1.63"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "iana-time-zone-haiku",
- "js-sys",
- "log",
- "wasm-bindgen",
- "windows-core",
-]
-
-[[package]]
-name = "iana-time-zone-haiku"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
-dependencies = [
- "cc",
-]
-
 [[package]]
 name = "icu_collections"
 version = "2.0.0"
@@ -843,9 +801,9 @@ checksum = 
"4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
 
 [[package]]
 name = "jiff"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
+checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
 dependencies = [
  "jiff-static",
  "jiff-tzdb-platform",
@@ -858,9 +816,9 @@ dependencies = [
 
 [[package]]
 name = "jiff-static"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
+checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -931,17 +889,76 @@ name = "log"
 version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+dependencies = [
+ "sval",
+ "sval_ref",
+ "value-bag",
+]
 
 [[package]]
 name = "logforth"
-version = "0.27.0"
+version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "8bb3bacbca013b1a4d9f342501b6aa28eb32a6aa33bc804792fad83d661a59d5"
+checksum = "bd048889d633cac5c189eca703f5c5ed65210d358eb5910a478e233d42528d6e"
+dependencies = [
+ "logforth-append-file",
+ "logforth-bridge-log",
+ "logforth-core",
+ "logforth-layout-json",
+ "logforth-layout-text",
+]
+
+[[package]]
+name = "logforth-append-file"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "aeb66a16ac0f5cdd6a0e7005c6e1fa2744e915244941ac6cd01bd56de2995f48"
 dependencies = [
- "anyhow",
- "env_filter",
  "jiff",
+ "logforth-core",
+]
+
+[[package]]
+name = "logforth-bridge-log"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "392ff9723d68a943ccffabe03b5272f7c93104f0008a6c7357ef888c21ab6297"
+dependencies = [
  "log",
+ "logforth-core",
+]
+
+[[package]]
+name = "logforth-core"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "7666819ed32e38aabb45959a632b0f9c25fc77e60c824b02a5fcd87ab626f6ed"
+dependencies = [
+ "anyhow",
+ "value-bag",
+]
+
+[[package]]
+name = "logforth-layout-json"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "49e1db5d0f5b1bc57134ff9d1ed3889910d230545f3d249bde44bac0e8a8724f"
+dependencies = [
+ "jiff",
+ "logforth-core",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "logforth-layout-text"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "c00c67d92539b26edbba5e43ce8f5b97d62412c1cfc9463400f50cfad2f1f1bf"
+dependencies = [
+ "colored",
+ "jiff",
+ "logforth-core",
 ]
 
 [[package]]
@@ -1023,25 +1040,16 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
 
-[[package]]
-name = "num-traits"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
-dependencies = [
- "autocfg",
-]
-
 [[package]]
 name = "oay"
 version = "0.41.23"
 dependencies = [
  "anyhow",
  "axum",
- "chrono",
  "dav-server",
  "dav-server-opendalfs",
  "futures-util",
+ "jiff",
  "log",
  "logforth",
  "opendal",
@@ -1075,11 +1083,11 @@ dependencies = [
  "backon",
  "base64 0.22.1",
  "bytes",
- "chrono",
  "futures",
  "getrandom 0.2.16",
  "http",
  "http-body",
+ "jiff",
  "log",
  "md-5",
  "percent-encoding",
@@ -1502,6 +1510,15 @@ dependencies = [
  "serde_derive",
 ]
 
+[[package]]
+name = "serde_buf"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "3a86be9d6c7d34718d2ec6f56c8d6a4671d1a7357c2a6921f47fe5a3ee6056cc"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "serde_core"
 version = "1.0.228"
@@ -1522,6 +1539,15 @@ dependencies = [
  "syn 2.0.101",
 ]
 
+[[package]]
+name = "serde_fmt"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "serde_json"
 version = "1.0.140"
@@ -1629,6 +1655,84 @@ version = "2.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
 
+[[package]]
+name = "sval"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "d94c4464e595f0284970fd9c7e9013804d035d4a61ab74b113242c874c05814d"
+
+[[package]]
+name = "sval_buffer"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "a0f46e34b20a39e6a2bf02b926983149b3af6609fd1ee8a6e63f6f340f3e2164"
+dependencies = [
+ "sval",
+ "sval_ref",
+]
+
+[[package]]
+name = "sval_dynamic"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "03d0970e53c92ab5381d3b2db1828da8af945954d4234225f6dd9c3afbcef3f5"
+dependencies = [
+ "sval",
+]
+
+[[package]]
+name = "sval_fmt"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "43e5e6e1613e1e7fc2e1a9fdd709622e54c122ceb067a60d170d75efd491a839"
+dependencies = [
+ "itoa",
+ "ryu",
+ "sval",
+]
+
+[[package]]
+name = "sval_json"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "aec382f7bfa6e367b23c9611f129b94eb7daaf3d8fae45a8d0a0211eb4d4c8e6"
+dependencies = [
+ "itoa",
+ "ryu",
+ "sval",
+]
+
+[[package]]
+name = "sval_nested"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "3049d0f99ce6297f8f7d9953b35a0103b7584d8f638de40e64edb7105fa578ae"
+dependencies = [
+ "sval",
+ "sval_buffer",
+ "sval_ref",
+]
+
+[[package]]
+name = "sval_ref"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "f88913e77506085c0a8bf6912bb6558591a960faf5317df6c1d9b227224ca6e1"
+dependencies = [
+ "sval",
+]
+
+[[package]]
+name = "sval_serde"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "f579fd7254f4be6cd7b450034f856b78523404655848789c451bacc6aa8b387d"
+dependencies = [
+ "serde_core",
+ "sval",
+ "sval_nested",
+]
+
 [[package]]
 name = "syn"
 version = "1.0.109"
@@ -1910,6 +2014,12 @@ version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
 
+[[package]]
+name = "typeid"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
+
 [[package]]
 name = "typenum"
 version = "1.18.0"
@@ -1963,6 +2073,43 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "value-bag"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5"
+dependencies = [
+ "value-bag-serde1",
+ "value-bag-sval2",
+]
+
+[[package]]
+name = "value-bag-serde1"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "35540706617d373b118d550d41f5dfe0b78a0c195dc13c6815e92e2638432306"
+dependencies = [
+ "erased-serde",
+ "serde",
+ "serde_buf",
+ "serde_fmt",
+]
+
+[[package]]
+name = "value-bag-sval2"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "6fe7e140a2658cc16f7ee7a86e413e803fc8f9b5127adc8755c19f9fefa63a52"
+dependencies = [
+ "sval",
+ "sval_buffer",
+ "sval_dynamic",
+ "sval_fmt",
+ "sval_json",
+ "sval_ref",
+ "sval_serde",
+]
+
 [[package]]
 name = "version_check"
 version = "0.9.5"
@@ -2124,7 +2271,7 @@ dependencies = [
  "windows-collections",
  "windows-core",
  "windows-future",
- "windows-link 0.1.1",
+ "windows-link",
  "windows-numerics",
 ]
 
@@ -2145,7 +2292,7 @@ checksum = 
"c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
 dependencies = [
  "windows-implement",
  "windows-interface",
- "windows-link 0.1.1",
+ "windows-link",
  "windows-result",
  "windows-strings",
 ]
@@ -2157,7 +2304,7 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
 dependencies = [
  "windows-core",
- "windows-link 0.1.1",
+ "windows-link",
  "windows-threading",
 ]
 
@@ -2189,12 +2336,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
 
-[[package]]
-name = "windows-link"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
-
 [[package]]
 name = "windows-numerics"
 version = "0.2.0"
@@ -2202,7 +2343,7 @@ source = 
"registry+https://github.com/rust-lang/crates.io-index";
 checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
 dependencies = [
  "windows-core",
- "windows-link 0.1.1",
+ "windows-link",
 ]
 
 [[package]]
@@ -2211,7 +2352,7 @@ version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
 dependencies = [
- "windows-link 0.1.1",
+ "windows-link",
 ]
 
 [[package]]
@@ -2220,7 +2361,7 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
 dependencies = [
- "windows-link 0.1.1",
+ "windows-link",
 ]
 
 [[package]]
@@ -2263,7 +2404,7 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
 dependencies = [
- "windows-link 0.1.1",
+ "windows-link",
 ]
 
 [[package]]
diff --git a/bin/oay/Cargo.toml b/bin/oay/Cargo.toml
index f664e32ab..b0cf4fdfc 100644
--- a/bin/oay/Cargo.toml
+++ b/bin/oay/Cargo.toml
@@ -40,14 +40,14 @@ frontends-webdav = [
 ]
 
 [dependencies]
-anyhow = "1"
-axum = "0.8"
-chrono = "0.4.31"
+anyhow = { version = "1.0.100" }
+axum = { version = "0.8.6" }
 dav-server = { version = "0.8", optional = true }
 dav-server-opendalfs = { version = "0.6.0", path = 
"../../integrations/dav-server", optional = true }
 futures-util = { version = "0.3.29", optional = true }
+jiff = { version = "0.2.15" }
 log = { version = "0.4.27" }
-logforth = { version = "0.27.0", default-features = false }
+logforth = { version = "0.28.1", features = ["starter-log"] }
 opendal = { version = "0.54.0", path = "../../core", features = [
   "services-fs",
 ] }
diff --git a/bin/oay/src/bin/oay.rs b/bin/oay/src/bin/oay.rs
index 703b434f9..ff2f6d3d0 100644
--- a/bin/oay/src/bin/oay.rs
+++ b/bin/oay/src/bin/oay.rs
@@ -34,7 +34,7 @@ async fn main() -> Result<()> {
 }
 
 async fn s3() -> Result<()> {
-    logforth::stderr().apply();
+    logforth::starter_log::stderr().apply();
 
     let cfg: Config =
         toml::from_str(&std::fs::read_to_string("oay.toml").context("failed to 
open oay.toml")?)?;
diff --git a/bin/oay/src/bin/webdav.rs b/bin/oay/src/bin/webdav.rs
index b2975b541..8ba6c1675 100644
--- a/bin/oay/src/bin/webdav.rs
+++ b/bin/oay/src/bin/webdav.rs
@@ -25,7 +25,7 @@ use opendal::services::Fs;
 
 #[tokio::main]
 async fn main() -> Result<()> {
-    logforth::stderr().apply();
+    logforth::starter_log::stderr().apply();
 
     let cfg: Config = Config {
         backend: oay::BackendConfig {
diff --git a/bin/oay/src/services/s3/service.rs 
b/bin/oay/src/services/s3/service.rs
index 01a0d84c3..af314aa37 100644
--- a/bin/oay/src/services/s3/service.rs
+++ b/bin/oay/src/services/s3/service.rs
@@ -24,7 +24,6 @@ use axum::http::StatusCode;
 use axum::response::IntoResponse;
 use axum::response::Response;
 use axum::routing::get;
-use chrono::SecondsFormat;
 use futures_util::StreamExt;
 use opendal::Operator;
 use serde::Deserialize;
@@ -117,10 +116,7 @@ async fn handle_list_objects(
         } else {
             contents.push(Object {
                 key: v.path().to_string(),
-                last_modified: meta
-                    .last_modified()
-                    .unwrap_or_default()
-                    .to_rfc3339_opts(SecondsFormat::Millis, true),
+                last_modified: format!("{:.6}", 
meta.last_modified().unwrap_or_default()),
                 etag: meta.etag().unwrap_or_default().to_string(),
                 size: meta.content_length(),
             });
diff --git a/bin/oli/Cargo.lock b/bin/oli/Cargo.lock
index 5841135f0..a5af6a1fe 100644
--- a/bin/oli/Cargo.lock
+++ b/bin/oli/Cargo.lock
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "addr2line"
@@ -1139,6 +1139,47 @@ version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
 
+[[package]]
+name = "jiff"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
+dependencies = [
+ "jiff-static",
+ "jiff-tzdb-platform",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "jiff-tzdb"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524"
+
+[[package]]
+name = "jiff-tzdb-platform"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
+dependencies = [
+ "jiff-tzdb",
+]
+
 [[package]]
 name = "js-sys"
 version = "0.3.77"
@@ -1386,13 +1427,13 @@ dependencies = [
  "backon",
  "base64",
  "bytes",
- "chrono",
  "crc32c",
  "futures",
  "getrandom 0.2.16",
  "ghac",
  "http",
  "http-body",
+ "jiff",
  "log",
  "md-5",
  "percent-encoding",
@@ -1549,6 +1590,15 @@ version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
 
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
+dependencies = [
+ "portable-atomic",
+]
+
 [[package]]
 name = "potential_utf"
 version = "0.1.2"
diff --git a/bin/oli/tests/integration/test_utils.rs 
b/bin/oli/tests/integration/test_utils.rs
index 69701f7bd..78e0c45aa 100644
--- a/bin/oli/tests/integration/test_utils.rs
+++ b/bin/oli/tests/integration/test_utils.rs
@@ -143,6 +143,10 @@ pub const REPLACEMENTS: &[(&str, &str)] = &[
         r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{9} UTC)",
         "[TIMESTAMP]",
     ),
+    (
+        r"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{9}Z)",
+        "[TIMESTAMP]",
+    ),
 ];
 pub static REPLACEMENT_REGEXS: std::sync::LazyLock<Vec<(regex::Regex, 
String)>> =
     std::sync::LazyLock::new(|| {
diff --git a/bindings/c/src/metadata.rs b/bindings/c/src/metadata.rs
index df381f367..a47407053 100644
--- a/bindings/c/src/metadata.rs
+++ b/bindings/c/src/metadata.rs
@@ -131,7 +131,7 @@ impl opendal_metadata {
         let mtime = self.deref().last_modified();
         match mtime {
             None => -1,
-            Some(time) => time.timestamp_millis(),
+            Some(time) => time.as_millisecond(),
         }
     }
 }
diff --git a/bindings/cpp/Cargo.toml b/bindings/cpp/Cargo.toml
index 50af3560e..e9e5cf69f 100644
--- a/bindings/cpp/Cargo.toml
+++ b/bindings/cpp/Cargo.toml
@@ -30,17 +30,17 @@ rust-version = "1.85"
 crate-type = ["staticlib"]
 
 [dependencies]
-anyhow = "1.0"
-chrono = "0.4"
-cxx = "1.0"
+anyhow = { version = "1.0.100" }
+cxx = { version = "1.0.186" }
 cxx-async = { version = "0.1.3", optional = true }
-futures = "0.3"
+futures = { version = "0.3.31" }
+jiff = { version = "0.2.15" }
 # this crate won't be published, we always use the local version
 opendal = { version = ">=0", path = "../../core", features = ["blocking"] }
 tokio = { version = "1.27", features = ["fs", "macros", "rt-multi-thread"] }
 
 [build-dependencies]
-cxx-build = "1.0"
+cxx-build = { version = "1.0.186" }
 
 [features]
 async = ["cxx-async", "cxx/c++20"]
diff --git a/bindings/cpp/src/types.rs b/bindings/cpp/src/types.rs
index 8182b5aab..2e522bfde 100644
--- a/bindings/cpp/src/types.rs
+++ b/bindings/cpp/src/types.rs
@@ -29,10 +29,7 @@ impl From<od::Metadata> for ffi::Metadata {
         let content_type = meta.content_type().map(ToOwned::to_owned).into();
         let content_encoding = 
meta.content_encoding().map(ToOwned::to_owned).into();
         let etag = meta.etag().map(ToOwned::to_owned).into();
-        let last_modified = meta
-            .last_modified()
-            .map(|time| time.to_rfc3339_opts(chrono::SecondsFormat::Nanos, 
false))
-            .into();
+        let last_modified = meta.last_modified().map(|time| 
time.to_string()).into();
         let version = meta.version().map(ToOwned::to_owned).into();
         let is_current = meta.is_current().into();
         let is_deleted = meta.is_deleted();
diff --git a/bindings/dart/rust/src/api/opendal_api.rs 
b/bindings/dart/rust/src/api/opendal_api.rs
index d9a7fe636..8030abe0b 100644
--- a/bindings/dart/rust/src/api/opendal_api.rs
+++ b/bindings/dart/rust/src/api/opendal_api.rs
@@ -145,6 +145,6 @@ impl Metadata {
     /// We will output this time in RFC3339 format like 
`1996-12-19T16:39:57+08:00`.
     #[frb(sync, getter)]
     pub fn last_modified(&self) -> Option<String> {
-        self.0.last_modified().map(|ta| ta.to_rfc3339())
+        self.0.last_modified().map(|ta| ta.to_string())
     }
 }
diff --git a/bindings/haskell/Cargo.toml b/bindings/haskell/Cargo.toml
index e06dfda9c..8cd44f0f4 100644
--- a/bindings/haskell/Cargo.toml
+++ b/bindings/haskell/Cargo.toml
@@ -31,7 +31,7 @@ crate-type = ["cdylib"]
 doc = false
 
 [dependencies]
-chrono = "0.4"
+jiff = { version = "0.2.15" }
 log = { version = "0.4", features = ["std"] }
 # this crate won't be published, we always use the local version
 opendal = { version = ">=0", path = "../../core", features = [
diff --git a/bindings/haskell/src/types.rs b/bindings/haskell/src/types.rs
index 1d8598b02..0e17c366b 100644
--- a/bindings/haskell/src/types.rs
+++ b/bindings/haskell/src/types.rs
@@ -19,7 +19,6 @@ use std::ffi::CString;
 use std::ffi::c_char;
 
 use ::opendal as od;
-use chrono::SecondsFormat;
 
 #[repr(C)]
 #[derive(Debug)]
@@ -119,7 +118,7 @@ impl From<od::Metadata> for Metadata {
         };
 
         let last_modified = match val.last_modified() {
-            Some(s) => unsafe { 
leak_str(s.to_rfc3339_opts(SecondsFormat::Nanos, false).as_str()) },
+            Some(s) => unsafe { leak_str(s.to_string().as_str()) },
             None => std::ptr::null(),
         };
 
diff --git a/bindings/java/Cargo.toml b/bindings/java/Cargo.toml
index 6c0df7f6e..0d83468ac 100644
--- a/bindings/java/Cargo.toml
+++ b/bindings/java/Cargo.toml
@@ -150,14 +150,14 @@ services-yandex-disk = ["opendal/services-yandex-disk"]
 services-compfs = ["opendal/services-compfs"]
 
 [dependencies]
-anyhow = "1.0.71"
-jni = "0.21.1"
+anyhow = { version = "1.0.100" }
+jiff = { version = "0.2.15" }
+jni = { version = "0.21.1" }
 # this crate won't be published, we always use the local version
 opendal = { version = ">=0", path = "../../core", features = [
   "blocking",
 ] }
 tokio = { version = "1.28.1", features = ["full"] }
-chrono = "0.4"
 
 # This is not optimal. See also the Cargo issue:
 # https://github.com/rust-lang/cargo/issues/1197#issuecomment-1641086954
diff --git a/bindings/java/src/convert.rs b/bindings/java/src/convert.rs
index 841cb1a44..bd0706e4a 100644
--- a/bindings/java/src/convert.rs
+++ b/bindings/java/src/convert.rs
@@ -16,7 +16,7 @@
 // under the License.
 
 use crate::Result;
-use chrono::{DateTime, Utc};
+use jiff::Timestamp;
 use jni::JNIEnv;
 use jni::objects::JObject;
 use jni::objects::JString;
@@ -123,11 +123,11 @@ pub(crate) fn read_jlong_field_to_usize(
     }
 }
 
-pub(crate) fn read_instant_field_to_date_time(
+pub(crate) fn read_instant_field_to_timestamp(
     env: &mut JNIEnv<'_>,
     obj: &JObject,
     field: &str,
-) -> Result<Option<DateTime<Utc>>> {
+) -> Result<Option<Timestamp>> {
     let result = env.get_field(obj, field, "Ljava/time/Instant;")?.l()?;
     if result.is_null() {
         return Ok(None);
@@ -137,15 +137,14 @@ pub(crate) fn read_instant_field_to_date_time(
         .call_method(&result, "getEpochSecond", "()J", &[])?
         .j()?;
     let nano = env.call_method(&result, "getNano", "()I", &[])?.i()?;
-    DateTime::from_timestamp(epoch_second, nano as u32)
-        .map(Some)
-        .ok_or_else(|| {
-            Error::new(
-                ErrorKind::Unexpected,
-                format!("Invalid timestamp: seconds={epoch_second}, 
nanos={nano}"),
-            )
-            .into()
-        })
+    Timestamp::new(epoch_second, nano).map(Some).map_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/bindings/java/src/lib.rs b/bindings/java/src/lib.rs
index d4edac645..027fb5b8b 100644
--- a/bindings/java/src/lib.rs
+++ b/bindings/java/src/lib.rs
@@ -156,8 +156,8 @@ fn make_metadata<'a>(env: &mut JNIEnv<'a>, metadata: 
Metadata) -> Result<JObject
                     "ofEpochSecond",
                     "(JJ)Ljava/time/Instant;",
                     &[
-                        JValue::Long(v.timestamp()),
-                        JValue::Long(v.timestamp_subsec_nanos() as jlong),
+                        JValue::Long(v.as_second()),
+                        JValue::Long(v.subsec_nanosecond() as jlong),
                     ],
                 )?
                 .l()?)
@@ -254,12 +254,12 @@ fn make_stat_options(env: &mut JNIEnv, options: &JObject) 
-> Result<opendal::opt
     Ok(opendal::options::StatOptions {
         if_match: convert::read_string_field(env, options, "ifMatch")?,
         if_none_match: convert::read_string_field(env, options, 
"ifNoneMatch")?,
-        if_modified_since: convert::read_instant_field_to_date_time(
+        if_modified_since: convert::read_instant_field_to_timestamp(
             env,
             options,
             "ifModifiedSince",
         )?,
-        if_unmodified_since: convert::read_instant_field_to_date_time(
+        if_unmodified_since: convert::read_instant_field_to_timestamp(
             env,
             options,
             "ifUnmodifiedSince",
diff --git a/bindings/nodejs/src/lib.rs b/bindings/nodejs/src/lib.rs
index 8faf1026e..736bc1e9e 100644
--- a/bindings/nodejs/src/lib.rs
+++ b/bindings/nodejs/src/lib.rs
@@ -822,7 +822,7 @@ impl Metadata {
     /// We will output this time in RFC3339 format like 
`1996-12-19T16:39:57+08:00`.
     #[napi(getter)]
     pub fn last_modified(&self) -> Option<String> {
-        self.0.last_modified().map(|ta| ta.to_rfc3339())
+        self.0.last_modified().map(|ta| ta.to_string())
     }
 
     /// mode represent this entry's mode.
diff --git a/bindings/ocaml/src/operator/metadata.rs 
b/bindings/ocaml/src/operator/metadata.rs
index 551df21af..5dfb9975e 100644
--- a/bindings/ocaml/src/operator/metadata.rs
+++ b/bindings/ocaml/src/operator/metadata.rs
@@ -62,5 +62,5 @@ pub fn metadata_etag(metadata: &mut Metadata) -> 
Option<String> {
 #[ocaml::func]
 #[ocaml::sig("metadata -> int64 option ")]
 pub fn metadata_last_modified(metadata: &mut Metadata) -> Option<i64> {
-    metadata.0.last_modified().map(|t| t.timestamp())
+    metadata.0.last_modified().map(|t| t.as_second())
 }
diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml
index 0d95e95a7..8aa7ecacd 100644
--- a/bindings/python/Cargo.toml
+++ b/bindings/python/Cargo.toml
@@ -158,15 +158,15 @@ doc = false
 
 [dependencies]
 bytes = "1.5.0"
-chrono = "0.4"
 dict_derive = "0.6.0"
 futures = "0.3.28"
+jiff = { version = "0.2.15" }
 # this crate won't be published, we always use the local version
 opendal = { version = ">=0", path = "../../core", features = [
   "blocking",
   "layers-mime-guess"
 ] }
-pyo3 = { version = "0.26.0", features = ["generate-import-lib", "chrono"] }
+pyo3 = { version = "0.26.0", features = ["generate-import-lib", "jiff-02"] }
 pyo3-async-runtimes = { version = "0.26.0", features = ["tokio-runtime"] }
 tokio = "1"
 
diff --git a/bindings/python/src/metadata.rs b/bindings/python/src/metadata.rs
index f7bdd8a14..c15eb77ba 100644
--- a/bindings/python/src/metadata.rs
+++ b/bindings/python/src/metadata.rs
@@ -15,11 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use chrono::prelude::*;
-use pyo3::prelude::*;
-use std::collections::HashMap;
-
 use crate::*;
+use jiff::Timestamp;
+use std::collections::HashMap;
 
 #[pyclass(module = "opendal")]
 pub struct Entry(ocore::Entry);
@@ -123,7 +121,7 @@ impl Metadata {
 
     /// Last modified time
     #[getter]
-    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
+    pub fn last_modified(&self) -> Option<Timestamp> {
         self.0.last_modified()
     }
 
diff --git a/bindings/python/src/options.rs b/bindings/python/src/options.rs
index 6e242c735..b40226268 100644
--- a/bindings/python/src/options.rs
+++ b/bindings/python/src/options.rs
@@ -16,12 +16,11 @@
 // under the License.
 
 use dict_derive::FromPyObject;
+use jiff::Timestamp;
 use opendal::{self as ocore, raw::BytesRange};
 use pyo3::pyclass;
 use std::collections::HashMap;
 
-use chrono::{DateTime, Utc};
-
 #[pyclass(module = "opendal")]
 #[derive(FromPyObject, Default)]
 pub struct ReadOptions {
@@ -34,8 +33,8 @@ pub struct ReadOptions {
     pub size: Option<usize>,
     pub if_match: Option<String>,
     pub if_none_match: Option<String>,
-    pub if_modified_since: Option<DateTime<Utc>>,
-    pub if_unmodified_since: Option<DateTime<Utc>>,
+    pub if_modified_since: Option<Timestamp>,
+    pub if_unmodified_since: Option<Timestamp>,
     pub content_type: Option<String>,
     pub cache_control: Option<String>,
     pub content_disposition: Option<String>,
@@ -147,8 +146,8 @@ pub struct StatOptions {
     pub version: Option<String>,
     pub if_match: Option<String>,
     pub if_none_match: Option<String>,
-    pub if_modified_since: Option<DateTime<Utc>>,
-    pub if_unmodified_since: Option<DateTime<Utc>>,
+    pub if_modified_since: Option<Timestamp>,
+    pub if_unmodified_since: Option<Timestamp>,
     pub content_type: Option<String>,
     pub cache_control: Option<String>,
     pub content_disposition: Option<String>,
diff --git a/core/Cargo.lock b/core/Cargo.lock
index 6358b81c0..7d1d09700 100644
--- a/core/Cargo.lock
+++ b/core/Cargo.lock
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "Inflector"
@@ -4256,9 +4256,9 @@ dependencies = [
 
 [[package]]
 name = "jiff"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
+checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
 dependencies = [
  "jiff-static",
  "jiff-tzdb-platform",
@@ -4271,9 +4271,9 @@ dependencies = [
 
 [[package]]
 name = "jiff-static"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
+checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5313,7 +5313,6 @@ dependencies = [
  "bb8",
  "bytes",
  "cacache",
- "chrono",
  "compio",
  "crc32c",
  "criterion",
@@ -5336,6 +5335,7 @@ dependencies = [
  "hmac",
  "http 1.3.1",
  "http-body 1.0.1",
+ "jiff",
  "js-sys",
  "libtest-mimic",
  "log",
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 26f0c7542..cede6ede5 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -242,16 +242,13 @@ anyhow = { version = "1.0.100", features = ["std"] }
 backon = { version = "1.5", features = ["tokio-sleep"] }
 base64 = "0.22"
 bytes = "1.6"
-chrono = { version = "0.4.42", default-features = false, features = [
-  "clock",
-  "std",
-] }
 futures = { version = "0.3", default-features = false, features = [
   "std",
   "async-await",
 ] }
 http = "1.1"
 http-body = "1"
+jiff = { version = "0.2.15" }
 log = "0.4"
 md-5 = "0.10"
 percent-encoding = "2"
diff --git a/core/src/lib.rs b/core/src/lib.rs
index f7b490f9d..135b373de 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -181,8 +181,8 @@ mod tests {
     #[test]
     fn assert_size() {
         assert_eq!(16, size_of::<Operator>());
-        assert_eq!(320, size_of::<Entry>());
-        assert_eq!(296, size_of::<Metadata>());
+        assert_eq!(360, size_of::<Entry>());
+        assert_eq!(336, size_of::<Metadata>());
         assert_eq!(1, size_of::<EntryMode>());
         assert_eq!(24, size_of::<Scheme>());
     }
diff --git a/core/src/raw/adapters/typed_kv/api.rs 
b/core/src/raw/adapters/typed_kv/api.rs
index ab5498085..a8cd8f884 100644
--- a/core/src/raw/adapters/typed_kv/api.rs
+++ b/core/src/raw/adapters/typed_kv/api.rs
@@ -15,13 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt::Debug;
-use std::future::Future;
-use std::future::ready;
-use std::mem::size_of;
-
-use chrono::Utc;
-
 use crate::Buffer;
 use crate::EntryMode;
 use crate::Error;
@@ -30,6 +23,11 @@ use crate::Metadata;
 use crate::Result;
 use crate::Scheme;
 use crate::raw::MaybeSend;
+use jiff::Timestamp;
+use std::fmt::Debug;
+use std::future::Future;
+use std::future::ready;
+use std::mem::size_of;
 
 /// Adapter is the typed adapter to underlying kv services.
 ///
@@ -86,7 +84,7 @@ impl Value {
         Self {
             metadata: Metadata::new(EntryMode::DIR)
                 .with_content_length(0)
-                .with_last_modified(Utc::now()),
+                .with_last_modified(Timestamp::now()),
             value: Buffer::new(),
         }
     }
diff --git a/core/src/raw/http_util/header.rs b/core/src/raw/http_util/header.rs
index f9b26bd4a..09adf864c 100644
--- a/core/src/raw/http_util/header.rs
+++ b/core/src/raw/http_util/header.rs
@@ -19,8 +19,6 @@ use std::collections::HashMap;
 
 use base64::Engine;
 use base64::engine::general_purpose;
-use chrono::DateTime;
-use chrono::Utc;
 use http::HeaderMap;
 use http::HeaderName;
 use http::HeaderValue;
@@ -33,6 +31,7 @@ use http::header::CONTENT_TYPE;
 use http::header::ETAG;
 use http::header::LAST_MODIFIED;
 use http::header::LOCATION;
+use jiff::Timestamp;
 use md5::Digest;
 
 use crate::EntryMode;
@@ -94,7 +93,7 @@ pub fn parse_content_range(headers: &HeaderMap) -> 
Result<Option<BytesContentRan
 }
 
 /// Parse last modified from header map.
-pub fn parse_last_modified(headers: &HeaderMap) -> 
Result<Option<DateTime<Utc>>> {
+pub fn parse_last_modified(headers: &HeaderMap) -> Result<Option<Timestamp>> {
     parse_header_to_str(headers, LAST_MODIFIED)?
         .map(parse_datetime_from_rfc2822)
         .transpose()
diff --git a/core/src/raw/chrono_util.rs b/core/src/raw/jiff_util.rs
similarity index 51%
rename from core/src/raw/chrono_util.rs
rename to core/src/raw/jiff_util.rs
index 4d34ee950..9c2b9f75e 100644
--- a/core/src/raw/chrono_util.rs
+++ b/core/src/raw/jiff_util.rs
@@ -15,23 +15,23 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::time::Duration;
-use std::time::UNIX_EPOCH;
-
-use chrono::DateTime;
-use chrono::Utc;
-
 use crate::*;
+use std::time::SystemTime;
+
+use jiff::Timestamp;
 
 /// Parse datetime from rfc2822.
 ///
 /// For example: `Fri, 28 Nov 2014 21:00:09 +0900`
-pub fn parse_datetime_from_rfc2822(s: &str) -> Result<DateTime<Utc>> {
-    DateTime::parse_from_rfc2822(s)
-        .map(|v| v.into())
-        .map_err(|e| {
-            Error::new(ErrorKind::Unexpected, "parse datetime from rfc2822 
failed").set_source(e)
-        })
+pub fn parse_datetime_from_rfc2822(s: &str) -> Result<Timestamp> {
+    match jiff::fmt::rfc2822::parse(s) {
+        Ok(zoned) => Ok(zoned.timestamp()),
+        Err(err) => Err(Error::new(
+            ErrorKind::Unexpected,
+            format!("parse '{s}' from rfc2822 failed"),
+        )
+        .set_source(err)),
+    }
 }
 
 /// Parse datetime from rfc3339.
@@ -41,56 +41,62 @@ pub fn parse_datetime_from_rfc2822(s: &str) -> 
Result<DateTime<Utc>> {
 /// With a time zone:
 ///
 /// ```
-/// use chrono::Datelike;
+/// use jiff::tz::TimeZone;
 /// use opendal::raw::parse_datetime_from_rfc3339;
 /// use opendal::Error;
 ///
 /// let date_time = parse_datetime_from_rfc3339("2014-11-28T21:00:09+09:00")?;
-/// assert_eq!(date_time.date_naive().day(), 28);
+/// assert_eq!(date_time.to_zoned(TimeZone::UTC).day(), 28);
 /// # Ok::<(), Error>(())
 /// ```
 ///
 /// With the UTC offset of 00:00:
 ///
 /// ```
-/// use chrono::Timelike;
-/// # use opendal::Error;
-/// # use opendal::raw::parse_datetime_from_rfc3339;
+/// use jiff::tz::TimeZone;
+/// use opendal::Error;
+/// use opendal::raw::parse_datetime_from_rfc3339;
 ///
 /// let date_time = parse_datetime_from_rfc3339("2014-11-28T21:00:09Z")?;
-/// assert_eq!(date_time.hour(), 21);
+/// assert_eq!(date_time.to_zoned(TimeZone::UTC).hour(), 21);
 /// # Ok::<(), Error>(())
 /// ```
-pub fn parse_datetime_from_rfc3339(s: &str) -> Result<DateTime<Utc>> {
-    DateTime::parse_from_rfc3339(s)
-        .map(|v| v.into())
-        .map_err(|e| {
-            Error::new(ErrorKind::Unexpected, "parse datetime from rfc3339 
failed").set_source(e)
-        })
+pub fn parse_datetime_from_rfc3339(s: &str) -> Result<Timestamp> {
+    match s.parse() {
+        Ok(t) => Ok(t),
+        Err(err) => Err(Error::new(
+            ErrorKind::Unexpected,
+            format!("parse '{s}' into timestamp failed"),
+        )
+        .set_source(err)),
+    }
 }
 
 /// parse datetime from given timestamp_millis
-pub fn parse_datetime_from_from_timestamp_millis(s: i64) -> 
Result<DateTime<Utc>> {
-    let st = UNIX_EPOCH
-        .checked_add(Duration::from_millis(s as u64))
-        .ok_or_else(|| Error::new(ErrorKind::Unexpected, "input timestamp 
overflow"))?;
-
-    Ok(st.into())
+pub fn parse_datetime_from_timestamp_millis(millis: i64) -> Result<Timestamp> {
+    Timestamp::from_millisecond(millis).map_err(|err| {
+        Error::new(ErrorKind::Unexpected, "input timestamp 
overflow").set_source(err)
+    })
 }
 
-/// parse datetime from given timestamp
-pub fn parse_datetime_from_from_timestamp(s: i64) -> Result<DateTime<Utc>> {
-    let st = UNIX_EPOCH
-        .checked_add(Duration::from_secs(s as u64))
-        .ok_or_else(|| Error::new(ErrorKind::Unexpected, "input timestamp 
overflow"))?;
+/// parse datetime from given timestamp_secs
+pub fn parse_datetime_from_timestamp(secs: i64) -> Result<Timestamp> {
+    Timestamp::from_second(secs).map_err(|err| {
+        Error::new(ErrorKind::Unexpected, "input timestamp 
overflow").set_source(err)
+    })
+}
 
-    Ok(st.into())
+/// parse datetime from given system time
+pub fn parse_datetime_from_system_time(t: SystemTime) -> Result<Timestamp> {
+    Timestamp::try_from(t).map_err(|err| {
+        Error::new(ErrorKind::Unexpected, "input timestamp 
overflow").set_source(err)
+    })
 }
 
 /// format datetime into http date, this format is required by:
 /// https://httpwg.org/specs/rfc9110.html#field.if-modified-since
-pub fn format_datetime_into_http_date(s: DateTime<Utc>) -> String {
-    s.format("%a, %d %b %Y %H:%M:%S GMT").to_string()
+pub fn format_datetime_into_http_date(s: Timestamp) -> String {
+    s.strftime("%a, %d %b %Y %H:%M:%S GMT").to_string()
 }
 
 #[cfg(test)]
diff --git a/core/src/raw/mod.rs b/core/src/raw/mod.rs
index 9e5c0f896..22879d3a9 100644
--- a/core/src/raw/mod.rs
+++ b/core/src/raw/mod.rs
@@ -71,8 +71,8 @@ pub use http_util::*;
 mod serde_util;
 pub use serde_util::*;
 
-mod chrono_util;
-pub use chrono_util::*;
+mod jiff_util;
+pub use jiff_util::*;
 
 #[cfg(feature = "internal-tokio-rt")]
 mod tokio_util;
diff --git a/core/src/raw/ops.rs b/core/src/raw/ops.rs
index 416f2fe71..afab131ca 100644
--- a/core/src/raw/ops.rs
+++ b/core/src/raw/ops.rs
@@ -19,14 +19,11 @@
 //!
 //! By using ops, users can add more context for operation.
 
-use std::collections::HashMap;
-use std::time::Duration;
-
-use chrono::DateTime;
-use chrono::Utc;
-
 use crate::options;
 use crate::raw::*;
+use jiff::Timestamp;
+use std::collections::HashMap;
+use std::time::Duration;
 
 /// Args for `create` operation.
 ///
@@ -312,8 +309,8 @@ pub struct OpRead {
     range: BytesRange,
     if_match: Option<String>,
     if_none_match: Option<String>,
-    if_modified_since: Option<DateTime<Utc>>,
-    if_unmodified_since: Option<DateTime<Utc>>,
+    if_modified_since: Option<Timestamp>,
+    if_unmodified_since: Option<Timestamp>,
     override_content_type: Option<String>,
     override_cache_control: Option<String>,
     override_content_disposition: Option<String>,
@@ -399,24 +396,24 @@ impl OpRead {
     }
 
     /// Set the If-Modified-Since of the option
-    pub fn with_if_modified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn with_if_modified_since(mut self, v: Timestamp) -> Self {
         self.if_modified_since = Some(v);
         self
     }
 
     /// Get If-Modified-Since from option
-    pub fn if_modified_since(&self) -> Option<DateTime<Utc>> {
+    pub fn if_modified_since(&self) -> Option<Timestamp> {
         self.if_modified_since
     }
 
     /// Set the If-Unmodified-Since of the option
-    pub fn with_if_unmodified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn with_if_unmodified_since(mut self, v: Timestamp) -> Self {
         self.if_unmodified_since = Some(v);
         self
     }
 
     /// Get If-Unmodified-Since from option
-    pub fn if_unmodified_since(&self) -> Option<DateTime<Utc>> {
+    pub fn if_unmodified_since(&self) -> Option<Timestamp> {
         self.if_unmodified_since
     }
 
@@ -562,8 +559,8 @@ impl From<options::ReaderOptions> for (OpRead, OpReader) {
 pub struct OpStat {
     if_match: Option<String>,
     if_none_match: Option<String>,
-    if_modified_since: Option<DateTime<Utc>>,
-    if_unmodified_since: Option<DateTime<Utc>>,
+    if_modified_since: Option<Timestamp>,
+    if_unmodified_since: Option<Timestamp>,
     override_content_type: Option<String>,
     override_cache_control: Option<String>,
     override_content_disposition: Option<String>,
@@ -599,24 +596,24 @@ impl OpStat {
     }
 
     /// Set the If-Modified-Since of the option
-    pub fn with_if_modified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn with_if_modified_since(mut self, v: Timestamp) -> Self {
         self.if_modified_since = Some(v);
         self
     }
 
     /// Get If-Modified-Since from option
-    pub fn if_modified_since(&self) -> Option<DateTime<Utc>> {
+    pub fn if_modified_since(&self) -> Option<Timestamp> {
         self.if_modified_since
     }
 
     /// Set the If-Unmodified-Since of the option
-    pub fn with_if_unmodified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn with_if_unmodified_since(mut self, v: Timestamp) -> Self {
         self.if_unmodified_since = Some(v);
         self
     }
 
     /// Get If-Unmodified-Since from option
-    pub fn if_unmodified_since(&self) -> Option<DateTime<Utc>> {
+    pub fn if_unmodified_since(&self) -> Option<Timestamp> {
         self.if_unmodified_since
     }
 
diff --git a/core/src/raw/std_io_util.rs b/core/src/raw/std_io_util.rs
index 9bb58d3ea..98510d7c5 100644
--- a/core/src/raw/std_io_util.rs
+++ b/core/src/raw/std_io_util.rs
@@ -26,7 +26,7 @@ use crate::*;
 /// Add `NotADirectory` and `IsADirectory` once they are stable.
 ///
 /// ref: <https://github.com/rust-lang/rust/issues/86442>
-pub fn new_std_io_error(err: std::io::Error) -> Error {
+pub fn new_std_io_error(err: io::Error) -> Error {
     use std::io::ErrorKind::*;
 
     let (kind, retryable) = match err.kind() {
diff --git a/core/src/services/aliyun_drive/backend.rs 
b/core/src/services/aliyun_drive/backend.rs
index dfbc03319..828e49404 100644
--- a/core/src/services/aliyun_drive/backend.rs
+++ b/core/src/services/aliyun_drive/backend.rs
@@ -20,9 +20,9 @@ use std::fmt::Formatter;
 use std::sync::Arc;
 
 use bytes::Buf;
-use chrono::Utc;
 use http::Response;
 use http::StatusCode;
+use jiff::Timestamp;
 use log::debug;
 use tokio::sync::Mutex;
 
@@ -325,22 +325,18 @@ impl Access for AliyunDriveBackend {
 
         if file.path_type == "folder" {
             let meta = Metadata::new(EntryMode::DIR).with_last_modified(
-                file.updated_at
-                    .parse::<chrono::DateTime<Utc>>()
-                    .map_err(|e| {
-                        Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e)
-                    })?,
+                file.updated_at.parse::<Timestamp>().map_err(|e| {
+                    Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e)
+                })?,
             );
 
             return Ok(RpStat::new(meta));
         }
 
         let mut meta = Metadata::new(EntryMode::FILE).with_last_modified(
-            file.updated_at
-                .parse::<chrono::DateTime<Utc>>()
-                .map_err(|e| {
-                    Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e)
-                })?,
+            file.updated_at.parse::<Timestamp>().map_err(|e| {
+                Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e)
+            })?,
         );
         if let Some(v) = file.size {
             meta = meta.with_content_length(v);
diff --git a/core/src/services/aliyun_drive/core.rs 
b/core/src/services/aliyun_drive/core.rs
index 7f2cedfa1..3459c2ffc 100644
--- a/core/src/services/aliyun_drive/core.rs
+++ b/core/src/services/aliyun_drive/core.rs
@@ -19,12 +19,12 @@ use std::fmt::Debug;
 use std::sync::Arc;
 
 use bytes::Buf;
-use chrono::Utc;
 use http::Method;
 use http::Request;
 use http::Response;
 use http::header::HeaderValue;
 use http::header::{self};
+use jiff::Timestamp;
 use serde::Deserialize;
 use serde::Serialize;
 use tokio::sync::Mutex;
@@ -145,14 +145,14 @@ impl AliyunDriveCore {
                 access_token,
                 expire_at,
             ) => {
-                if *expire_at < Utc::now().timestamp() || 
access_token.is_none() {
+                if *expire_at < Timestamp::now().as_second() || 
access_token.is_none() {
                     let res = self
                         .get_access_token(client_id, client_secret, 
refresh_token)
                         .await?;
                     let output: RefreshTokenResponse = 
serde_json::from_reader(res.reader())
                         .map_err(new_json_deserialize_error)?;
                     *access_token = Some(output.access_token);
-                    *expire_at = output.expires_in + Utc::now().timestamp();
+                    *expire_at = output.expires_in + 
Timestamp::now().as_second();
                     *refresh_token = output.refresh_token;
                 }
                 access_token.clone()
diff --git a/core/src/services/aliyun_drive/lister.rs 
b/core/src/services/aliyun_drive/lister.rs
index ed043a6bc..af61b79fe 100644
--- a/core/src/services/aliyun_drive/lister.rs
+++ b/core/src/services/aliyun_drive/lister.rs
@@ -17,9 +17,6 @@
 
 use std::sync::Arc;
 
-use bytes::Buf;
-use chrono::Utc;
-
 use self::oio::Entry;
 use super::core::AliyunDriveCore;
 use super::core::AliyunDriveFileList;
@@ -29,6 +26,8 @@ use crate::ErrorKind;
 use crate::Metadata;
 use crate::Result;
 use crate::raw::*;
+use bytes::Buf;
+use jiff::Timestamp;
 
 pub struct AliyunDriveLister {
     core: Arc<AliyunDriveCore>,
@@ -69,13 +68,9 @@ impl oio::PageList for AliyunDriveLister {
             ctx.entries.push_back(Entry::new(
                 &parent.path,
                 Metadata::new(EntryMode::DIR).with_last_modified(
-                    parent
-                        .updated_at
-                        .parse::<chrono::DateTime<Utc>>()
-                        .map_err(|e| {
-                            Error::new(ErrorKind::Unexpected, "parse last 
modified time")
-                                .set_source(e)
-                        })?,
+                    parent.updated_at.parse::<Timestamp>().map_err(|e| {
+                        Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e)
+                    })?,
                 ),
             ));
             None
@@ -109,9 +104,9 @@ impl oio::PageList for AliyunDriveLister {
                 (path, Metadata::new(EntryMode::FILE))
             };
 
-            md = 
md.with_last_modified(item.updated_at.parse::<chrono::DateTime<Utc>>().map_err(
-                |e| Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e),
-            )?);
+            md = 
md.with_last_modified(item.updated_at.parse::<Timestamp>().map_err(|e| {
+                Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e)
+            })?);
             if let Some(v) = item.size {
                 md = md.with_content_length(v);
             }
diff --git a/core/src/services/alluxio/core.rs 
b/core/src/services/alluxio/core.rs
index 8f9dbbaa7..b9b0590e9 100644
--- a/core/src/services/alluxio/core.rs
+++ b/core/src/services/alluxio/core.rs
@@ -359,7 +359,7 @@ impl TryFrom<FileInfo> for Metadata {
         };
         metadata
             .set_content_length(file_info.length)
-            .set_last_modified(parse_datetime_from_from_timestamp_millis(
+            .set_last_modified(parse_datetime_from_timestamp_millis(
                 file_info.last_modification_time_ms,
             )?);
         Ok(metadata)
diff --git a/core/src/services/b2/core.rs b/core/src/services/b2/core.rs
index 649842835..e429a29b6 100644
--- a/core/src/services/b2/core.rs
+++ b/core/src/services/b2/core.rs
@@ -21,12 +21,11 @@ use std::sync::Arc;
 use std::time::Duration;
 
 use bytes::Buf;
-use chrono::DateTime;
-use chrono::Utc;
 use http::Request;
 use http::Response;
 use http::StatusCode;
 use http::header;
+use jiff::Timestamp;
 use serde::Deserialize;
 use serde::Serialize;
 use tokio::sync::RwLock;
@@ -80,7 +79,7 @@ impl B2Core {
             let signer = self.signer.read().await;
 
             if !signer.auth_info.authorization_token.is_empty()
-                && signer.auth_info.expires_in > Utc::now()
+                && signer.auth_info.expires_in > Timestamp::now()
             {
                 let auth_info = signer.auth_info.clone();
                 return Ok(auth_info);
@@ -114,8 +113,7 @@ impl B2Core {
                         api_url: token.api_url.clone(),
                         download_url: token.download_url.clone(),
                         // This authorization token is valid for at most 24 
hours.
-                        expires_in: Utc::now()
-                            + chrono::TimeDelta::try_hours(20).expect("20 
hours must be valid"),
+                        expires_in: Timestamp::now() + Duration::from_secs(20 
* 60 * 60),
                     };
                 }
                 _ => {
@@ -577,8 +575,8 @@ pub struct AuthInfo {
     pub api_url: String,
     /// The base URL to use for downloading files.
     pub download_url: String,
-
-    pub expires_in: DateTime<Utc>,
+    /// The time when the authorization token expires.
+    pub expires_in: Timestamp,
 }
 
 impl Default for B2Signer {
@@ -591,7 +589,7 @@ impl Default for B2Signer {
                 authorization_token: String::new(),
                 api_url: String::new(),
                 download_url: String::new(),
-                expires_in: DateTime::<Utc>::MIN_UTC,
+                expires_in: Timestamp::MIN,
             },
         }
     }
diff --git a/core/src/services/cacache/backend.rs 
b/core/src/services/cacache/backend.rs
index c3a9b1911..a2b057e77 100644
--- a/core/src/services/cacache/backend.rs
+++ b/core/src/services/cacache/backend.rs
@@ -15,14 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt::Debug;
-use std::sync::Arc;
-
-use chrono::DateTime;
-
 use crate::raw::*;
 use crate::services::CacacheConfig;
 use crate::*;
+use jiff::Timestamp;
+use std::fmt::Debug;
+use std::sync::Arc;
 
 use super::DEFAULT_SCHEME;
 use super::core::CacacheCore;
@@ -109,11 +107,11 @@ impl Access for CacacheAccessor {
             Some(meta) => {
                 let mut md = Metadata::new(EntryMode::FILE);
                 md.set_content_length(meta.size as u64);
-                // Convert u128 milliseconds to DateTime<Utc>
+                // Convert u128 milliseconds to Timestamp
                 let millis = meta.time;
                 let secs = (millis / 1000) as i64;
-                let nanos = ((millis % 1000) * 1_000_000) as u32;
-                if let Some(dt) = DateTime::from_timestamp(secs, nanos) {
+                let nanos = ((millis % 1000) * 1_000_000) as i32;
+                if let Ok(dt) = Timestamp::new(secs, nanos) {
                     md.set_last_modified(dt);
                 }
                 Ok(RpStat::new(md))
diff --git a/core/src/services/cloudflare_kv/backend.rs 
b/core/src/services/cloudflare_kv/backend.rs
index 782076597..4820182d1 100644
--- a/core/src/services/cloudflare_kv/backend.rs
+++ b/core/src/services/cloudflare_kv/backend.rs
@@ -20,9 +20,6 @@ use std::fmt::Formatter;
 use std::sync::Arc;
 use std::time::Duration;
 
-use bytes::Buf;
-use http::StatusCode;
-
 use super::DEFAULT_SCHEME;
 use crate::ErrorKind;
 use crate::raw::*;
@@ -34,6 +31,9 @@ use 
crate::services::cloudflare_kv::lister::CloudflareKvLister;
 use crate::services::cloudflare_kv::model::*;
 use crate::services::cloudflare_kv::writer::CloudflareWriter;
 use crate::*;
+use bytes::Buf;
+use http::StatusCode;
+use jiff::Timestamp;
 
 impl Configurator for CloudflareKvConfig {
     type Builder = CloudflareKvBuilder;
@@ -249,7 +249,7 @@ impl Access for CloudflareKvAccessor {
             // Create metadata for current directory
             let cf_kv_metadata = CfKvMetadata {
                 etag: build_tmp_path_of(&current_path),
-                last_modified: chrono::Local::now().to_rfc3339(),
+                last_modified: Timestamp::now().to_string(),
                 content_length: 0,
                 is_dir: true,
             };
@@ -348,7 +348,9 @@ impl Access for CloudflareKvAccessor {
         }
 
         // Parse since time once for both time-based conditions
-        let last_modified = 
chrono::DateTime::parse_from_rfc3339(&metadata.last_modified)
+        let last_modified = metadata
+            .last_modified
+            .parse::<Timestamp>()
             .map_err(|_| Error::new(ErrorKind::Unsupported, "invalid since 
format"))?;
 
         // Check modified_since condition
@@ -437,7 +439,9 @@ impl Access for CloudflareKvAccessor {
             }
 
             // Parse since time once for both time-based conditions
-            let last_modified = 
chrono::DateTime::parse_from_rfc3339(&metadata.last_modified)
+            let last_modified = metadata
+                .last_modified
+                .parse::<Timestamp>()
                 .map_err(|_| Error::new(ErrorKind::Unsupported, "invalid since 
format"))?;
 
             // Check modified_since condition
diff --git a/core/src/services/cloudflare_kv/writer.rs 
b/core/src/services/cloudflare_kv/writer.rs
index b21b7152d..1a3e422bc 100644
--- a/core/src/services/cloudflare_kv/writer.rs
+++ b/core/src/services/cloudflare_kv/writer.rs
@@ -17,13 +17,13 @@
 
 use std::sync::Arc;
 
-use http::StatusCode;
-
 use super::core::CloudflareKvCore;
 use super::error::parse_error;
 use crate::raw::*;
 use crate::services::cloudflare_kv::model::CfKvMetadata;
 use crate::*;
+use http::StatusCode;
+use jiff::Timestamp;
 
 pub struct CloudflareWriter {
     core: Arc<CloudflareKvCore>,
@@ -40,7 +40,7 @@ impl oio::OneShotWrite for CloudflareWriter {
     async fn write_once(&self, bs: Buffer) -> Result<Metadata> {
         let cf_kv_metadata = CfKvMetadata {
             etag: build_tmp_path_of(&self.path),
-            last_modified: chrono::Local::now().to_rfc3339(),
+            last_modified: Timestamp::now().to_string(),
             content_length: bs.len(),
             is_dir: self.path.ends_with('/'),
         };
diff --git a/core/src/services/compfs/backend.rs 
b/core/src/services/compfs/backend.rs
index 6fb2a692e..906fcab66 100644
--- a/core/src/services/compfs/backend.rs
+++ b/core/src/services/compfs/backend.rs
@@ -152,7 +152,6 @@ impl Access for CompfsBackend {
 
     async fn stat(&self, path: &str, _: OpStat) -> Result<RpStat> {
         let path = self.core.prepare_path(path);
-
         let meta = self
             .core
             .exec(move || async move { compio::fs::metadata(path).await })
@@ -165,11 +164,10 @@ impl Access for CompfsBackend {
         } else {
             EntryMode::Unknown
         };
-        let last_mod = meta.modified().map_err(new_std_io_error)?.into();
+        let last_mod = 
parse_datetime_from_system_time(meta.modified().map_err(new_std_io_error)?)?;
         let ret = Metadata::new(mode)
             .with_last_modified(last_mod)
             .with_content_length(meta.len());
-
         Ok(RpStat::new(ret))
     }
 
diff --git a/core/src/services/dashmap/writer.rs 
b/core/src/services/dashmap/writer.rs
index ebc0bf3d2..e641a33b4 100644
--- a/core/src/services/dashmap/writer.rs
+++ b/core/src/services/dashmap/writer.rs
@@ -20,7 +20,7 @@ use std::time::SystemTime;
 
 use super::core::DashmapCore;
 use super::core::DashmapValue;
-use crate::raw::{OpWrite, oio};
+use crate::raw::{OpWrite, oio, parse_datetime_from_system_time};
 use crate::*;
 
 pub struct DashmapWriter {
@@ -54,7 +54,7 @@ impl oio::Write for DashmapWriter {
         let entry_mode = EntryMode::from_path(&self.path);
         let mut meta = Metadata::new(entry_mode);
         meta.set_content_length(content.len() as u64);
-        meta.set_last_modified(SystemTime::now().into());
+        
meta.set_last_modified(parse_datetime_from_system_time(SystemTime::now())?);
 
         if let Some(v) = self.op.content_type() {
             meta.set_content_type(v);
diff --git a/core/src/services/dbfs/backend.rs 
b/core/src/services/dbfs/backend.rs
index 599c4be4c..2541dcfab 100644
--- a/core/src/services/dbfs/backend.rs
+++ b/core/src/services/dbfs/backend.rs
@@ -195,7 +195,7 @@ impl Access for DbfsBackend {
                 let bs = resp.into_body();
                 let decoded_response: DbfsStatus =
                     
serde_json::from_reader(bs.reader()).map_err(new_json_deserialize_error)?;
-                
meta.set_last_modified(parse_datetime_from_from_timestamp_millis(
+                meta.set_last_modified(parse_datetime_from_timestamp_millis(
                     decoded_response.modification_time,
                 )?);
                 match decoded_response.is_dir {
diff --git a/core/src/services/dbfs/lister.rs b/core/src/services/dbfs/lister.rs
index 077c2a658..2f5cc4cb9 100644
--- a/core/src/services/dbfs/lister.rs
+++ b/core/src/services/dbfs/lister.rs
@@ -62,14 +62,14 @@ impl oio::PageList for DbfsLister {
                 true => {
                     let normalized_path = format!("{}/", &status.path);
                     let mut meta = Metadata::new(EntryMode::DIR);
-                    
meta.set_last_modified(parse_datetime_from_from_timestamp_millis(
+                    
meta.set_last_modified(parse_datetime_from_timestamp_millis(
                         status.modification_time,
                     )?);
                     oio::Entry::new(&normalized_path, meta)
                 }
                 false => {
                     let mut meta = Metadata::new(EntryMode::FILE);
-                    
meta.set_last_modified(parse_datetime_from_from_timestamp_millis(
+                    
meta.set_last_modified(parse_datetime_from_timestamp_millis(
                         status.modification_time,
                     )?);
                     meta.set_content_length(status.file_size as u64);
diff --git a/core/src/services/dropbox/builder.rs 
b/core/src/services/dropbox/builder.rs
index b561047b0..549459f6a 100644
--- a/core/src/services/dropbox/builder.rs
+++ b/core/src/services/dropbox/builder.rs
@@ -15,12 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use jiff::Timestamp;
 use std::fmt::Debug;
 use std::fmt::Formatter;
 use std::sync::Arc;
-
-use chrono::DateTime;
-use chrono::Utc;
 use tokio::sync::Mutex;
 
 use super::DEFAULT_SCHEME;
@@ -135,7 +133,7 @@ impl Builder for DropboxBuilder {
             (Some(access_token), None) => DropboxSigner {
                 access_token,
                 // We will never expire user specified token.
-                expires_in: DateTime::<Utc>::MAX_UTC,
+                expires_in: Timestamp::MAX,
                 ..Default::default()
             },
             (None, Some(refresh_token)) => {
diff --git a/core/src/services/dropbox/core.rs 
b/core/src/services/dropbox/core.rs
index 1f92a5cfd..b6c59978a 100644
--- a/core/src/services/dropbox/core.rs
+++ b/core/src/services/dropbox/core.rs
@@ -15,23 +15,22 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::default::Default;
-use std::fmt::Debug;
-use std::fmt::Formatter;
-use std::sync::Arc;
-
 use bytes::Buf;
 use bytes::Bytes;
-use chrono::DateTime;
-use chrono::Utc;
 use http::Request;
 use http::Response;
 use http::StatusCode;
 use http::header;
 use http::header::CONTENT_LENGTH;
 use http::header::CONTENT_TYPE;
+use jiff::Timestamp;
 use serde::Deserialize;
 use serde::Serialize;
+use std::default::Default;
+use std::fmt::Debug;
+use std::fmt::Formatter;
+use std::sync::Arc;
+use std::time::Duration;
 use tokio::sync::Mutex;
 
 use super::error::parse_error;
@@ -64,7 +63,7 @@ impl DropboxCore {
         let mut signer = self.signer.lock().await;
 
         // Access token is valid, use it directly.
-        if !signer.access_token.is_empty() && signer.expires_in > Utc::now() {
+        if !signer.access_token.is_empty() && signer.expires_in > 
Timestamp::now() {
             let value = format!("Bearer {}", signer.access_token)
                 .parse()
                 .expect("token must be valid header value");
@@ -97,10 +96,8 @@ impl DropboxCore {
         signer.access_token.clone_from(&token.access_token);
 
         // Refresh it 2 minutes earlier.
-        signer.expires_in = Utc::now()
-            + chrono::TimeDelta::try_seconds(token.expires_in as i64)
-                .expect("expires_in must be valid seconds")
-            - chrono::TimeDelta::try_seconds(120).expect("120 must be valid 
seconds");
+        signer.expires_in =
+            Timestamp::now() + Duration::from_secs(token.expires_in) - 
Duration::from_secs(120);
 
         let value = format!("Bearer {}", token.access_token)
             .parse()
@@ -343,7 +340,7 @@ pub struct DropboxSigner {
     pub refresh_token: String,
 
     pub access_token: String,
-    pub expires_in: DateTime<Utc>,
+    pub expires_in: Timestamp,
 }
 
 impl Default for DropboxSigner {
@@ -354,7 +351,7 @@ impl Default for DropboxSigner {
             client_secret: String::new(),
 
             access_token: String::new(),
-            expires_in: DateTime::<Utc>::MIN_UTC,
+            expires_in: Timestamp::MIN,
         }
     }
 }
@@ -430,7 +427,7 @@ struct DropboxMetadataArgs {
 #[derive(Clone, Deserialize)]
 struct DropboxTokenResponse {
     access_token: String,
-    expires_in: usize,
+    expires_in: u64,
 }
 
 #[derive(Default, Debug, Deserialize)]
diff --git a/core/src/services/fs/core.rs b/core/src/services/fs/core.rs
index 822cb42b3..46d731eef 100644
--- a/core/src/services/fs/core.rs
+++ b/core/src/services/fs/core.rs
@@ -20,8 +20,6 @@ use std::path::Path;
 use std::path::PathBuf;
 use std::sync::Arc;
 
-use chrono::DateTime;
-
 use super::error::*;
 use crate::raw::*;
 use crate::*;
@@ -74,7 +72,6 @@ impl FsCore {
     pub async fn fs_stat(&self, path: &str) -> Result<Metadata> {
         let p = self.root.join(path.trim_end_matches('/'));
         let meta = tokio::fs::metadata(&p).await.map_err(new_std_io_error)?;
-
         let mode = if meta.is_dir() {
             EntryMode::DIR
         } else if meta.is_file() {
@@ -84,12 +81,9 @@ impl FsCore {
         };
         let m = Metadata::new(mode)
             .with_content_length(meta.len())
-            .with_last_modified(
-                meta.modified()
-                    .map(DateTime::from)
-                    .map_err(new_std_io_error)?,
-            );
-
+            .with_last_modified(parse_datetime_from_system_time(
+                meta.modified().map_err(new_std_io_error)?,
+            )?);
         Ok(m)
     }
 
diff --git a/core/src/services/fs/writer.rs b/core/src/services/fs/writer.rs
index ff4e3ba34..38c4c2f3e 100644
--- a/core/src/services/fs/writer.rs
+++ b/core/src/services/fs/writer.rs
@@ -107,7 +107,9 @@ impl oio::Write for FsWriter {
         let file_meta = self.f.metadata().await.map_err(new_std_io_error)?;
         let meta = Metadata::new(EntryMode::FILE)
             .with_content_length(file_meta.len())
-            
.with_last_modified(file_meta.modified().map_err(new_std_io_error)?.into());
+            .with_last_modified(parse_datetime_from_system_time(
+                file_meta.modified().map_err(new_std_io_error)?,
+            )?);
         Ok(meta)
     }
 
@@ -181,7 +183,9 @@ impl oio::PositionWrite for FsWriter {
         };
         let meta = Metadata::new(mode)
             .with_content_length(file_meta.len())
-            
.with_last_modified(file_meta.modified().map_err(new_std_io_error)?.into());
+            .with_last_modified(parse_datetime_from_system_time(
+                file_meta.modified().map_err(new_std_io_error)?,
+            )?);
         Ok(meta)
     }
 
diff --git a/core/src/services/ftp/backend.rs b/core/src/services/ftp/backend.rs
index ee942f9a1..660e6e873 100644
--- a/core/src/services/ftp/backend.rs
+++ b/core/src/services/ftp/backend.rs
@@ -258,7 +258,7 @@ impl Access for FtpBackend {
 
         let mut meta = Metadata::new(mode);
         meta.set_content_length(file.size() as u64);
-        meta.set_last_modified(file.modified().into());
+        
meta.set_last_modified(parse_datetime_from_system_time(file.modified())?);
 
         Ok(RpStat::new(meta))
     }
diff --git a/core/src/services/ftp/lister.rs b/core/src/services/ftp/lister.rs
index 6dedc8f45..a7fd77085 100644
--- a/core/src/services/ftp/lister.rs
+++ b/core/src/services/ftp/lister.rs
@@ -57,7 +57,7 @@ impl oio::List for FtpLister {
             Metadata::new(EntryMode::Unknown)
         };
         meta.set_content_length(de.size() as u64);
-        meta.set_last_modified(de.modified().into());
+        
meta.set_last_modified(parse_datetime_from_system_time(de.modified())?);
 
         let entry = if de.is_file() {
             oio::Entry::new(&path, meta)
diff --git a/core/src/services/gdrive/backend.rs 
b/core/src/services/gdrive/backend.rs
index 777e06887..df5bc659c 100644
--- a/core/src/services/gdrive/backend.rs
+++ b/core/src/services/gdrive/backend.rs
@@ -18,11 +18,6 @@
 use std::fmt::Debug;
 use std::sync::Arc;
 
-use bytes::Buf;
-use chrono::Utc;
-use http::Response;
-use http::StatusCode;
-
 use super::core::GdriveCore;
 use super::core::GdriveFile;
 use super::delete::GdriveDeleter;
@@ -31,6 +26,10 @@ use super::lister::GdriveLister;
 use super::writer::GdriveWriter;
 use crate::raw::*;
 use crate::*;
+use bytes::Buf;
+use http::Response;
+use http::StatusCode;
+use jiff::Timestamp;
 
 #[derive(Clone, Debug)]
 pub struct GdriveBackend {
@@ -77,7 +76,7 @@ impl Access for GdriveBackend {
             })?);
         }
         if let Some(v) = gdrive_file.modified_time {
-            meta = 
meta.with_last_modified(v.parse::<chrono::DateTime<Utc>>().map_err(|e| {
+            meta = meta.with_last_modified(v.parse::<Timestamp>().map_err(|e| {
                 Error::new(ErrorKind::Unexpected, "parse last modified 
time").set_source(e)
             })?);
         }
diff --git a/core/src/services/gdrive/builder.rs 
b/core/src/services/gdrive/builder.rs
index ea985df3b..dc5a0946b 100644
--- a/core/src/services/gdrive/builder.rs
+++ b/core/src/services/gdrive/builder.rs
@@ -15,13 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use jiff::Timestamp;
+use log::debug;
 use std::fmt::Debug;
 use std::fmt::Formatter;
 use std::sync::Arc;
-
-use chrono::DateTime;
-use chrono::Utc;
-use log::debug;
 use tokio::sync::Mutex;
 
 use super::DEFAULT_SCHEME;
@@ -175,7 +173,7 @@ impl Builder for GdriveBuilder {
             (Some(access_token), None) => {
                 signer.access_token = access_token;
                 // We will never expire user specified access token.
-                signer.expires_in = DateTime::<Utc>::MAX_UTC;
+                signer.expires_in = Timestamp::MAX;
             }
             (None, Some(refresh_token)) => {
                 let client_id = self.config.client_id.ok_or_else(|| {
diff --git a/core/src/services/gdrive/core.rs b/core/src/services/gdrive/core.rs
index e59914e70..82354dd67 100644
--- a/core/src/services/gdrive/core.rs
+++ b/core/src/services/gdrive/core.rs
@@ -15,21 +15,20 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt::Debug;
-use std::fmt::Formatter;
-use std::sync::Arc;
-
 use bytes;
 use bytes::Buf;
 use bytes::Bytes;
-use chrono::DateTime;
-use chrono::Utc;
 use http::Request;
 use http::Response;
 use http::StatusCode;
 use http::header;
+use jiff::Timestamp;
 use serde::Deserialize;
 use serde_json::json;
+use std::fmt::Debug;
+use std::fmt::Formatter;
+use std::sync::Arc;
+use std::time::Duration;
 use tokio::sync::Mutex;
 
 use super::error::parse_error;
@@ -304,7 +303,7 @@ pub struct GdriveSigner {
     pub refresh_token: String,
 
     pub access_token: String,
-    pub expires_in: DateTime<Utc>,
+    pub expires_in: Timestamp,
 }
 
 impl GdriveSigner {
@@ -317,13 +316,13 @@ impl GdriveSigner {
             client_secret: "".to_string(),
             refresh_token: "".to_string(),
             access_token: "".to_string(),
-            expires_in: DateTime::<Utc>::MIN_UTC,
+            expires_in: Timestamp::MIN,
         }
     }
 
     /// Sign a request.
     pub async fn sign<T>(&mut self, req: &mut Request<T>) -> Result<()> {
-        if !self.access_token.is_empty() && self.expires_in > Utc::now() {
+        if !self.access_token.is_empty() && self.expires_in > Timestamp::now() 
{
             let value = format!("Bearer {}", self.access_token)
                 .parse()
                 .expect("access token must be valid header value");
@@ -352,10 +351,8 @@ impl GdriveSigner {
                     let token: GdriveTokenResponse = 
serde_json::from_reader(resp_body.reader())
                         .map_err(new_json_deserialize_error)?;
                     self.access_token.clone_from(&token.access_token);
-                    self.expires_in = Utc::now()
-                        + chrono::TimeDelta::try_seconds(token.expires_in)
-                            .expect("expires_in must be valid seconds")
-                        - chrono::TimeDelta::try_seconds(120).expect("120 must 
be valid seconds");
+                    self.expires_in = Timestamp::now() + 
Duration::from_secs(token.expires_in)
+                        - Duration::from_secs(120);
                 }
                 _ => {
                     return Err(parse_error(resp));
@@ -469,7 +466,7 @@ impl PathQuery for GdrivePathQuery {
 #[derive(Deserialize)]
 pub struct GdriveTokenResponse {
     access_token: String,
-    expires_in: i64,
+    expires_in: u64,
 }
 
 /// This is the file struct returned by the Google Drive API.
diff --git a/core/src/services/github/core.rs b/core/src/services/github/core.rs
index 37b496b60..944cd0fd9 100644
--- a/core/src/services/github/core.rs
+++ b/core/src/services/github/core.rs
@@ -27,6 +27,7 @@ use http::Response;
 use http::StatusCode;
 use http::header;
 use http::request;
+use jiff::Timestamp;
 use serde::Deserialize;
 use serde::Serialize;
 
@@ -174,7 +175,7 @@ impl GithubCore {
         let req = self.sign(req)?;
 
         let mut req_body = CreateOrUpdateContentsRequest {
-            message: format!("Write {} at {} via opendal", path, 
chrono::Local::now()),
+            message: format!("Write {} at {} via opendal", path, 
Timestamp::now()),
             content: 
base64::engine::general_purpose::STANDARD.encode(bs.to_bytes()),
             sha: None,
         };
@@ -222,7 +223,7 @@ impl GithubCore {
         let req = self.sign(req)?;
 
         let req_body = DeleteContentsRequest {
-            message: format!("Delete {} at {} via opendal", path, 
chrono::Local::now()),
+            message: format!("Delete {} at {} via opendal", path, 
Timestamp::now()),
             sha,
         };
 
diff --git a/core/src/services/hdfs/backend.rs 
b/core/src/services/hdfs/backend.rs
index 083e1a762..22555cee2 100644
--- a/core/src/services/hdfs/backend.rs
+++ b/core/src/services/hdfs/backend.rs
@@ -249,7 +249,7 @@ impl Access for HdfsBackend {
         };
         let mut m = Metadata::new(mode);
         m.set_content_length(meta.len());
-        m.set_last_modified(meta.modified().into());
+        m.set_last_modified(parse_datetime_from_system_time(meta.modified())?);
 
         Ok(RpStat::new(m))
     }
diff --git a/core/src/services/hdfs/lister.rs b/core/src/services/hdfs/lister.rs
index 60f53c1b7..7d83ead57 100644
--- a/core/src/services/hdfs/lister.rs
+++ b/core/src/services/hdfs/lister.rs
@@ -56,7 +56,7 @@ impl oio::List for HdfsLister {
         let entry = if de.is_file() {
             let meta = Metadata::new(EntryMode::FILE)
                 .with_content_length(de.len())
-                .with_last_modified(de.modified().into());
+                
.with_last_modified(parse_datetime_from_system_time(de.modified())?);
             oio::Entry::new(&path, meta)
         } else if de.is_dir() {
             // Make sure we are returning the correct path.
diff --git a/core/src/services/hdfs_native/backend.rs 
b/core/src/services/hdfs_native/backend.rs
index dd69c344e..39c41824d 100644
--- a/core/src/services/hdfs_native/backend.rs
+++ b/core/src/services/hdfs_native/backend.rs
@@ -205,7 +205,7 @@ impl Access for HdfsNativeBackend {
 
         let mut metadata = Metadata::new(mode);
         metadata
-            .set_last_modified(parse_datetime_from_from_timestamp_millis(
+            .set_last_modified(parse_datetime_from_timestamp_millis(
                 status.modification_time as i64,
             )?)
             .set_content_length(status.length as u64);
diff --git a/core/src/services/hdfs_native/lister.rs 
b/core/src/services/hdfs_native/lister.rs
index 21bda41bf..af18b658d 100644
--- a/core/src/services/hdfs_native/lister.rs
+++ b/core/src/services/hdfs_native/lister.rs
@@ -22,7 +22,7 @@ use crate::Metadata;
 use crate::Result;
 use crate::raw::build_rel_path;
 use crate::raw::oio;
-use crate::raw::parse_datetime_from_from_timestamp_millis;
+use crate::raw::parse_datetime_from_timestamp_millis;
 use crate::services::hdfs_native::error::parse_hdfs_error;
 
 pub struct HdfsNativeLister {
@@ -67,7 +67,7 @@ impl oio::List for HdfsNativeLister {
                 } else {
                     let meta = Metadata::new(EntryMode::FILE)
                         .with_content_length(status.length as u64)
-                        
.with_last_modified(parse_datetime_from_from_timestamp_millis(
+                        
.with_last_modified(parse_datetime_from_timestamp_millis(
                             status.modification_time as i64,
                         )?);
                     oio::Entry::new(&path, meta)
diff --git a/core/src/services/koofr/backend.rs 
b/core/src/services/koofr/backend.rs
index 1458504d5..a56cf7b85 100644
--- a/core/src/services/koofr/backend.rs
+++ b/core/src/services/koofr/backend.rs
@@ -265,7 +265,7 @@ impl Access for KoofrBackend {
 
                 md.set_content_length(file.size)
                     .set_content_type(&file.content_type)
-                    
.set_last_modified(parse_datetime_from_from_timestamp_millis(file.modified)?);
+                    
.set_last_modified(parse_datetime_from_timestamp_millis(file.modified)?);
 
                 Ok(RpStat::new(md))
             }
diff --git a/core/src/services/koofr/lister.rs 
b/core/src/services/koofr/lister.rs
index 8369c62ec..88642aa78 100644
--- a/core/src/services/koofr/lister.rs
+++ b/core/src/services/koofr/lister.rs
@@ -74,7 +74,7 @@ impl oio::PageList for KoofrLister {
                 let m = Metadata::new(EntryMode::FILE)
                     .with_content_length(file.size)
                     .with_content_type(file.content_type)
-                    
.with_last_modified(parse_datetime_from_from_timestamp_millis(file.modified)?);
+                    
.with_last_modified(parse_datetime_from_timestamp_millis(file.modified)?);
                 Entry::new(&path, m)
             };
 
diff --git a/core/src/services/lakefs/backend.rs 
b/core/src/services/lakefs/backend.rs
index 1c1613c20..f4802e843 100644
--- a/core/src/services/lakefs/backend.rs
+++ b/core/src/services/lakefs/backend.rs
@@ -20,10 +20,9 @@ use std::fmt::Formatter;
 use std::sync::Arc;
 
 use bytes::Buf;
-use chrono::TimeZone;
-use chrono::Utc;
 use http::Response;
 use http::StatusCode;
+use jiff::Timestamp;
 use log::debug;
 
 use super::DEFAULT_SCHEME;
@@ -242,7 +241,7 @@ impl Access for LakefsBackend {
                     meta.set_content_disposition(v);
                 }
 
-                
meta.set_last_modified(Utc.timestamp_opt(decoded_response.mtime, 0).unwrap());
+                
meta.set_last_modified(Timestamp::from_second(decoded_response.mtime).unwrap());
 
                 Ok(RpStat::new(meta))
             }
diff --git a/core/src/services/lakefs/lister.rs 
b/core/src/services/lakefs/lister.rs
index 3dc426384..e73a26473 100644
--- a/core/src/services/lakefs/lister.rs
+++ b/core/src/services/lakefs/lister.rs
@@ -17,15 +17,13 @@
 
 use std::sync::Arc;
 
-use bytes::Buf;
-use chrono::TimeZone;
-use chrono::Utc;
-
 use super::core::LakefsCore;
 use super::core::LakefsListResponse;
 use super::error::parse_error;
 use crate::raw::*;
 use crate::*;
+use bytes::Buf;
+use jiff::Timestamp;
 
 pub struct LakefsLister {
     core: Arc<LakefsCore>,
@@ -94,7 +92,7 @@ impl oio::PageList for LakefsLister {
             let mut meta = Metadata::new(entry_type);
 
             if status.mtime != 0 {
-                meta.set_last_modified(Utc.timestamp_opt(status.mtime, 
0).unwrap());
+                
meta.set_last_modified(Timestamp::from_second(status.mtime).unwrap());
             }
 
             if entry_type == EntryMode::FILE {
diff --git a/core/src/services/mini_moka/writer.rs 
b/core/src/services/mini_moka/writer.rs
index a751d444b..5e5c12b13 100644
--- a/core/src/services/mini_moka/writer.rs
+++ b/core/src/services/mini_moka/writer.rs
@@ -15,12 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::sync::Arc;
-
 use super::core::{MiniMokaCore, MiniMokaValue};
 use crate::raw::oio;
 use crate::raw::*;
 use crate::*;
+use jiff::Timestamp;
+use std::sync::Arc;
 
 pub struct MiniMokaWriter {
     core: Arc<MiniMokaCore>,
@@ -51,7 +51,7 @@ impl oio::Write for MiniMokaWriter {
 
         let mut md = Metadata::new(EntryMode::from_path(&self.path));
         md.set_content_length(buf.len() as u64);
-        md.set_last_modified(chrono::Utc::now());
+        md.set_last_modified(Timestamp::now());
 
         // Set metadata from OpWrite
         if let Some(content_type) = self.op.content_type() {
diff --git a/core/src/services/monoiofs/backend.rs 
b/core/src/services/monoiofs/backend.rs
index 114ed1907..217714217 100644
--- a/core/src/services/monoiofs/backend.rs
+++ b/core/src/services/monoiofs/backend.rs
@@ -15,14 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use monoio::fs::OpenOptions;
 use std::fmt::Debug;
 use std::io;
 use std::path::PathBuf;
 use std::sync::Arc;
 
-use chrono::DateTime;
-use monoio::fs::OpenOptions;
-
 use super::core::BUFFER_SIZE;
 use super::core::MonoiofsCore;
 use super::delete::MonoiofsDeleter;
@@ -126,11 +124,9 @@ impl Access for MonoiofsBackend {
         };
         let m = Metadata::new(mode)
             .with_content_length(meta.len())
-            .with_last_modified(
-                meta.modified()
-                    .map(DateTime::from)
-                    .map_err(new_std_io_error)?,
-            );
+            .with_last_modified(parse_datetime_from_system_time(
+                meta.modified().map_err(new_std_io_error)?,
+            )?);
         Ok(RpStat::new(m))
     }
 
diff --git a/core/src/services/monoiofs/writer.rs 
b/core/src/services/monoiofs/writer.rs
index df0272a8a..e4172e561 100644
--- a/core/src/services/monoiofs/writer.rs
+++ b/core/src/services/monoiofs/writer.rs
@@ -20,7 +20,6 @@ use std::sync::Arc;
 
 use bytes::Buf;
 use bytes::Bytes;
-use chrono::DateTime;
 use futures::SinkExt;
 use futures::StreamExt;
 use futures::channel::mpsc;
@@ -171,12 +170,9 @@ impl oio::Write for MonoiofsWriter {
         };
         let meta = Metadata::new(mode)
             .with_content_length(file_meta.len())
-            .with_last_modified(
-                file_meta
-                    .modified()
-                    .map(DateTime::from)
-                    .map_err(new_std_io_error)?,
-            );
+            .with_last_modified(parse_datetime_from_system_time(
+                file_meta.modified().map_err(new_std_io_error)?,
+            )?);
         Ok(meta)
     }
 
diff --git a/core/src/services/onedrive/builder.rs 
b/core/src/services/onedrive/builder.rs
index d8e5071a6..35be2cbbb 100644
--- a/core/src/services/onedrive/builder.rs
+++ b/core/src/services/onedrive/builder.rs
@@ -15,15 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::fmt::Debug;
-use std::fmt::Formatter;
-use std::sync::Arc;
-
-use chrono::DateTime;
-use chrono::Utc;
+use jiff::Timestamp;
 use log::debug;
 use services::onedrive::core::OneDriveCore;
 use services::onedrive::core::OneDriveSigner;
+use std::fmt::Debug;
+use std::fmt::Formatter;
+use std::sync::Arc;
 use tokio::sync::Mutex;
 
 use super::DEFAULT_SCHEME;
@@ -192,7 +190,7 @@ impl Builder for OnedriveBuilder {
         match (self.config.access_token, self.config.refresh_token) {
             (Some(access_token), None) => {
                 signer.access_token = access_token;
-                signer.expires_in = DateTime::<Utc>::MAX_UTC;
+                signer.expires_in = Timestamp::MAX;
             }
             (None, Some(refresh_token)) => {
                 let client_id = self.config.client_id.ok_or_else(|| {
diff --git a/core/src/services/onedrive/core.rs 
b/core/src/services/onedrive/core.rs
index d62e88d96..07cb7746c 100644
--- a/core/src/services/onedrive/core.rs
+++ b/core/src/services/onedrive/core.rs
@@ -22,12 +22,11 @@ use std::time::Duration;
 
 use bytes::Buf;
 use bytes::Bytes;
-use chrono::DateTime;
-use chrono::Utc;
 use http::Request;
 use http::Response;
 use http::StatusCode;
 use http::header;
+use jiff::Timestamp;
 use tokio::sync::Mutex;
 
 use super::error::parse_error;
@@ -55,7 +54,8 @@ const SPECIAL_POSIX_ENTRIES: [&str; 3] = [".", "/", ""];
 // organizes a few core module functions
 impl OneDriveCore {
     // OneDrive personal's base URL. `me` is an alias that represents the 
user's "Drive".
-    pub(crate) const DRIVE_ROOT_URL: &str = 
"https://graph.microsoft.com/v1.0/me/drive/root";;
+    pub(crate) const DRIVE_ROOT_URL: &'static str =
+        "https://graph.microsoft.com/v1.0/me/drive/root";;
 
     /// Get a URL to an OneDrive item
     pub(crate) fn onedrive_item_url(&self, path: &str, build_absolute_path: 
bool) -> String {
@@ -608,7 +608,7 @@ pub struct OneDriveSigner {
     pub refresh_token: String,
 
     pub access_token: String,
-    pub expires_in: DateTime<Utc>,
+    pub expires_in: Timestamp,
 }
 
 // OneDrive is part of Graph API hence shares the same authentication and 
authorization processes.
@@ -629,7 +629,7 @@ impl OneDriveSigner {
             client_secret: "".to_string(),
             refresh_token: "".to_string(),
             access_token: "".to_string(),
-            expires_in: DateTime::<Utc>::MIN_UTC,
+            expires_in: Timestamp::MIN,
         }
     }
 
@@ -655,10 +655,8 @@ impl OneDriveSigner {
                         .map_err(new_json_deserialize_error)?;
                 self.access_token = data.access_token;
                 self.refresh_token = data.refresh_token;
-                self.expires_in = Utc::now()
-                    + chrono::TimeDelta::try_seconds(data.expires_in)
-                        .expect("expires_in must be valid seconds")
-                    - chrono::TimeDelta::minutes(2); // assumes 2 mins 
graceful transmission for implementation simplicity
+                self.expires_in = Timestamp::now() + 
Duration::from_secs(data.expires_in)
+                    - Duration::from_secs(120); // assumes 2 mins graceful 
transmission for implementation simplicity
                 Ok(())
             }
             _ => Err(parse_error(response)),
@@ -667,7 +665,7 @@ impl OneDriveSigner {
 
     /// Sign a request.
     pub async fn sign<T>(&mut self, request: &mut Request<T>) -> Result<()> {
-        if !self.access_token.is_empty() && self.expires_in > Utc::now() {
+        if !self.access_token.is_empty() && self.expires_in > Timestamp::now() 
{
             let value = format!("Bearer {}", self.access_token)
                 .parse()
                 .expect("access_token must be valid header value");
diff --git a/core/src/services/onedrive/graph_model.rs 
b/core/src/services/onedrive/graph_model.rs
index 87a98b077..3fe407c0a 100644
--- a/core/src/services/onedrive/graph_model.rs
+++ b/core/src/services/onedrive/graph_model.rs
@@ -22,7 +22,7 @@ use serde::Serialize;
 pub struct GraphOAuthRefreshTokenResponseBody {
     pub access_token: String,
     pub refresh_token: String,
-    pub expires_in: i64, // in seconds
+    pub expires_in: u64, // in seconds
 }
 
 /// We `$select` some fields when sending GET requests.
diff --git a/core/src/services/seafile/lister.rs 
b/core/src/services/seafile/lister.rs
index 58d948b82..e1720cde9 100644
--- a/core/src/services/seafile/lister.rs
+++ b/core/src/services/seafile/lister.rs
@@ -57,7 +57,7 @@ impl oio::PageList for SeafileLister {
 
                         let entry = if info.type_field == "file" {
                             let meta = Metadata::new(EntryMode::FILE)
-                                
.with_last_modified(parse_datetime_from_from_timestamp(info.mtime)?)
+                                
.with_last_modified(parse_datetime_from_timestamp(info.mtime)?)
                                 .with_content_length(info.size.unwrap_or(0));
                             Entry::new(&rel_path, meta)
                         } else {
diff --git a/core/src/services/sftp/utils.rs b/core/src/services/sftp/utils.rs
index f30c84233..96f9fa9a1 100644
--- a/core/src/services/sftp/utils.rs
+++ b/core/src/services/sftp/utils.rs
@@ -19,6 +19,7 @@ use openssh_sftp_client::metadata::MetaData as SftpMeta;
 
 use crate::EntryMode;
 use crate::Metadata;
+use crate::raw::parse_datetime_from_system_time;
 
 /// REMOVE ME: we should not implement `From<SftpMeta> for Metadata`.
 impl From<SftpMeta> for Metadata {
@@ -43,7 +44,9 @@ impl From<SftpMeta> for Metadata {
         }
 
         if let Some(modified) = meta.modified() {
-            metadata.set_last_modified(modified.as_system_time().into());
+            if let Ok(m) = 
parse_datetime_from_system_time(modified.as_system_time()) {
+                metadata.set_last_modified(m);
+            }
         }
 
         metadata
diff --git a/core/src/services/upyun/core.rs b/core/src/services/upyun/core.rs
index b6dc4c2ee..881fdf2d5 100644
--- a/core/src/services/upyun/core.rs
+++ b/core/src/services/upyun/core.rs
@@ -26,6 +26,7 @@ use http::HeaderMap;
 use http::Request;
 use http::Response;
 use http::header;
+use jiff::Timestamp;
 use md5::Digest;
 use serde::Deserialize;
 use sha1::Sha1;
@@ -86,8 +87,8 @@ impl UpyunCore {
 
     pub fn sign(&self, req: &mut Request<Buffer>) -> Result<()> {
         // get rfc1123 date
-        let date = chrono::Utc::now()
-            .format("%a, %d %b %Y %H:%M:%S GMT")
+        let date = Timestamp::now()
+            .strftime("%a, %d %b %Y %H:%M:%S GMT")
             .to_string();
         let authorization =
             self.signer
diff --git a/core/src/services/upyun/lister.rs 
b/core/src/services/upyun/lister.rs
index b93687c18..d86249bc4 100644
--- a/core/src/services/upyun/lister.rs
+++ b/core/src/services/upyun/lister.rs
@@ -89,7 +89,7 @@ impl oio::PageList for UpyunLister {
                 let m = Metadata::new(EntryMode::FILE)
                     .with_content_length(file.length)
                     .with_content_type(file.type_field)
-                    
.with_last_modified(parse_datetime_from_from_timestamp(file.last_modified)?);
+                    
.with_last_modified(parse_datetime_from_timestamp(file.last_modified)?);
                 Entry::new(&path, m)
             };
 
diff --git a/core/src/services/webhdfs/backend.rs 
b/core/src/services/webhdfs/backend.rs
index 38503ef1a..3ec8cba29 100644
--- a/core/src/services/webhdfs/backend.rs
+++ b/core/src/services/webhdfs/backend.rs
@@ -310,7 +310,7 @@ impl Access for WebhdfsBackend {
                     FileStatusType::Directory => Metadata::new(EntryMode::DIR),
                     FileStatusType::File => Metadata::new(EntryMode::FILE)
                         .with_content_length(file_status.length)
-                        
.with_last_modified(parse_datetime_from_from_timestamp_millis(
+                        
.with_last_modified(parse_datetime_from_timestamp_millis(
                             file_status.modification_time,
                         )?),
                 };
diff --git a/core/src/services/webhdfs/lister.rs 
b/core/src/services/webhdfs/lister.rs
index 1d8228d79..dae855e79 100644
--- a/core/src/services/webhdfs/lister.rs
+++ b/core/src/services/webhdfs/lister.rs
@@ -110,7 +110,7 @@ impl oio::PageList for WebhdfsLister {
                 FileStatusType::Directory => Metadata::new(EntryMode::DIR),
                 FileStatusType::File => Metadata::new(EntryMode::FILE)
                     .with_content_length(status.length)
-                    
.with_last_modified(parse_datetime_from_from_timestamp_millis(
+                    .with_last_modified(parse_datetime_from_timestamp_millis(
                         status.modification_time,
                     )?),
             };
diff --git a/core/src/types/metadata.rs b/core/src/types/metadata.rs
index fab17dbeb..d09a481fe 100644
--- a/core/src/types/metadata.rs
+++ b/core/src/types/metadata.rs
@@ -15,12 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::collections::HashMap;
-
-use chrono::prelude::*;
-
 use crate::raw::*;
 use crate::*;
+use jiff::Timestamp;
+use std::collections::HashMap;
 
 /// Metadata contains all the information related to a specific path.
 ///
@@ -62,7 +60,7 @@ pub struct Metadata {
     content_type: Option<String>,
     content_encoding: Option<String>,
     etag: Option<String>,
-    last_modified: Option<DateTime<Utc>>,
+    last_modified: Option<Timestamp>,
     version: Option<String>,
 
     user_metadata: Option<HashMap<String, String>>,
@@ -321,18 +319,18 @@ impl Metadata {
     /// `Last-Modified` is defined by [RFC 
7232](https://httpwg.org/specs/rfc7232.html#header.last-modified)
     ///
     /// Refer to [MDN 
Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)
 for more information.
-    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
+    pub fn last_modified(&self) -> Option<Timestamp> {
         self.last_modified
     }
 
     /// Set Last modified of this entry.
-    pub fn set_last_modified(&mut self, v: DateTime<Utc>) -> &mut Self {
+    pub fn set_last_modified(&mut self, v: Timestamp) -> &mut Self {
         self.last_modified = Some(v);
         self
     }
 
     /// Set Last modified of this entry.
-    pub fn with_last_modified(mut self, v: DateTime<Utc>) -> Self {
+    pub fn with_last_modified(mut self, v: Timestamp) -> Self {
         self.last_modified = Some(v);
         self
     }
diff --git a/core/src/types/operator/operator_futures.rs 
b/core/src/types/operator/operator_futures.rs
index 1fcb46e25..f761316b2 100644
--- a/core/src/types/operator/operator_futures.rs
+++ b/core/src/types/operator/operator_futures.rs
@@ -24,12 +24,10 @@ use std::future::IntoFuture;
 use std::ops::RangeBounds;
 use std::time::Duration;
 
-use chrono::DateTime;
-use chrono::Utc;
-use futures::Future;
-
 use crate::raw::*;
 use crate::*;
+use futures::Future;
+use jiff::Timestamp;
 
 /// OperatorFuture is the future generated by [`Operator`].
 ///
@@ -107,7 +105,7 @@ impl<F: Future<Output = Result<Metadata>>> FutureStat<F> {
     /// Set the If-Modified-Since for this operation.
     ///
     /// Refer to [`options::StatOptions::if_modified_since`] for more details.
-    pub fn if_modified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn if_modified_since(mut self, v: Timestamp) -> Self {
         self.args.if_modified_since = Some(v);
         self
     }
@@ -115,7 +113,7 @@ impl<F: Future<Output = Result<Metadata>>> FutureStat<F> {
     /// Set the If-Unmodified-Since for this operation.
     ///
     /// Refer to [`options::StatOptions::if_unmodified_since`] for more 
details.
-    pub fn if_unmodified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn if_unmodified_since(mut self, v: Timestamp) -> Self {
         self.args.if_unmodified_since = Some(v);
         self
     }
@@ -385,15 +383,14 @@ impl<F: Future<Output = Result<Buffer>>> FutureRead<F> {
     ///
     /// ```
     /// # use opendal::Result;
-    /// use chrono::DateTime;
-    /// use chrono::Utc;
+    /// use jiff::Timestamp;
     /// use opendal::Operator;
-    /// # async fn test(op: Operator, time: DateTime<Utc>) -> Result<()> {
+    /// # async fn test(op: Operator, time: Timestamp) -> Result<()> {
     /// let mut metadata = 
op.read_with("path/to/file").if_modified_since(time).await?;
     /// # Ok(())
     /// # }
     /// ```
-    pub fn if_modified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn if_modified_since(mut self, v: Timestamp) -> Self {
         self.args.if_modified_since = Some(v);
         self
     }
@@ -407,10 +404,9 @@ impl<F: Future<Output = Result<Buffer>>> FutureRead<F> {
     ///
     /// ```
     /// # use opendal::Result;
-    /// use chrono::DateTime;
-    /// use chrono::Utc;
+    /// use jiff::Timestamp;
     /// use opendal::Operator;
-    /// # async fn test(op: Operator, time: DateTime<Utc>) -> Result<()> {
+    /// # async fn test(op: Operator, time: Timestamp) -> Result<()> {
     /// let mut metadata = op
     ///     .read_with("path/to/file")
     ///     .if_unmodified_since(time)
@@ -418,7 +414,7 @@ impl<F: Future<Output = Result<Buffer>>> FutureRead<F> {
     /// # Ok(())
     /// # }
     /// ```
-    pub fn if_unmodified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn if_unmodified_since(mut self, v: Timestamp) -> Self {
         self.args.if_unmodified_since = Some(v);
         self
     }
@@ -579,10 +575,9 @@ impl<F: Future<Output = Result<Reader>>> FutureReader<F> {
     ///
     /// ```
     /// # use opendal::Result;
-    /// use chrono::DateTime;
-    /// use chrono::Utc;
+    /// use jiff::Timestamp;
     /// use opendal::Operator;
-    /// # async fn test(op: Operator, time: DateTime<Utc>) -> Result<()> {
+    /// # async fn test(op: Operator, time: Timestamp) -> Result<()> {
     /// let mut r = op
     ///     .reader_with("path/to/file")
     ///     .if_modified_since(time)
@@ -590,7 +585,7 @@ impl<F: Future<Output = Result<Reader>>> FutureReader<F> {
     /// # Ok(())
     /// # }
     /// ```
-    pub fn if_modified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn if_modified_since(mut self, v: Timestamp) -> Self {
         self.args.if_modified_since = Some(v);
         self
     }
@@ -604,10 +599,9 @@ impl<F: Future<Output = Result<Reader>>> FutureReader<F> {
     ///
     /// ```
     /// # use opendal::Result;
-    /// use chrono::DateTime;
-    /// use chrono::Utc;
+    /// use jiff::Timestamp;
     /// use opendal::Operator;
-    /// # async fn test(op: Operator, time: DateTime<Utc>) -> Result<()> {
+    /// # async fn test(op: Operator, time: Timestamp) -> Result<()> {
     /// let mut r = op
     ///     .reader_with("path/to/file")
     ///     .if_unmodified_since(time)
@@ -615,7 +609,7 @@ impl<F: Future<Output = Result<Reader>>> FutureReader<F> {
     /// # Ok(())
     /// # }
     /// ```
-    pub fn if_unmodified_since(mut self, v: DateTime<Utc>) -> Self {
+    pub fn if_unmodified_since(mut self, v: Timestamp) -> Self {
         self.args.if_unmodified_since = Some(v);
         self
     }
diff --git a/core/src/types/options.rs b/core/src/types/options.rs
index 81863366d..e754e6d40 100644
--- a/core/src/types/options.rs
+++ b/core/src/types/options.rs
@@ -17,12 +17,9 @@
 
 //! Options module provides options definitions for operations.
 
-use std::collections::HashMap;
-
-use chrono::DateTime;
-use chrono::Utc;
-
 use crate::raw::BytesRange;
+use jiff::Timestamp;
+use std::collections::HashMap;
 
 /// Options for delete operations.
 #[derive(Debug, Clone, Default, Eq, PartialEq)]
@@ -108,14 +105,14 @@ pub struct ReadOptions {
     ///
     /// If file exists and it hasn't been modified since the specified time, 
an error with kind
     /// [`ErrorKind::ConditionNotMatch`] will be returned.
-    pub if_modified_since: Option<DateTime<Utc>>,
+    pub if_modified_since: Option<Timestamp>,
     /// Set `if_unmodified_since` for this operation.
     ///
     /// This feature can be used to check if the file hasn't been modified 
since the given timestamp.
     ///
     /// If file exists and it has been modified since the specified time, an 
error with kind
     /// [`ErrorKind::ConditionNotMatch`] will be returned.
-    pub if_unmodified_since: Option<DateTime<Utc>>,
+    pub if_unmodified_since: Option<Timestamp>,
 
     /// Set `concurrent` for the operation.
     ///
@@ -192,14 +189,14 @@ pub struct ReaderOptions {
     ///
     /// If file exists and it hasn't been modified since the specified time, 
an error with kind
     /// [`ErrorKind::ConditionNotMatch`] will be returned.
-    pub if_modified_since: Option<DateTime<Utc>>,
+    pub if_modified_since: Option<Timestamp>,
     /// Set `if_unmodified_since` for this operation.
     ///
     /// This feature can be used to check if the file hasn't been modified 
since the given timestamp.
     ///
     /// If file exists and it has been modified since the specified time, an 
error with kind
     /// [`ErrorKind::ConditionNotMatch`] will be returned.
-    pub if_unmodified_since: Option<DateTime<Utc>>,
+    pub if_unmodified_since: Option<Timestamp>,
 
     /// Set `concurrent` for the operation.
     ///
@@ -277,14 +274,14 @@ pub struct StatOptions {
     ///
     /// If file exists and it hasn't been modified since the specified time, 
an error with kind
     /// [`ErrorKind::ConditionNotMatch`] will be returned.
-    pub if_modified_since: Option<DateTime<Utc>>,
+    pub if_modified_since: Option<Timestamp>,
     /// Set `if_unmodified_since` for this operation.
     ///
     /// This feature can be used to check if the file hasn't been modified 
since the given timestamp.
     ///
     /// If file exists and it has been modified since the specified time, an 
error with kind
     /// [`ErrorKind::ConditionNotMatch`] will be returned.
-    pub if_unmodified_since: Option<DateTime<Utc>>,
+    pub if_unmodified_since: Option<Timestamp>,
 
     /// Specify the content-type header that should be sent back by the 
operation.
     ///
diff --git a/core/tests/behavior/async_read.rs 
b/core/tests/behavior/async_read.rs
index e79f3b22f..78c5eff23 100644
--- a/core/tests/behavior/async_read.rs
+++ b/core/tests/behavior/async_read.rs
@@ -288,14 +288,14 @@ pub async fn test_reader_with_if_modified_since(op: 
Operator) -> anyhow::Result<
         .expect("write must succeed");
     let last_modified_time = op.stat(&path).await?.last_modified().unwrap();
 
-    let since = last_modified_time - chrono::Duration::seconds(1);
+    let since = last_modified_time - Duration::from_secs(1);
     let reader = op.reader_with(&path).if_modified_since(since).await?;
     let bs = reader.read(..).await?.to_bytes();
     assert_eq!(bs, content);
 
     sleep(Duration::from_secs(1)).await;
 
-    let since = last_modified_time + chrono::Duration::seconds(1);
+    let since = last_modified_time + Duration::from_secs(1);
     let reader = op.reader_with(&path).if_modified_since(since).await?;
     let res = reader.read(..).await;
     assert!(res.is_err());
@@ -317,7 +317,7 @@ pub async fn test_reader_with_if_unmodified_since(op: 
Operator) -> anyhow::Resul
         .expect("write must succeed");
     let last_modified_time = op.stat(&path).await?.last_modified().unwrap();
 
-    let since = last_modified_time - chrono::Duration::seconds(1);
+    let since = last_modified_time - Duration::from_secs(1);
     let reader = op.reader_with(&path).if_unmodified_since(since).await?;
     let res = reader.read(..).await;
     assert!(res.is_err());
@@ -325,7 +325,7 @@ pub async fn test_reader_with_if_unmodified_since(op: 
Operator) -> anyhow::Resul
 
     sleep(Duration::from_secs(1)).await;
 
-    let since = last_modified_time + chrono::Duration::seconds(1);
+    let since = last_modified_time + Duration::from_secs(1);
     let reader = op.reader_with(&path).if_unmodified_since(since).await?;
     let bs = reader.read(..).await?.to_bytes();
     assert_eq!(bs, content);
@@ -565,7 +565,7 @@ pub async fn test_read_with_if_modified_since(op: Operator) 
-> anyhow::Result<()
         .expect("write must succeed");
     let last_modified_time = op.stat(&path).await?.last_modified().unwrap();
 
-    let since = last_modified_time - chrono::Duration::seconds(1);
+    let since = last_modified_time - Duration::from_secs(1);
     let bs = op
         .read_with(&path)
         .if_modified_since(since)
@@ -575,7 +575,7 @@ pub async fn test_read_with_if_modified_since(op: Operator) 
-> anyhow::Result<()
 
     sleep(Duration::from_secs(1)).await;
 
-    let since = last_modified_time + chrono::Duration::seconds(1);
+    let since = last_modified_time + Duration::from_secs(1);
     let res = op.read_with(&path).if_modified_since(since).await;
     assert!(res.is_err());
     assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
@@ -596,14 +596,14 @@ pub async fn test_read_with_if_unmodified_since(op: 
Operator) -> anyhow::Result<
         .expect("write must succeed");
     let last_modified = op.stat(&path).await?.last_modified().unwrap();
 
-    let since = last_modified - chrono::Duration::seconds(3600);
+    let since = last_modified - Duration::from_secs(3600);
     let res = op.read_with(&path).if_unmodified_since(since).await;
     assert!(res.is_err());
     assert_eq!(res.unwrap_err().kind(), ErrorKind::ConditionNotMatch);
 
     sleep(Duration::from_secs(1)).await;
 
-    let since = last_modified + chrono::Duration::seconds(1);
+    let since = last_modified + Duration::from_secs(1);
     let bs = op
         .read_with(&path)
         .if_unmodified_since(since)
diff --git a/integrations/cloud_filter/src/lib.rs 
b/integrations/cloud_filter/src/lib.rs
index dde66ac3f..6e635f0cb 100644
--- a/integrations/cloud_filter/src/lib.rs
+++ b/integrations/cloud_filter/src/lib.rs
@@ -231,7 +231,7 @@ impl Filter for CloudFilter {
                             .size(metadata.content_length())
                             .written(
                                 FileTime::from_unix_time(
-                                    
metadata.last_modified().unwrap_or_default().timestamp(),
+                                    
metadata.last_modified().unwrap_or_default().as_second(),
                                 )
                                 .expect("valid time"),
                             )
diff --git a/integrations/object_store/Cargo.toml 
b/integrations/object_store/Cargo.toml
index 236d5417a..d1f91f6c5 100644
--- a/integrations/object_store/Cargo.toml
+++ b/integrations/object_store/Cargo.toml
@@ -39,7 +39,9 @@ path = "tests/behavior/main.rs"
 [dependencies]
 async-trait = "0.1"
 bytes = "1"
+chrono = { version = "0.4.42", features = ["std", "clock"] }
 futures = "0.3"
+jiff = { version = "0.2.15 "}
 object_store = "0.12.3"
 opendal = { version = "0.54.0", path = "../../core", default-features = false }
 pin-project = "1.1"
diff --git a/integrations/object_store/src/lib.rs 
b/integrations/object_store/src/lib.rs
index 9671bedd7..983612882 100644
--- a/integrations/object_store/src/lib.rs
+++ b/integrations/object_store/src/lib.rs
@@ -97,3 +97,11 @@ mod assert_send {
         assert_send(store.list_with_delimiter(None));
     }
 }
+
+fn timestamp_to_datetime(ts: jiff::Timestamp) -> 
Option<chrono::DateTime<chrono::Utc>> {
+    chrono::DateTime::<chrono::Utc>::from_timestamp(ts.as_second(), 
ts.subsec_nanosecond() as u32)
+}
+
+fn datetime_to_timestamp(dt: chrono::DateTime<chrono::Utc>) -> 
Option<jiff::Timestamp> {
+    jiff::Timestamp::new(dt.timestamp(), dt.timestamp_subsec_nanos() as 
i32).ok()
+}
diff --git a/integrations/object_store/src/service/core.rs 
b/integrations/object_store/src/service/core.rs
index bfcf61d66..6c7f9443d 100644
--- a/integrations/object_store/src/service/core.rs
+++ b/integrations/object_store/src/service/core.rs
@@ -15,13 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::borrow::Cow;
-
+use crate::{datetime_to_timestamp, timestamp_to_datetime};
 use object_store::{
     Attribute, AttributeValue, GetOptions, GetRange, ObjectMeta, PutOptions, 
PutResult,
 };
 use opendal::raw::*;
 use opendal::*;
+use std::borrow::Cow;
 
 /// Parse OpStat arguments to object_store GetOptions for head requests
 pub fn parse_op_stat(args: &OpStat) -> Result<GetOptions> {
@@ -43,11 +43,11 @@ pub fn parse_op_stat(args: &OpStat) -> Result<GetOptions> {
     }
 
     if let Some(if_modified_since) = args.if_modified_since() {
-        options.if_modified_since = Some(if_modified_since);
+        options.if_modified_since = timestamp_to_datetime(if_modified_since);
     }
 
     if let Some(if_unmodified_since) = args.if_unmodified_since() {
-        options.if_unmodified_since = Some(if_unmodified_since);
+        options.if_unmodified_since = 
timestamp_to_datetime(if_unmodified_since);
     }
 
     Ok(options)
@@ -70,11 +70,11 @@ pub fn parse_op_read(args: &OpRead) -> Result<GetOptions> {
     }
 
     if let Some(if_modified_since) = args.if_modified_since() {
-        options.if_modified_since = Some(if_modified_since);
+        options.if_modified_since = timestamp_to_datetime(if_modified_since);
     }
 
     if let Some(if_unmodified_since) = args.if_unmodified_since() {
-        options.if_unmodified_since = Some(if_unmodified_since);
+        options.if_unmodified_since = 
timestamp_to_datetime(if_unmodified_since);
     }
 
     if !args.range().is_full() {
@@ -152,7 +152,9 @@ pub fn format_put_result(result: PutResult) -> Metadata {
 pub fn format_metadata(meta: &ObjectMeta) -> Metadata {
     let mut metadata = Metadata::new(EntryMode::FILE);
     metadata.set_content_length(meta.size);
-    metadata.set_last_modified(meta.last_modified);
+    if let Some(last_modified) = datetime_to_timestamp(meta.last_modified) {
+        metadata.set_last_modified(last_modified);
+    }
     if let Some(etag) = &meta.e_tag {
         metadata.set_etag(etag);
     }
diff --git a/integrations/object_store/src/store.rs 
b/integrations/object_store/src/store.rs
index ec1374bc0..177ce72d5 100644
--- a/integrations/object_store/src/store.rs
+++ b/integrations/object_store/src/store.rs
@@ -21,6 +21,7 @@ use std::io;
 use std::sync::Arc;
 
 use crate::utils::*;
+use crate::{datetime_to_timestamp, timestamp_to_datetime};
 use async_trait::async_trait;
 use futures::FutureExt;
 use futures::StreamExt;
@@ -317,10 +318,14 @@ impl ObjectStore for OpendalStore {
             if let Some(if_none_match) = &options.if_none_match {
                 s = s.if_none_match(if_none_match.as_str());
             }
-            if let Some(if_modified_since) = options.if_modified_since {
+            if let Some(if_modified_since) =
+                options.if_modified_since.and_then(datetime_to_timestamp)
+            {
                 s = s.if_modified_since(if_modified_since);
             }
-            if let Some(if_unmodified_since) = options.if_unmodified_since {
+            if let Some(if_unmodified_since) =
+                options.if_unmodified_since.and_then(datetime_to_timestamp)
+            {
                 s = s.if_unmodified_since(if_unmodified_since);
             }
             s.into_send()
@@ -341,7 +346,10 @@ impl ObjectStore for OpendalStore {
 
         let meta = ObjectMeta {
             location: location.clone(),
-            last_modified: meta.last_modified().unwrap_or_default(),
+            last_modified: meta
+                .last_modified()
+                .and_then(timestamp_to_datetime)
+                .unwrap_or_default(),
             size: meta.content_length(),
             e_tag: meta.etag().map(|x| x.to_string()),
             version: meta.version().map(|x| x.to_string()),
@@ -367,10 +375,14 @@ impl ObjectStore for OpendalStore {
             if let Some(if_none_match) = options.if_none_match {
                 r = r.if_none_match(if_none_match.as_str());
             }
-            if let Some(if_modified_since) = options.if_modified_since {
+            if let Some(if_modified_since) =
+                options.if_modified_since.and_then(datetime_to_timestamp)
+            {
                 r = r.if_modified_since(if_modified_since);
             }
-            if let Some(if_unmodified_since) = options.if_unmodified_since {
+            if let Some(if_unmodified_since) =
+                options.if_unmodified_since.and_then(datetime_to_timestamp)
+            {
                 r = r.if_unmodified_since(if_unmodified_since);
             }
             r.into_send()
diff --git a/integrations/object_store/src/utils.rs 
b/integrations/object_store/src/utils.rs
index 34a511227..efce4d601 100644
--- a/integrations/object_store/src/utils.rs
+++ b/integrations/object_store/src/utils.rs
@@ -20,6 +20,7 @@ use object_store::ObjectMeta;
 use opendal::Metadata;
 use std::future::IntoFuture;
 
+use crate::timestamp_to_datetime;
 /// Conditionally add the `Send` marker trait for the wrapped type.
 /// Only take effect when the `send_wrapper` feature is enabled.
 #[cfg(not(feature = "send_wrapper"))]
@@ -57,7 +58,10 @@ pub fn format_object_store_error(err: opendal::Error, path: 
&str) -> object_stor
 pub fn format_object_meta(path: &str, meta: &Metadata) -> ObjectMeta {
     ObjectMeta {
         location: path.into(),
-        last_modified: meta.last_modified().unwrap_or_default(),
+        last_modified: meta
+            .last_modified()
+            .and_then(timestamp_to_datetime)
+            .unwrap_or_default(),
         size: meta.content_length(),
         e_tag: meta.etag().map(|x| x.to_string()),
         version: meta.version().map(|x| x.to_string()),

Reply via email to