diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs
index a098e2b80..cf493e7c5 100644
--- a/src/backend/libc/fs/syscalls.rs
+++ b/src/backend/libc/fs/syscalls.rs
@@ -1778,6 +1778,7 @@ pub(crate) fn sendfile(
 
 /// Convert from a Linux `statx` value to rustix's `Stat`.
 #[cfg(all(linux_kernel, target_pointer_width = "32"))]
+#[allow(deprecated)] // for `st_[amc]time` u64->i64 transition
 fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
     Ok(Stat {
         st_dev: crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor).into(),
@@ -1789,23 +1790,11 @@ fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
         st_size: x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blksize: x.stx_blksize.into(),
         st_blocks: x.stx_blocks.into(),
-        st_atime: x
-            .stx_atime
-            .tv_sec
-            .try_into()
-            .map_err(|_| io::Errno::OVERFLOW)?,
+        st_atime: bitcast!(i64::from(x.stx_atime.tv_sec)),
         st_atime_nsec: x.stx_atime.tv_nsec as _,
-        st_mtime: x
-            .stx_mtime
-            .tv_sec
-            .try_into()
-            .map_err(|_| io::Errno::OVERFLOW)?,
+        st_mtime: bitcast!(i64::from(x.stx_mtime.tv_sec)),
         st_mtime_nsec: x.stx_mtime.tv_nsec as _,
-        st_ctime: x
-            .stx_ctime
-            .tv_sec
-            .try_into()
-            .map_err(|_| io::Errno::OVERFLOW)?,
+        st_ctime: bitcast!(i64::from(x.stx_ctime.tv_sec)),
         st_ctime_nsec: x.stx_ctime.tv_nsec as _,
         st_ino: x.stx_ino.into(),
     })
@@ -1827,23 +1816,11 @@ fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
     result.st_size = x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?;
     result.st_blksize = x.stx_blksize.into();
     result.st_blocks = x.stx_blocks.try_into().map_err(|_e| io::Errno::OVERFLOW)?;
-    result.st_atime = x
-        .stx_atime
-        .tv_sec
-        .try_into()
-        .map_err(|_| io::Errno::OVERFLOW)?;
+    result.st_atime = bitcast!(i64::from(x.stx_atime.tv_sec));
     result.st_atime_nsec = x.stx_atime.tv_nsec as _;
-    result.st_mtime = x
-        .stx_mtime
-        .tv_sec
-        .try_into()
-        .map_err(|_| io::Errno::OVERFLOW)?;
+    result.st_mtime = bitcast!(i64::from(x.stx_mtime.tv_sec));
     result.st_mtime_nsec = x.stx_mtime.tv_nsec as _;
-    result.st_ctime = x
-        .stx_ctime
-        .tv_sec
-        .try_into()
-        .map_err(|_| io::Errno::OVERFLOW)?;
+    result.st_ctime = bitcast!(i64::from(x.stx_ctime.tv_sec));
     result.st_ctime_nsec = x.stx_ctime.tv_nsec as _;
     result.st_ino = x.stx_ino.into();
 
@@ -1852,6 +1829,7 @@ fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
 
 /// Convert from a Linux `stat64` value to rustix's `Stat`.
 #[cfg(all(linux_kernel, target_pointer_width = "32"))]
+#[allow(deprecated)] // for `st_[amc]time` u64->i64 transition
 fn stat64_to_stat(s64: c::stat64) -> io::Result<Stat> {
     Ok(Stat {
         st_dev: s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
@@ -1863,17 +1841,17 @@ fn stat64_to_stat(s64: c::stat64) -> io::Result<Stat> {
         st_size: s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blksize: s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blocks: s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?,
-        st_atime: s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_atime: bitcast!(i64::from(s64.st_atime)),
         st_atime_nsec: s64
             .st_atime_nsec
             .try_into()
             .map_err(|_| io::Errno::OVERFLOW)?,
-        st_mtime: s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_mtime: bitcast!(i64::from(s64.st_mtime)),
         st_mtime_nsec: s64
             .st_mtime_nsec
             .try_into()
             .map_err(|_| io::Errno::OVERFLOW)?,
-        st_ctime: s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_ctime: bitcast!(i64::from(s64.st_ctime)),
         st_ctime_nsec: s64
             .st_ctime_nsec
             .try_into()
@@ -1899,17 +1877,17 @@ fn stat64_to_stat(s64: c::stat64) -> io::Result<Stat> {
     result.st_size = s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?;
     result.st_blksize = s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?;
     result.st_blocks = s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?;
-    result.st_atime = s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+    result.st_atime = i64::from(s64.st_atime) as _;
     result.st_atime_nsec = s64
         .st_atime_nsec
         .try_into()
         .map_err(|_| io::Errno::OVERFLOW)?;
-    result.st_mtime = s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+    result.st_mtime = i64::from(s64.st_mtime) as _;
     result.st_mtime_nsec = s64
         .st_mtime_nsec
         .try_into()
         .map_err(|_| io::Errno::OVERFLOW)?;
-    result.st_ctime = s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?;
+    result.st_ctime = i64::from(s64.st_ctime) as _;
     result.st_ctime_nsec = s64
         .st_ctime_nsec
         .try_into()
diff --git a/src/backend/libc/fs/types.rs b/src/backend/libc/fs/types.rs
index 19508c241..f318f1636 100644
--- a/src/backend/libc/fs/types.rs
+++ b/src/backend/libc/fs/types.rs
@@ -986,10 +986,13 @@ pub struct Stat {
     pub st_size: i64,
     pub st_blksize: u32,
     pub st_blocks: u64,
+    #[deprecated(note = "Use `rustix::fs::StatExt::atime` instead.")]
     pub st_atime: u64,
     pub st_atime_nsec: u32,
+    #[deprecated(note = "Use `rustix::fs::StatExt::mtime` instead.")]
     pub st_mtime: u64,
     pub st_mtime_nsec: u32,
+    #[deprecated(note = "Use `rustix::fs::StatExt::ctime` instead.")]
     pub st_ctime: u64,
     pub st_ctime_nsec: u32,
     pub st_ino: u64,
diff --git a/src/backend/linux_raw/fs/syscalls.rs b/src/backend/linux_raw/fs/syscalls.rs
index 47d01df1c..126549386 100644
--- a/src/backend/linux_raw/fs/syscalls.rs
+++ b/src/backend/linux_raw/fs/syscalls.rs
@@ -711,6 +711,7 @@ fn lstat_old(path: &CStr) -> io::Result<Stat> {
     target_arch = "mips64",
     target_arch = "mips64r6"
 ))]
+#[allow(deprecated)] // for `st_[amc]time` u64->i64 transition
 fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
     Ok(Stat {
         st_dev: crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor),
@@ -722,23 +723,11 @@ fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
         st_size: x.stx_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blksize: x.stx_blksize.into(),
         st_blocks: x.stx_blocks.into(),
-        st_atime: x
-            .stx_atime
-            .tv_sec
-            .try_into()
-            .map_err(|_| io::Errno::OVERFLOW)?,
+        st_atime: bitcast!(i64::from(x.stx_atime.tv_sec)),
         st_atime_nsec: x.stx_atime.tv_nsec.into(),
-        st_mtime: x
-            .stx_mtime
-            .tv_sec
-            .try_into()
-            .map_err(|_| io::Errno::OVERFLOW)?,
+        st_mtime: bitcast!(i64::from(x.stx_mtime.tv_sec)),
         st_mtime_nsec: x.stx_mtime.tv_nsec.into(),
-        st_ctime: x
-            .stx_ctime
-            .tv_sec
-            .try_into()
-            .map_err(|_| io::Errno::OVERFLOW)?,
+        st_ctime: bitcast!(i64::from(x.stx_ctime.tv_sec)),
         st_ctime_nsec: x.stx_ctime.tv_nsec.into(),
         st_ino: x.stx_ino.into(),
     })
@@ -746,6 +735,7 @@ fn statx_to_stat(x: crate::fs::Statx) -> io::Result<Stat> {
 
 /// Convert from a Linux `stat64` value to rustix's `Stat`.
 #[cfg(target_pointer_width = "32")]
+#[allow(deprecated)] // for `st_[amc]time` u64->i64 transition
 fn stat_to_stat(s64: linux_raw_sys::general::stat64) -> io::Result<Stat> {
     Ok(Stat {
         st_dev: s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?,
@@ -757,17 +747,17 @@ fn stat_to_stat(s64: linux_raw_sys::general::stat64) -> io::Result<Stat> {
         st_size: s64.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blksize: s64.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blocks: s64.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?,
-        st_atime: s64.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_atime: bitcast!(i64::from(s64.st_atime)),
         st_atime_nsec: s64
             .st_atime_nsec
             .try_into()
             .map_err(|_| io::Errno::OVERFLOW)?,
-        st_mtime: s64.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_mtime: bitcast!(i64::from(s64.st_mtime)),
         st_mtime_nsec: s64
             .st_mtime_nsec
             .try_into()
             .map_err(|_| io::Errno::OVERFLOW)?,
-        st_ctime: s64.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_ctime: bitcast!(i64::from(s64.st_ctime)),
         st_ctime_nsec: s64
             .st_ctime_nsec
             .try_into()
@@ -789,17 +779,17 @@ fn stat_to_stat(s: linux_raw_sys::general::stat) -> io::Result<Stat> {
         st_size: s.st_size.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blksize: s.st_blksize.try_into().map_err(|_| io::Errno::OVERFLOW)?,
         st_blocks: s.st_blocks.try_into().map_err(|_| io::Errno::OVERFLOW)?,
-        st_atime: s.st_atime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_atime: bitcast!(i64::from(s.st_atime)),
         st_atime_nsec: s
             .st_atime_nsec
             .try_into()
             .map_err(|_| io::Errno::OVERFLOW)?,
-        st_mtime: s.st_mtime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_mtime: bitcast!(i64::from(s.st_mtime)),
         st_mtime_nsec: s
             .st_mtime_nsec
             .try_into()
             .map_err(|_| io::Errno::OVERFLOW)?,
-        st_ctime: s.st_ctime.try_into().map_err(|_| io::Errno::OVERFLOW)?,
+        st_ctime: bitcast!(i64::from(s.st_ctime)),
         st_ctime_nsec: s
             .st_ctime_nsec
             .try_into()
diff --git a/src/backend/linux_raw/fs/types.rs b/src/backend/linux_raw/fs/types.rs
index 39823c4e1..c109a6ff9 100644
--- a/src/backend/linux_raw/fs/types.rs
+++ b/src/backend/linux_raw/fs/types.rs
@@ -653,10 +653,13 @@ pub struct Stat {
     pub st_size: i64,
     pub st_blksize: u32,
     pub st_blocks: u64,
+    #[deprecated(note = "Use `rustix::fs::StatExt::atime` instead.")]
     pub st_atime: u64,
     pub st_atime_nsec: u32,
+    #[deprecated(note = "Use `rustix::fs::StatExt::mtime` instead.")]
     pub st_mtime: u64,
     pub st_mtime_nsec: u32,
+    #[deprecated(note = "Use `rustix::fs::StatExt::ctime` instead.")]
     pub st_ctime: u64,
     pub st_ctime_nsec: u32,
     pub st_ino: u64,
diff --git a/src/fs/mod.rs b/src/fs/mod.rs
index 996bb4e57..27d357012 100644
--- a/src/fs/mod.rs
+++ b/src/fs/mod.rs
@@ -141,3 +141,38 @@ pub use std::os::unix::fs::{DirEntryExt, FileExt, FileTypeExt, MetadataExt, Open
 #[cfg(feature = "std")]
 #[cfg(all(wasi_ext, target_os = "wasi"))]
 pub use std::os::wasi::fs::{DirEntryExt, FileExt, FileTypeExt, MetadataExt, OpenOptionsExt};
+
+/// Extension trait for accessing timestamp fields of `Stat`.
+///
+/// Rustix's `Stat` type on some platforms has unsigned `st_mtime`,
+/// `st_atime`, and `st_ctime` fields. This is incorrect, as Unix defines
+/// these fields to be signed, with negative values representing dates before
+/// the Unix epoch. Until the next semver bump, these unsigned fields are
+/// deprecated, and this trait provides accessors which return their values
+/// as signed integers.
+#[cfg(all(unix, not(any(target_os = "aix", target_os = "nto"))))]
+pub trait StatExt {
+    /// Return the value of the `st_atime` field, casted to the correct type.
+    fn atime(&self) -> i64;
+    /// Return the value of the `st_mtime` field, casted to the correct type.
+    fn mtime(&self) -> i64;
+    /// Return the value of the `st_ctime` field, casted to the correct type.
+    fn ctime(&self) -> i64;
+}
+
+#[cfg(all(unix, not(any(target_os = "aix", target_os = "nto"))))]
+#[allow(deprecated)]
+impl StatExt for Stat {
+    #[inline]
+    fn atime(&self) -> i64 {
+        self.st_atime as i64
+    }
+    #[inline]
+    fn mtime(&self) -> i64 {
+        self.st_mtime as i64
+    }
+    #[inline]
+    fn ctime(&self) -> i64 {
+        self.st_ctime as i64
+    }
+}
diff --git a/tests/fs/futimens.rs b/tests/fs/futimens.rs
index 616638f13..1aa9f72b5 100644
--- a/tests/fs/futimens.rs
+++ b/tests/fs/futimens.rs
@@ -1,7 +1,7 @@
 #[cfg(not(any(target_os = "redox", target_os = "wasi")))]
 #[test]
 fn test_futimens() {
-    use rustix::fs::{fstat, futimens, openat, Mode, OFlags, Timespec, Timestamps, CWD};
+    use rustix::fs::{fstat, futimens, openat, Mode, OFlags, StatExt, Timespec, Timestamps, CWD};
 
     let tmp = tempfile::tempdir().unwrap();
     let dir = openat(CWD, tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
@@ -28,7 +28,7 @@ fn test_futimens() {
 
     let after = fstat(&file).unwrap();
 
-    assert_eq!(times.last_modification.tv_sec as u64, after.st_mtime as u64);
+    assert_eq!(times.last_modification.tv_sec as u64, after.mtime() as u64);
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(
         times.last_modification.tv_nsec as u64,
diff --git a/tests/fs/utimensat.rs b/tests/fs/utimensat.rs
index ec65f466d..14dce7f76 100644
--- a/tests/fs/utimensat.rs
+++ b/tests/fs/utimensat.rs
@@ -1,7 +1,9 @@
 #[cfg(not(any(target_os = "redox", target_os = "wasi")))]
 #[test]
 fn test_utimensat() {
-    use rustix::fs::{openat, statat, utimensat, AtFlags, Mode, OFlags, Timespec, Timestamps, CWD};
+    use rustix::fs::{
+        openat, statat, utimensat, AtFlags, Mode, OFlags, StatExt, Timespec, Timestamps, CWD,
+    };
 
     let tmp = tempfile::tempdir().unwrap();
     let dir = openat(
@@ -34,7 +36,7 @@ fn test_utimensat() {
 
     let after = statat(&dir, "file", AtFlags::empty()).unwrap();
 
-    assert_eq!(times.last_modification.tv_sec as u64, after.st_mtime as u64);
+    assert_eq!(times.last_modification.tv_sec as u64, after.mtime() as u64);
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(
         times.last_modification.tv_nsec as u64,
@@ -45,15 +47,15 @@ fn test_utimensat() {
         times.last_modification.tv_nsec as u64,
         after.st_mtimensec as u64
     );
-    assert!(times.last_access.tv_sec as u64 >= after.st_atime as u64);
+    assert!(times.last_access.tv_sec as u64 >= after.atime() as u64);
     #[cfg(not(target_os = "netbsd"))]
     assert!(
-        times.last_access.tv_sec as u64 > after.st_atime as u64
+        times.last_access.tv_sec as u64 > after.atime() as u64
             || times.last_access.tv_nsec as u64 >= after.st_atime_nsec as u64
     );
     #[cfg(target_os = "netbsd")]
     assert!(
-        times.last_access.tv_sec as u64 > after.st_atime as u64
+        times.last_access.tv_sec as u64 > after.atime() as u64
             || times.last_access.tv_nsec as u64 >= after.st_atimensec as u64
     );
 }
diff --git a/tests/fs/y2038.rs b/tests/fs/y2038.rs
index eba3a16d5..615f92636 100644
--- a/tests/fs/y2038.rs
+++ b/tests/fs/y2038.rs
@@ -9,7 +9,7 @@
 #[test]
 fn test_y2038_with_utimensat() {
     use rustix::fs::{
-        fstat, openat, statat, utimensat, AtFlags, Mode, OFlags, Timespec, Timestamps, CWD,
+        fstat, openat, statat, utimensat, AtFlags, Mode, OFlags, StatExt, Timespec, Timestamps, CWD,
     };
 
     let tmp = tempfile::tempdir().unwrap();
@@ -46,23 +46,23 @@ fn test_y2038_with_utimensat() {
     // Use `statat` to read back the timestamp.
     let stat = statat(&dir, "file", AtFlags::empty()).unwrap();
 
-    assert_eq!(TryInto::<u64>::try_into(stat.st_mtime).unwrap(), m_sec);
+    assert_eq!(TryInto::<u64>::try_into(stat.mtime()).unwrap(), m_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
     #[cfg(target_os = "netbsd")]
     assert_eq!(stat.st_mtimensec as u32, m_nsec);
 
-    assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() >= a_sec);
+    assert!(TryInto::<u64>::try_into(stat.atime()).unwrap() >= a_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atime_nsec as u32 >= a_nsec
     );
     #[cfg(target_os = "netbsd")]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atimensec as u32 >= a_nsec
     );
 
@@ -70,23 +70,23 @@ fn test_y2038_with_utimensat() {
     let file = openat(&dir, "file", OFlags::RDONLY, Mode::empty()).unwrap();
     let stat = fstat(&file).unwrap();
 
-    assert_eq!(TryInto::<u64>::try_into(stat.st_mtime).unwrap(), m_sec);
+    assert_eq!(TryInto::<u64>::try_into(stat.mtime()).unwrap(), m_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
     #[cfg(target_os = "netbsd")]
     assert_eq!(stat.st_mtimensec as u32, m_nsec);
 
-    assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() >= a_sec);
+    assert!(TryInto::<u64>::try_into(stat.atime()).unwrap() >= a_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atime_nsec as u32 >= a_nsec
     );
     #[cfg(target_os = "netbsd")]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atimensec as u32 >= a_nsec
     );
 }
@@ -102,7 +102,7 @@ fn test_y2038_with_utimensat() {
 #[test]
 fn test_y2038_with_futimens() {
     use rustix::fs::{
-        fstat, futimens, openat, statat, AtFlags, Mode, OFlags, Timespec, Timestamps, CWD,
+        fstat, futimens, openat, statat, AtFlags, Mode, OFlags, StatExt, Timespec, Timestamps, CWD,
     };
 
     let tmp = tempfile::tempdir().unwrap();
@@ -139,23 +139,23 @@ fn test_y2038_with_futimens() {
     // Use `statat` to read back the timestamp.
     let stat = statat(&dir, "file", AtFlags::empty()).unwrap();
 
-    assert_eq!(TryInto::<u64>::try_into(stat.st_mtime).unwrap(), m_sec);
+    assert_eq!(TryInto::<u64>::try_into(stat.mtime()).unwrap(), m_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
     #[cfg(target_os = "netbsd")]
     assert_eq!(stat.st_mtimensec as u32, m_nsec);
 
-    assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() >= a_sec);
+    assert!(TryInto::<u64>::try_into(stat.atime()).unwrap() >= a_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atime_nsec as u32 >= a_nsec
     );
     #[cfg(target_os = "netbsd")]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atimensec as u32 >= a_nsec
     );
 
@@ -163,23 +163,23 @@ fn test_y2038_with_futimens() {
     let file = openat(&dir, "file", OFlags::RDONLY, Mode::empty()).unwrap();
     let stat = fstat(&file).unwrap();
 
-    assert_eq!(TryInto::<u64>::try_into(stat.st_mtime).unwrap(), m_sec);
+    assert_eq!(TryInto::<u64>::try_into(stat.mtime()).unwrap(), m_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
     #[cfg(target_os = "netbsd")]
     assert_eq!(stat.st_mtimensec as u32, m_nsec);
 
-    assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() >= a_sec);
+    assert!(TryInto::<u64>::try_into(stat.atime()).unwrap() >= a_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atime_nsec as u32 >= a_nsec
     );
     #[cfg(target_os = "netbsd")]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atimensec as u32 >= a_nsec
     );
 }
@@ -193,7 +193,7 @@ fn test_y2038_with_futimens() {
 #[cfg(not(all(target_os = "emscripten", target_pointer_width = "32")))]
 #[test]
 fn test_y2038_with_futimens_and_stat() {
-    use rustix::fs::{fstat, futimens, open, stat, Mode, OFlags, Timespec, Timestamps};
+    use rustix::fs::{fstat, futimens, open, stat, Mode, OFlags, StatExt, Timespec, Timestamps};
 
     let tmp = tempfile::tempdir().unwrap();
 
@@ -233,23 +233,23 @@ fn test_y2038_with_futimens_and_stat() {
     // Use `statat` to read back the timestamp.
     let stat = stat(tmp.path().join("file")).unwrap();
 
-    assert_eq!(TryInto::<u64>::try_into(stat.st_mtime).unwrap(), m_sec);
+    assert_eq!(TryInto::<u64>::try_into(stat.mtime()).unwrap(), m_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
     #[cfg(target_os = "netbsd")]
     assert_eq!(stat.st_mtimensec as u32, m_nsec);
 
-    assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() >= a_sec);
+    assert!(TryInto::<u64>::try_into(stat.atime()).unwrap() >= a_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atime_nsec as u32 >= a_nsec
     );
     #[cfg(target_os = "netbsd")]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atimensec as u32 >= a_nsec
     );
 
@@ -257,23 +257,23 @@ fn test_y2038_with_futimens_and_stat() {
     let file = open(tmp.path().join("file"), OFlags::RDONLY, Mode::empty()).unwrap();
     let stat = fstat(&file).unwrap();
 
-    assert_eq!(TryInto::<u64>::try_into(stat.st_mtime).unwrap(), m_sec);
+    assert_eq!(TryInto::<u64>::try_into(stat.mtime()).unwrap(), m_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
     #[cfg(target_os = "netbsd")]
     assert_eq!(stat.st_mtimensec as u32, m_nsec);
 
-    assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() >= a_sec);
+    assert!(TryInto::<u64>::try_into(stat.atime()).unwrap() >= a_sec);
 
     #[cfg(not(target_os = "netbsd"))]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atime_nsec as u32 >= a_nsec
     );
     #[cfg(target_os = "netbsd")]
     assert!(
-        TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+        TryInto::<u64>::try_into(stat.atime()).unwrap() > a_sec
             || stat.st_atimensec as u32 >= a_nsec
     );
 }