Skip to content

Conversation

@cvengler
Copy link

@cvengler cvengler commented Nov 11, 2025

Accepted ACP: rust-lang/libs-team#692
Tracking Issue: #149067


This merge request introduces two new constants to SystemTime: MIN and MAX, whose values represent the maximum values for the respective data type, depending upon the platform.

Technically, this value is already obtainable during runtime with the following algorithm:
Use SystemTime::UNIX_EPOCH and call checked_add (or checked_sub) repeatedly with Duration::new(0, 1) on it, until it returns None.
Mathematically speaking, this algorithm will terminate after a finite amount of steps, yet it is impractical to run it, as it takes practically forever.

Besides, this commit also adds a unit test to verify those values represent the respective minimum and maximum, by letting a checked_add and checked_sub on it fail.

In the future, the hope of the authors lies within the creation of a SystemTime::saturating_add and SystemTime::saturating_sub, similar to the functions already present in std::time::Duration.
However, for those, these constants are crucially required, thereby this should be seen as the initial step towards this direction.
With this change, implementing these functions oneself outside the standard library becomes feasible in a portable manner for the first time.

This feature (and a related saturating version of checked_{add, sub} has been requested multiple times over the course of the past few years, most notably:

@rustbot rustbot added O-hermit Operating System: Hermit O-SGX Target: SGX O-solid Operating System: SOLID O-unix Operating system: Unix-like O-wasi Operating system: Wasi, Webassembly System Interface O-windows Operating system: Windows S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Nov 11, 2025
@cvengler
Copy link
Author

For what it is worth: Right now, the Rust ecosystem does weird stuff in order to figure out a limit.

chrono for example picks arbitrary value that is far in the future but not too far in the future (as I have been told).

arti, the project I work upon and from which the motivation of this PR stems from, uses a custom SaturatingSystemTime, that is highly unportable and very Unix specific: https://gitlab.torproject.org/tpo/core/arti/-/blob/main/crates/tor-dirserver/src/mirror/operation.rs?ref_type=heads#L93

@rust-log-analyzer

This comment has been minimized.

@Kivooeo
Copy link
Member

Kivooeo commented Nov 11, 2025

I'm pretty sure, though I could be wrong that this will need an ACP first before any work

@cvengler
Copy link
Author

I'm pretty sure, though I could be wrong that this will need an ACP first before any work

I am fine in opening such a thing.
We can always defer such an issue if not required. 🙂

cc @ijackson

@cvengler cvengler force-pushed the time_systemtime_limits branch from 481fe49 to 3ef3955 Compare November 11, 2025 22:18
@cvengler cvengler marked this pull request as ready for review November 12, 2025 10:38
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Nov 12, 2025
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Nov 12, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 12, 2025

r? @ChrisDenton

rustbot has assigned @ChrisDenton.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot

This comment has been minimized.

@cvengler
Copy link
Author

Marking this as ready for review, given that CI works now. 🎉

@ChrisDenton
Copy link
Member

This will indeed require an ACP before this can be merged.

@cvengler cvengler force-pushed the time_systemtime_limits branch from 3ef3955 to e5745aa Compare November 12, 2025 14:32
@Kivooeo Kivooeo added S-blocked Status: Blocked on something else such as an RFC or other implementation work. needs-acp This change is blocked on the author creating an ACP. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 12, 2025
@Kivooeo
Copy link
Member

Kivooeo commented Nov 12, 2025

I block this until ACP will accepted

@cvengler
Copy link
Author

Alright, we already have a draft of an ACP in our pipeline.
Will push it in the next days or in the week of the 24th of November, as I will be on vacation the coming week.

@rust-bors
Copy link

rust-bors bot commented Dec 12, 2025

☀️ Try build successful (CI)
Build commit: 48a8c48 (48a8c48906bd1f0214274ff6012f1616e674add7, parent: c4dc70ee0ad7f811fb32e5bed9cd6c7b37beed4e)

@ChrisDenton
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Dec 12, 2025

📌 Commit ac5c70a has been approved by ChrisDenton

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 12, 2025
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Dec 12, 2025
…=ChrisDenton

Add SystemTime::{MIN, MAX}

Accepted ACP: <rust-lang/libs-team#692>
Tracking Issue: <rust-lang#149067>

---

This merge request introduces two new constants to `SystemTime`: `MIN` and `MAX`, whose values represent the maximum values for the respective data type, depending upon the platform.

Technically, this value is already obtainable during runtime with the following algorithm:
Use `SystemTime::UNIX_EPOCH` and call `checked_add` (or `checked_sub`) repeatedly with `Duration::new(0, 1)` on it, until it returns None.
Mathematically speaking, this algorithm will terminate after a finite amount of steps, yet it is impractical to run it, as it takes practically forever.

Besides, this commit also adds a unit test to verify those values represent the respective minimum and maximum, by letting a `checked_add` and `checked_sub` on it fail.

In the future, the hope of the authors lies within the creation of a `SystemTime::saturating_add` and `SystemTime::saturating_sub`, similar to the functions already present in `std::time::Duration`.
However, for those, these constants are crucially required, thereby this should be seen as the initial step towards this direction.
With this change, implementing these functions oneself outside the standard library becomes feasible in a portable manner for the first time.

This feature (and a related saturating version of `checked_{add, sub}` has been requested multiple times over the course of the past few years, most notably:
* rust-lang#100141
* rust-lang#133525
* rust-lang#105762
* rust-lang#71224
* rust-lang#45448
* rust-lang#52555
jhpratt added a commit to jhpratt/rust that referenced this pull request Dec 13, 2025
…=ChrisDenton

Add SystemTime::{MIN, MAX}

Accepted ACP: <rust-lang/libs-team#692>
Tracking Issue: <rust-lang#149067>

---

This merge request introduces two new constants to `SystemTime`: `MIN` and `MAX`, whose values represent the maximum values for the respective data type, depending upon the platform.

Technically, this value is already obtainable during runtime with the following algorithm:
Use `SystemTime::UNIX_EPOCH` and call `checked_add` (or `checked_sub`) repeatedly with `Duration::new(0, 1)` on it, until it returns None.
Mathematically speaking, this algorithm will terminate after a finite amount of steps, yet it is impractical to run it, as it takes practically forever.

Besides, this commit also adds a unit test to verify those values represent the respective minimum and maximum, by letting a `checked_add` and `checked_sub` on it fail.

In the future, the hope of the authors lies within the creation of a `SystemTime::saturating_add` and `SystemTime::saturating_sub`, similar to the functions already present in `std::time::Duration`.
However, for those, these constants are crucially required, thereby this should be seen as the initial step towards this direction.
With this change, implementing these functions oneself outside the standard library becomes feasible in a portable manner for the first time.

This feature (and a related saturating version of `checked_{add, sub}` has been requested multiple times over the course of the past few years, most notably:
* rust-lang#100141
* rust-lang#133525
* rust-lang#105762
* rust-lang#71224
* rust-lang#45448
* rust-lang#52555
bors added a commit that referenced this pull request Dec 13, 2025
Rollup of 11 pull requests

Successful merges:

 - #145278 (Update `rustc_codegen_gcc` rotate operation document)
 - #148825 (Add SystemTime::{MIN, MAX})
 - #148837 (Use `let...else` instead of `match foo { ... _ => return };` and `if let ... else return`)
 - #149177 (Add proper suggestion for associated function with unknown field)
 - #149843 (Inherit attributes in delegation)
 - #149860 (Fix: Prevent macro-expanded extern crates from shadowing extern arguments)
 - #149874 (Weak for Arc pointer is marked as DynSend/DynSync)
 - #149903 (Remove unused code in `cfg_old`)
 - #149911 (bootstrap: Don't pass an unused `--color` to compiletest)
 - #149916 (Add a sanity check in case of any duplicate nodes)
 - #149924 (`declare_lint_pass` for `INLINE_ALWAYS_MISMATCHING_TARGET_FEATURES`)

r? `@ghost`
`@rustbot` modify labels: rollup
@jhpratt
Copy link
Member

jhpratt commented Dec 13, 2025

@bors r-

#149940 (comment)

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Dec 13, 2025
@ChrisDenton
Copy link
Member

ChrisDenton commented Dec 13, 2025

Hm, there are two issues here:

Firstly there's a pre-existing bug in the Windows implementation of checked_sub_duration. This should return None for values less than zero. As far as I can make out this bug has existed for a very long time but apparently nobody has ever encountered it (I guess because dates before 1601 are very rare).

The second problem is with the new test. Windows SystemTime does not have nano-second precision. Its intervals are in 100 nanosecond increments. One workaround would be to add a MIN_INTERVAL constant to the test which is 100 on Windows and 1 everywhere else (unless there are other platforms which don't have 1 nanosecond intervals).

@cvengler
Copy link
Author

Hm, there are two issues here:

Firstly there's a pre-existing bug in the Windows implementation of checked_sub_duration. This should return None for values less than zero. As far as I can make out this bug has existed for a very long time but apparently nobody has ever encountered it (I guess because dates before 1601 are very rare).

The second problem is with the new test. Windows SystemTime does not have nano-second precision. Its intervals are in 100 nanosecond increments. One workaround would be to add a MIN_INTERVAL constant to the test which is 100 on Windows and 1 everywhere else (unless there are other platforms which don't have 1 nanosecond intervals).

Thanks, that was very fast!
I was indeed working on this just the very moment.

Firstly there's a pre-existing bug in the Windows implementation of checked_sub_duration. This should return None for values less than zero. As far as I can make out this bug has existed for a very long time but apparently nobody has ever encountered it (I guess because dates before 1601 are very rare).

Good catch, will fix it.

The second problem is with the new test. Windows SystemTime does not have nano-second precision. Its intervals are in 100 nanosecond increments. One workaround would be to add a MIN_INTERVAL constant to the test which is 100 on Windows and 1 everywhere else (unless there are other platforms which don't have 1 nanosecond intervals).

MIN_INTERVAL would be a possibility.
However, I am more inclined towards changing the implementation to do cmp::max(dur.subsec_nanos() as u64 / 100, 1), but this might be something for a follow-up PR.
For this one, the const approach in the test is probably best.

@ChrisDenton
Copy link
Member

However, I am more inclined towards changing the implementation to do cmp::max(dur.subsec_nanos() as u64 / 100, 1), but this might be something for a follow-up PR.

Ah, that does indeed sound good.

@cvengler
Copy link
Author

cvengler commented Dec 13, 2025

However, I am more inclined towards changing the implementation to do cmp::max(dur.subsec_nanos() as u64 / 100, 1), but this might be something for a follow-up PR.

Ah, that does indeed sound good.

I pushed two commits.
One fixing the bug in checked_sub_duration and another one modifying the test case and documenting the status quo.

I hope this PR is the correct place for this?
Otherwise I could move this into a separate one, but I kind of want to get this PR into the main branch now.
My plan would be to open a follow-up MR changing this behavior, because it is probably a different kind of change to the ecosystem?

Alternatively, I would hard reset this to ac5c70a and open a new PR with those changes, setting this PR to "stale" before the other one is merged, then rebasing onto it.

@rust-log-analyzer

This comment has been minimized.

@cvengler cvengler force-pushed the time_systemtime_limits branch 2 times, most recently from 168b257 to b02ab4c Compare December 13, 2025 09:43
There is a slight edge case when adding and subtracting a `Duration`
from a `SystemTime`, namely when the duration itself is finer/smaller
than the time precision on the operating systems.

On most (if not all non-Windows) operating systems, the precision of
`Duration` aligns with the `SystemTime`, both being one nanosecond.

However, on Windows, this time precision is 100ns, meaning that adding
or subtracting a `Duration` whose value is `< Duration::new(0, 100)`
will result in that method behaving like an addition/subtracting of
`Duration::ZERO`, due to the `Duration` getting rounded-down to the zero
value.
@cvengler cvengler force-pushed the time_systemtime_limits branch from b02ab4c to 8decbdf Compare December 13, 2025 09:51
@rust-log-analyzer

This comment has been minimized.

The Windows implementation of `SystemTime::checked_sub` contains a bug,
namely that it does not return `None` on values below 1601.

This bug stems from the fact that internally, the time gets converted to
an i64, with zero representing the anchor in 1601.  Of course,
performing checked subtraction on a signed integer generally works fine.
However, the resulting value delivers undefined behavior on Windows
systems.

To mitigate this issue, we try to convert the resulting i64 to an u64
because a negative value should obviously fail there.
@cvengler cvengler force-pushed the time_systemtime_limits branch from 8decbdf to d80348b Compare December 13, 2025 11:35
@cvengler
Copy link
Author

This seems to be building again. 🎉

@ChrisDenton
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Dec 13, 2025

📌 Commit d80348b has been approved by ChrisDenton

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-hermit Operating System: Hermit O-SGX Target: SGX O-solid Operating System: SOLID O-unix Operating system: Unix-like O-wasi Operating system: Wasi, Webassembly System Interface O-windows Operating system: Windows S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.