Skip to content

[libc++] Clarify clock behavior before epoch (LWG 3318) #144697

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions libcxx/include/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,9 @@ template <class Rep, class Period>
constexpr duration<Rep, Period> abs(duration<Rep, Period> d); // C++17

// Clocks

/// The system_clock represents wall-clock time based on the system-wide realtime clock.
/// The representation for it is a signed representation, so it can express times before and after the epoch
/// like: (1970-01-01 00:00:00 UTC).
class system_clock
{
public:
Expand Down Expand Up @@ -306,6 +308,8 @@ template<class charT, class traits> // C++20
operator<<(basic_ostream<charT, traits>& os, const sys_days& dp);

// [time.clock.utc], class utc_clock
/// The utc_clock represents Coordinated Universal Time (UTC)
/// It uses a signed representation just like system_clock and represents time before and after its epoch
class utc_clock { // C++20
public:
using rep = a signed arithmetic type;
Expand Down Expand Up @@ -342,6 +346,8 @@ template<class Duration> // C++20


// [time.clock.tai], class tai_clock
/// The tai_clock uses Coordinated Universal Time (UTC).
/// It uses a signed representation and can express time both before and after its epoch.
class tai_clock { // C++20
public:
using rep = a signed arithmetic type;
Expand Down Expand Up @@ -369,6 +375,8 @@ template<class charT, class traits, class Duration> // C++20
operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t);

// [time.clock.gps], class gps_clock
/// The gps_clock represents International Atomic Time (TAI). It uses a signed
/// representation and can express time both before and after its epoch.
class gps_clock { // C++20
public:
using rep = a signed arithmetic type;
Expand All @@ -395,6 +403,8 @@ template<class charT, class traits, class Duration> // C++20
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& t);

/// The class file_clock is used for file timestamps. It uses a signed representation
/// and can express time both before and after its epoch.
class file_clock // C++20
{
public:
Expand All @@ -420,6 +430,8 @@ template<class charT, class traits, class Duration> // C++20
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const file_time<Duration>& tp);

/// The class steady_clock is monotonic and it does not support negative time points.
/// Wheter it supports time before its epoch is unspecified.
Comment on lines +433 to +434
Copy link
Contributor

@frederick-vs-ja frederick-vs-ja Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we need to update https://github.com/llvm/llvm-project/blob/main/libcxx/docs/Status/Cxx20Issues.csv.

libc++'s duration::rep is nanoseconds so I think it can represent negative time points. According to the list in LWG3318, I think we don't need to mention signedness except for steady_clock and high_resolution_clock.

Also, it's also possibly redundant for steady_clock and high_resolution_clock. The standard says that the rep types are unspecified, and users can check the signedness by duration::min() < duration::zero(). Note that libc++ is already saying nanoseconds is the duration type of steady_clock in the comments.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I'll make the changes based on your suggestions!

class steady_clock
{
public:
Expand All @@ -431,7 +443,7 @@ public:

static time_point now() noexcept;
};

// high_resolution_clock is an alias for the steady_clock and has the same behavior.
typedef steady_clock high_resolution_clock;

// [time.clock.local] local time // C++20
Expand Down
Loading