Repository: sorairolake/nt-time (language: rust)

Issue:
FILETIME should be i64?
I could not find any explicit mention that it's an `i64`, but it's pretty strongly hinted:

* https://learn.microsoft.com/en-us/uwp/cpp-ref-for-winrt/clock
* https://learn.microsoft.com/en-us/windows/win32/adschema/a-accountexpires#remarks

And of course, Windows seems to represent it as 2 x `u32`, so who knows?
* https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
* https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types#DWORD


Discussion / hints:
Oh, I think you're right that it's a `u64`.

From https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime#remarks:
> It is not recommended that you add and subtract values from the FILETIME structure to obtain relative times. Instead, you should copy the low- and high-order parts of the file time to a [ULARGE_INTEGER](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ularge_integer-r1) structure, perform 64-bit arithmetic on the QuadPart member, and copy the LowPart and HighPart members into the FILETIME structure.

And [ULARGE_INTEGER](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ularge_integer-r1) represents a `u64`.
Hmm... But actually in .NET it's an `Int64`:

* https://learn.microsoft.com/en-us/dotnet/api/system.datetime.fromfiletime?view=net-7.0
* https://learn.microsoft.com/en-us/dotnet/api/system.datetime.tofiletime?view=net-7.0

Crucially, it cannot be negative though (lol):

https://learn.microsoft.com/en-us/dotnet/api/system.datetime.fromfiletime?view=net-7.0#exceptions
The prerequisites for `lpFileTime` parameters of [`FileTimeToSystemTime()`](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime) are as follows:

> This value must be less than 0x8000000000000000. Otherwise, the function fails.

`0x8000000000000000` is equivalent to `i64::MAX + 1`. From this and the definition of [`FILETIME`](https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime),[^1] I think size of `FILETIME` is `u64`.

[^1]: This consists of two [`DWORD`](https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types) (equivalent to `u32`) members.
Again, I think you're probably right. The whole situation is a mess (lol Microsoft).

Thank you for investigating, and for your explanation.

Fix patch:
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 858e949..70d4073 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -19,6 +19,7 @@ project adheres to https://semver.org/[Semantic Versioning].
 === Changed
 
 * Bump `actions/checkout` from 3 to 4 ({pull-request-url}/44[#44])
+* Update documentation for `FileTime` ({pull-request-url}/60[#60])
 
 == {compare-url}/v0.5.3\...v0.6.0[0.6.0] - 2023-09-03
 
diff --git a/README.md b/README.md
index dea055d..3c56587 100644
--- a/README.md
+++ b/README.md
@@ -11,8 +11,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
 [![Docs][docs-badge]][docs-url]
 ![License][license-badge]
 
-**nt-time** is a [Windows file time][file-time-docs-url] library for
-[Rust][rust-official-url].
+**nt-time** is a [Windows file time] library for [Rust].
 
 ## Usage
 
@@ -58,15 +57,15 @@ default.
 
 #### `large-dates`
 
-Enables the `large-dates` feature of the [`time`][time-crate-url] crate.
+Enables the `large-dates` feature of the [`time`] crate.
 
 #### `chrono`
 
-Enables the [`chrono`][chrono-crate-url] crate.
+Enables the [`chrono`] crate.
 
 #### `serde`
 
-Enables the [`serde`][serde-official-url] crate.
+Enables the [`serde`] crate.
 
 #### `serde-human-readable`
 
@@ -87,20 +86,20 @@ The minimum supported Rust version (MSRV) of this library is v1.65.0.
 
 ## Changelog
 
-Please see [CHANGELOG.adoc](CHANGELOG.adoc).
+Please see [CHANGELOG.adoc].
 
 ## Contributing
 
-Please see [CONTRIBUTING.adoc](CONTRIBUTING.adoc).
+Please see [CONTRIBUTING.adoc].
 
 ## License
 
-Copyright &copy; 2023 Shun Sakai (see [AUTHORS.adoc](AUTHORS.adoc))
+Copyright &copy; 2023 Shun Sakai (see [AUTHORS.adoc])
 
 This library is distributed under the terms of either the _Apache License 2.0_
 or the _MIT License_.
 
-See [COPYING](COPYING) for more details.
+See [COPYING] for more details.
 
 [ci-badge]: https://img.shields.io/github/actions/workflow/status/sorairolake/nt-time/CI.yaml?branch=develop&label=CI&logo=github&style=for-the-badge
 [ci-url]: https://github.com/sorairolake/nt-time/actions?query=branch%3Adevelop+workflow%3ACI++
@@ -109,8 +108,12 @@ See [COPYING](COPYING) for more details.
 [docs-badge]: https://img.shields.io/docsrs/nt-time?label=Docs.rs&logo=docsdotrs&style=for-the-badge
 [docs-url]: https://docs.rs/nt-time
 [license-badge]: https://img.shields.io/crates/l/nt-time?style=for-the-badge
-[file-time-docs-url]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
-[rust-official-url]: https://www.rust-lang.org/
-[time-crate-url]: https://crates.io/crates/time
-[chrono-crate-url]: https://crates.io/crates/chrono
-[serde-official-url]: https://serde.rs/
+[Windows file time]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
+[Rust]: https://www.rust-lang.org/
+[`time`]: https://crates.io/crates/time
+[`chrono`]: https://crates.io/crates/chrono
+[`serde`]: https://serde.rs/
+[CHANGELOG.adoc]: CHANGELOG.adoc
+[CONTRIBUTING.adoc]: CONTRIBUTING.adoc
+[AUTHORS.adoc]: AUTHORS.adoc
+[COPYING]: COPYING
diff --git a/src/file_time.rs b/src/file_time.rs
index aba59ba..cd208d9 100644
--- a/src/file_time.rs
+++ b/src/file_time.rs
@@ -2,9 +2,9 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! A [Windows file time][file-time-docs-url].
+//! A [Windows file time].
 //!
-//! [file-time-docs-url]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
+//! [Windows file time]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
 
 use core::{
     cmp::Ordering,
@@ -18,13 +18,22 @@ use crate::error::{FileTimeRangeError, FileTimeRangeErrorKind, OffsetDateTimeRan
 
 const FILE_TIMES_PER_SEC: u64 = 10_000_000;
 
-/// `FileTime` is a type that represents a [Windows file
-/// time][file-time-docs-url].
+/// `FileTime` is a type that represents a [Windows file time].
 ///
 /// This is a 64-bit unsigned integer value that represents the number of
-/// 100-nanosecond intervals that have elapsed since "1601-01-01 00:00:00 UTC".
+/// 100-nanosecond intervals that have elapsed since "1601-01-01 00:00:00 UTC",
+/// and is used as timestamps such as NTFS and [7z].
 ///
-/// [file-time-docs-url]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
+/// This represents the same value as the [`FILETIME`] structure of the Win32
+/// API, which represents a 64-bit unsigned integer value. Note that the maximum
+/// value of the `FILETIME` structure that can be input to the
+/// [`FileTimeToSystemTime`] function of the Win32 API is limited to
+/// "+30828-09-14 02:48:05.477580700 UTC", which is equivalent to [`i64::MAX`].
+///
+/// [Windows file time]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
+/// [7z]: https://www.7-zip.org/7z.html
+/// [`FILETIME`]: https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
+/// [`FileTimeToSystemTime`]: https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime
 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
 pub struct FileTime(u64);
 
diff --git a/src/lib.rs b/src/lib.rs
index 9fd6ccf..75f4c76 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,9 +2,7 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! The `nt-time` crate is a [Windows file time][file-time-docs-url] library.
-//!
-//! This is used as timestamps such as Windows and [7z][7z-format-url].
+//! The `nt-time` crate is a [Windows file time] library.
 //!
 //! # Examples
 //!
@@ -32,8 +30,7 @@
 //! assert_eq!(FileTime::new(u64::MAX), FileTime::MAX);
 //! ```
 //!
-//! [file-time-docs-url]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
-//! [7z-format-url]: https://www.7-zip.org/7z.html
+//! [Windows file time]: https://docs.microsoft.com/en-us/windows/win32/sysinfo/file-times
 
 #![doc(html_root_url = "https://docs.rs/nt-time/0.6.0/")]
 #![no_std]
diff --git a/src/serde_with.rs b/src/serde_with.rs
index d8cc2e0..8d9054e 100644
--- a/src/serde_with.rs
+++ b/src/serde_with.rs
@@ -2,9 +2,9 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! Differential formats for [Serde][serde-official-url].
+//! Differential formats for [Serde].
 //!
-//! [serde-official-url]: https://serde.rs/
+//! [Serde]: https://serde.rs/
 
 #[cfg(feature = "serde-human-readable")]
 pub mod iso_8601;
diff --git a/src/serde_with/iso_8601.rs b/src/serde_with/iso_8601.rs
index 7472d59..032111c 100644
--- a/src/serde_with/iso_8601.rs
+++ b/src/serde_with/iso_8601.rs
@@ -2,11 +2,10 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! Use the well-known [ISO 8601 format][iso-8601-description-url] when
-//! serializing and deserializing a [`FileTime`].
+//! Use the well-known [ISO 8601 format] when serializing and deserializing a
+//! [`FileTime`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! If the `large-dates` feature is not enabled, the maximum date and time is
 //! "9999-12-31 23:59:59.999999999 UTC".
@@ -32,8 +31,8 @@
 //! );
 //! ```
 //!
-//! [iso-8601-description-url]: https://www.iso.org/iso-8601-date-and-time-format.html
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [ISO 8601 format]: https://www.iso.org/iso-8601-date-and-time-format.html
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 pub mod option;
 
diff --git a/src/serde_with/iso_8601/option.rs b/src/serde_with/iso_8601/option.rs
index b7942ec..952719d 100644
--- a/src/serde_with/iso_8601/option.rs
+++ b/src/serde_with/iso_8601/option.rs
@@ -2,11 +2,10 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! Use the well-known [ISO 8601 format][iso-8601-description-url] when
-//! serializing and deserializing an [`Option<FileTime>`].
+//! Use the well-known [ISO 8601 format] when serializing and deserializing an
+//! [`Option<FileTime>`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! If the `large-dates` feature is not enabled, the maximum date and time is
 //! "9999-12-31 23:59:59.999999999 UTC".
@@ -40,8 +39,8 @@
 //! );
 //! ```
 //!
-//! [iso-8601-description-url]: https://www.iso.org/iso-8601-date-and-time-format.html
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [ISO 8601 format]: https://www.iso.org/iso-8601-date-and-time-format.html
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 use serde::{de::Error as _, ser::Error as _, Deserializer, Serializer};
 use time::{serde::iso8601, OffsetDateTime};
diff --git a/src/serde_with/rfc_2822.rs b/src/serde_with/rfc_2822.rs
index 33b70f7..359e467 100644
--- a/src/serde_with/rfc_2822.rs
+++ b/src/serde_with/rfc_2822.rs
@@ -2,11 +2,10 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! Use the well-known [RFC 2822 format][rfc-2822] when serializing and
-//! deserializing a [`FileTime`].
+//! Use the well-known [RFC 2822 format] when serializing and deserializing a
+//! [`FileTime`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! # Examples
 //!
@@ -29,8 +28,8 @@
 //! );
 //! ```
 //!
-//! [rfc-2822]: https://datatracker.ietf.org/doc/html/rfc2822#section-3.3
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [RFC 2822 format]: https://datatracker.ietf.org/doc/html/rfc2822#section-3.3
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 pub mod option;
 
diff --git a/src/serde_with/rfc_2822/option.rs b/src/serde_with/rfc_2822/option.rs
index 2dba8e0..fbe6446 100644
--- a/src/serde_with/rfc_2822/option.rs
+++ b/src/serde_with/rfc_2822/option.rs
@@ -2,11 +2,10 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! Use the well-known [RFC 2822 format][rfc-2822] when serializing and
-//! deserializing an [`Option<FileTime>`].
+//! Use the well-known [RFC 2822 format] when serializing and deserializing an
+//! [`Option<FileTime>`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! # Examples
 //!
@@ -37,8 +36,8 @@
 //! );
 //! ```
 //!
-//! [rfc-2822]: https://datatracker.ietf.org/doc/html/rfc2822#section-3.3
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [RFC 2822 format]: https://datatracker.ietf.org/doc/html/rfc2822#section-3.3
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 use serde::{de::Error as _, ser::Error as _, Deserializer, Serializer};
 use time::{serde::rfc2822, OffsetDateTime};
diff --git a/src/serde_with/rfc_3339.rs b/src/serde_with/rfc_3339.rs
index 59bcc7d..468c4e7 100644
--- a/src/serde_with/rfc_3339.rs
+++ b/src/serde_with/rfc_3339.rs
@@ -2,11 +2,10 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! Use the well-known [RFC 3339 format][rfc-3339] when serializing and
-//! deserializing a [`FileTime`].
+//! Use the well-known [RFC 3339 format] when serializing and deserializing a
+//! [`FileTime`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! # Examples
 //!
@@ -29,8 +28,8 @@
 //! );
 //! ```
 //!
-//! [rfc-3339]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [RFC 3339 format]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 pub mod option;
 
diff --git a/src/serde_with/rfc_3339/option.rs b/src/serde_with/rfc_3339/option.rs
index 143005c..8da4913 100644
--- a/src/serde_with/rfc_3339/option.rs
+++ b/src/serde_with/rfc_3339/option.rs
@@ -2,11 +2,10 @@
 //
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-//! Use the well-known [RFC 3339 format][rfc-3339] when serializing and
-//! deserializing an [`Option<FileTime>`].
+//! Use the well-known [RFC 3339 format] when serializing and deserializing an
+//! [`Option<FileTime>`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! # Examples
 //!
@@ -37,8 +36,8 @@
 //! );
 //! ```
 //!
-//! [rfc-3339]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [RFC 3339 format]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 use serde::{de::Error as _, ser::Error as _, Deserializer, Serializer};
 use time::{serde::rfc3339, OffsetDateTime};
diff --git a/src/serde_with/unix_time.rs b/src/serde_with/unix_time.rs
index a2be22c..4a2ea33 100644
--- a/src/serde_with/unix_time.rs
+++ b/src/serde_with/unix_time.rs
@@ -4,8 +4,7 @@
 
 //! Use Unix time when serializing and deserializing a [`FileTime`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! # Examples
 //!
@@ -28,7 +27,7 @@
 //! );
 //! ```
 //!
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 pub mod option;
 
diff --git a/src/serde_with/unix_time/option.rs b/src/serde_with/unix_time/option.rs
index d0db691..2243c5e 100644
--- a/src/serde_with/unix_time/option.rs
+++ b/src/serde_with/unix_time/option.rs
@@ -4,8 +4,7 @@
 
 //! Use Unix time when serializing and deserializing an [`Option<FileTime>`].
 //!
-//! Use this module in combination with Serde's
-//! [`#[with]`][serde-with-attribute] attribute.
+//! Use this module in combination with Serde's [`with`] attribute.
 //!
 //! # Examples
 //!
@@ -36,7 +35,7 @@
 //! );
 //! ```
 //!
-//! [serde-with-attribute]: https://serde.rs/field-attrs.html#with
+//! [`with`]: https://serde.rs/field-attrs.html#with
 
 use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
 


Test patch: