[llvm] 1c9035d - [SystemZ][z/OS] Add UtcClock extension to chrono.h/.cpp (#67846)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 12 12:43:00 PDT 2023


Author: Yusra Syeda
Date: 2023-10-12T15:42:56-04:00
New Revision: 1c9035d1b5a9af89fccf06fa0c45f0096b063983

URL: https://github.com/llvm/llvm-project/commit/1c9035d1b5a9af89fccf06fa0c45f0096b063983
DIFF: https://github.com/llvm/llvm-project/commit/1c9035d1b5a9af89fccf06fa0c45f0096b063983.diff

LOG: [SystemZ][z/OS] Add UtcClock extension to chrono.h/.cpp (#67846)

This PR adds handling for UtcClock to chrono.h/.cpp.

---------

Co-authored-by: Yusra Syeda <yusra.syeda at ibm.com>

Added: 
    llvm/unittests/Support/UTCTimeTest.cpp

Modified: 
    llvm/include/llvm/Support/Chrono.h
    llvm/lib/Support/Chrono.cpp
    llvm/unittests/Support/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/Chrono.h b/llvm/include/llvm/Support/Chrono.h
index 9c2bd45d2803e56..71859af7c7e4a59 100644
--- a/llvm/include/llvm/Support/Chrono.h
+++ b/llvm/include/llvm/Support/Chrono.h
@@ -33,6 +33,19 @@ namespace sys {
 template <typename D = std::chrono::nanoseconds>
 using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
 
+// utc_clock and utc_time are only available since C++20. Add enough code to
+// support formatting date/time in UTC.
+class UtcClock : public std::chrono::system_clock {};
+
+template <typename D = std::chrono::nanoseconds>
+using UtcTime = std::chrono::time_point<UtcClock, D>;
+
+/// Convert a std::time_t to a UtcTime
+inline UtcTime<std::chrono::seconds> toUtcTime(std::time_t T) {
+  using namespace std::chrono;
+  return UtcTime<seconds>(seconds(T));
+}
+
 /// Convert a TimePoint to std::time_t
 inline std::time_t toTimeT(TimePoint<> TP) {
   using namespace std::chrono;
@@ -40,6 +53,13 @@ inline std::time_t toTimeT(TimePoint<> TP) {
       time_point_cast<system_clock::time_point::duration>(TP));
 }
 
+/// Convert a UtcTime to std::time_t
+inline std::time_t toTimeT(UtcTime<> TP) {
+  using namespace std::chrono;
+  return system_clock::to_time_t(time_point<system_clock, seconds>(
+      duration_cast<seconds>(TP.time_since_epoch())));
+}
+
 /// Convert a std::time_t to a TimePoint
 inline TimePoint<std::chrono::seconds>
 toTimePoint(std::time_t T) {
@@ -58,6 +78,7 @@ toTimePoint(std::time_t T, uint32_t nsec) {
 } // namespace sys
 
 raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
+raw_ostream &operator<<(raw_ostream &OS, sys::UtcTime<> TP);
 
 /// Format provider for TimePoint<>
 ///
@@ -73,6 +94,11 @@ struct format_provider<sys::TimePoint<>> {
                      StringRef Style);
 };
 
+template <> struct format_provider<sys::UtcTime<std::chrono::seconds>> {
+  static void format(const sys::UtcTime<std::chrono::seconds> &TP,
+                     llvm::raw_ostream &OS, StringRef Style);
+};
+
 namespace detail {
 template <typename Period> struct unit { static const char value[]; };
 template <typename Period> const char unit<Period>::value[] = "";

diff  --git a/llvm/lib/Support/Chrono.cpp b/llvm/lib/Support/Chrono.cpp
index 859ece8f550080c..993d200675fe572 100644
--- a/llvm/lib/Support/Chrono.cpp
+++ b/llvm/lib/Support/Chrono.cpp
@@ -40,6 +40,24 @@ static inline struct tm getStructTM(TimePoint<> TP) {
   return Storage;
 }
 
+static inline struct tm getStructTMUtc(UtcTime<> TP) {
+  struct tm Storage;
+  std::time_t OurTime = toTimeT(TP);
+
+#if defined(LLVM_ON_UNIX)
+  struct tm *LT = ::gmtime_r(&OurTime, &Storage);
+  assert(LT);
+  (void)LT;
+#endif
+#if defined(_WIN32)
+  int Error = ::gmtime_s(&Storage, &OurTime);
+  assert(!Error);
+  (void)Error;
+#endif
+
+  return Storage;
+}
+
 raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
   struct tm LT = getStructTM(TP);
   char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")];
@@ -50,12 +68,10 @@ raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
                                .count()));
 }
 
-void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
-                                          StringRef Style) {
+template <class T>
+static void format(const T &Fractional, struct tm &LT, raw_ostream &OS,
+                   StringRef Style) {
   using namespace std::chrono;
-  TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
-  auto Fractional = T - Truncated;
-  struct tm LT = getStructTM(Truncated);
   // Handle extensions first. strftime mangles unknown %x on some platforms.
   if (Style.empty()) Style = "%Y-%m-%d %H:%M:%S.%N";
   std::string Format;
@@ -90,4 +106,23 @@ void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
   OS << (Len ? Buffer : "BAD-DATE-FORMAT");
 }
 
+void format_provider<UtcTime<std::chrono::seconds>>::format(
+    const UtcTime<std::chrono::seconds> &T, raw_ostream &OS, StringRef Style) {
+  using namespace std::chrono;
+  UtcTime<seconds> Truncated =
+      UtcTime<seconds>(duration_cast<seconds>(T.time_since_epoch()));
+  auto Fractional = T - Truncated;
+  struct tm LT = getStructTMUtc(Truncated);
+  llvm::format(Fractional, LT, OS, Style);
+}
+
+void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
+                                          StringRef Style) {
+  using namespace std::chrono;
+  TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
+  auto Fractional = T - Truncated;
+  struct tm LT = getStructTM(Truncated);
+  llvm::format(Fractional, LT, OS, Style);
+}
+
 } // namespace llvm

diff  --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index dfd55b228900d8e..e1bf793536b6862 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -91,6 +91,7 @@ add_llvm_unittest(SupportTests
   TypeTraitsTest.cpp
   TrailingObjectsTest.cpp
   UnicodeTest.cpp
+  UTCTimeTest.cpp
   VersionTupleTest.cpp
   VirtualFileSystemTest.cpp
   WithColorTest.cpp

diff  --git a/llvm/unittests/Support/UTCTimeTest.cpp b/llvm/unittests/Support/UTCTimeTest.cpp
new file mode 100644
index 000000000000000..64e04d29376c3af
--- /dev/null
+++ b/llvm/unittests/Support/UTCTimeTest.cpp
@@ -0,0 +1,41 @@
+//===- unittests/Support/UTCTimeTest.cpp ----------------- ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Chrono.h"
+#include "gtest/gtest.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+
+namespace llvm {
+namespace sys {
+namespace {
+
+TEST(UTCTime, convertutc) {
+  // Get the current time.
+  time_t currentTime;
+  time(&currentTime);
+
+  // Convert with toUtcTime.
+  SmallString<15> customResultString;
+  raw_svector_ostream T(customResultString);
+  T << formatv("{0:%Y-%m-%d %H:%M:%S}", llvm::sys::toUtcTime(currentTime));
+
+  // Convert with gmtime.
+  char gmtimeResultString[20];
+  std::tm *gmtimeResult = std::gmtime(&currentTime);
+  assert(gmtimeResult != NULL);
+  std::strftime(gmtimeResultString, 20, "%Y-%m-%d %H:%M:%S", gmtimeResult);
+
+  // Compare the formatted strings.
+  EXPECT_EQ(customResultString, StringRef(gmtimeResultString, 19));
+
+}
+} // namespace
+} // namespace sys
+} // namespace llvm


        


More information about the llvm-commits mailing list