[RFC] libstdc++: chrono::current_zone() should always respect $TZ

James Morris jamesmorris2@gmail.com
Sun May 7 21:55:15 GMT 2023


Hello,

I was playing around with GCC 13 and upgrading some old C++ code to
C++20. I had a small function for getting the current time based on
the <ctime> functions and tried to convert it to use the new <chrono>
functions. I was quite surprised that when using
chrono::current_zone(), my program stopped responding to the TZ
environment variable.

I'd like to propose that chrono::current_zone() always pays attention
to $TZ so as not to surprise users moving from <ctime>. tzdb.cc
already has code for this gated by an #ifdef, so maybe all that needs
to be done is to make that code available to all platforms.

Example of my code with <ctime>:

```
#include <ctime>
#include <iostream>

int main() {
    std::time_t epoch_time = std::time(nullptr);
    std::tm* local_time = std::localtime(&epoch_time);

    char time_string[] = "00:00:00 UTC";
    std::strftime(time_string, sizeof "00:00:00 UTC", "%T %Z", local_time);

    std::cout << time_string << '\n';
}
```

Example of what I tried to do with <chrono>:

```
#include <chrono>
#include <format>
#include <iostream>

namespace chrono = std::chrono;

int main() {
    auto zt = chrono::zoned_time(chrono::current_zone(),
chrono::system_clock::now());
    std::cout << std::format("{:%T %Z}", zt) << '\n';
}
```

Diff of proposed changes:

```
diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc
index a43b4f33eba..c16913dab67 100644
--- a/libstdc++-v3/src/c++20/tzdb.cc
+++ b/libstdc++-v3/src/c++20/tzdb.cc
@@ -1632,6 +1632,20 @@ namespace std::chrono
   {
     // TODO cache this function's result?

+    // AIX stores current zone in $TZ in /etc/environment but the value
+    // is typically a POSIX time zone name, not IANA zone.
+    // https://developer.ibm.com/articles/au-aix-posix/
+    // https://www.ibm.com/support/pages/managing-time-zone-variable-posix
+    //
+    // Other POSIX systems also allow the user to override the
+    // system timezone by setting $TZ.
+    if (const char* env = std::getenv("TZ"))
+      {
+    // This will fail unless TZ contains an IANA time zone name.
+    if (auto tz = do_locate_zone(this->zones, this->links, env))
+      return tz;
+      }
+
 #ifndef _AIX
     error_code ec;
     // This should be a symlink to e.g. /usr/share/zoneinfo/Europe/London
@@ -1685,17 +1699,6 @@ namespace std::chrono
           return tz;
           }
       }
-#else
-    // AIX stores current zone in $TZ in /etc/environment but the value
-    // is typically a POSIX time zone name, not IANA zone.
-    // https://developer.ibm.com/articles/au-aix-posix/
-    // https://www.ibm.com/support/pages/managing-time-zone-variable-posix
-    if (const char* env = std::getenv("TZ"))
-      {
-    // This will fail unless TZ contains an IANA time zone name.
-    if (auto tz = do_locate_zone(this->zones, this->links, env))
-      return tz;
-      }
 #endif

     // Default to UTC.
```

Thanks,
James


More information about the Libstdc++ mailing list