You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by ti...@apache.org on 2025/10/10 06:34:51 UTC

(opendal) 01/01: chore: migrate chrono to jiff

This is an automated email from the ASF dual-hosted git repository.

tison pushed a commit to branch chrono-to-jiff
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit c0e8bcca28de00df93db344a53f05b03837fe48c
Author: tison <wa...@gmail.com>
AuthorDate: Fri Oct 10 14:28:14 2025 +0800

    chore: migrate chrono to jiff
    
    Signed-off-by: tison <wa...@gmail.com>
---
 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          |   1 -
 bindings/cpp/Cargo.toml                     |  10 +-
 bindings/cpp/src/types.rs                   |   5 +-
 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/python/Cargo.toml                  |   2 +-
 bindings/python/src/metadata.rs             |   7 +-
 bindings/python/src/options.rs              |  11 +-
 core/Cargo.lock                             |  12 +-
 core/Cargo.toml                             |   5 +-
 core/src/raw/adapters/typed_kv/api.rs       |  14 +-
 core/src/raw/chrono_util.rs                 |  72 ++++---
 core/src/raw/http_util/header.rs            |   5 +-
 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/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         |   5 +-
 core/src/services/dashmap/writer.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/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/sftp/utils.rs             |   5 +-
 core/src/services/upyun/core.rs             |   5 +-
 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 +-
 57 files changed, 511 insertions(+), 427 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..3d5b4c497 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;
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/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/python/Cargo.toml b/bindings/python/Cargo.toml
index 0d95e95a7..88a3d59e6 100644
--- a/bindings/python/Cargo.toml
+++ b/bindings/python/Cargo.toml
@@ -158,9 +158,9 @@ 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",
diff --git a/bindings/python/src/metadata.rs b/bindings/python/src/metadata.rs
index f7bdd8a14..2fc9c35ef 100644
--- a/bindings/python/src/metadata.rs
+++ b/bindings/python/src/metadata.rs
@@ -15,12 +15,11 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use chrono::prelude::*;
+use crate::*;
+use jiff::Timestamp;
 use pyo3::prelude::*;
 use std::collections::HashMap;
 
-use crate::*;
-
 #[pyclass(module = "opendal")]
 pub struct Entry(ocore::Entry);
 
@@ -123,7 +122,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/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/chrono_util.rs b/core/src/raw/chrono_util.rs
index 4d34ee950..05695b0df 100644
--- a/core/src/raw/chrono_util.rs
+++ b/core/src/raw/chrono_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,7 +41,6 @@ pub fn parse_datetime_from_rfc2822(s: &str) -> Result<DateTime<Utc>> {
 /// With a time zone:
 ///
 /// ```
-/// use chrono::Datelike;
 /// use opendal::raw::parse_datetime_from_rfc3339;
 /// use opendal::Error;
 ///
@@ -53,7 +52,6 @@ pub fn parse_datetime_from_rfc2822(s: &str) -> Result<DateTime<Utc>> {
 /// With the UTC offset of 00:00:
 ///
 /// ```
-/// use chrono::Timelike;
 /// # use opendal::Error;
 /// # use opendal::raw::parse_datetime_from_rfc3339;
 ///
@@ -61,36 +59,42 @@ pub fn parse_datetime_from_rfc2822(s: &str) -> Result<DateTime<Utc>> {
 /// assert_eq!(date_time.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_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_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_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/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/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/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..cbee2baa1 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,11 @@ 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_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..88b045923 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_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_from_system_time(SystemTime::now())?);
 
         if let Some(v) = self.op.content_type() {
             meta.set_content_type(v);
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..5ad4e5885 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_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..10f790615 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_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_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..0cfb51bdf 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_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..57c75db87 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_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..6f60a3b2f 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_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..e9f2dcd43 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_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/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..5c90df018 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_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..464617de3 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_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/sftp/utils.rs b/core/src/services/sftp/utils.rs
index f30c84233..6f254ebe3 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_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_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/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)