Skip to content

Commit 1c9035d

Browse files
ysyedaYusra Syeda
andauthored
[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 <[email protected]>
1 parent 50ece4c commit 1c9035d

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed

llvm/include/llvm/Support/Chrono.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,33 @@ namespace sys {
3333
template <typename D = std::chrono::nanoseconds>
3434
using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
3535

36+
// utc_clock and utc_time are only available since C++20. Add enough code to
37+
// support formatting date/time in UTC.
38+
class UtcClock : public std::chrono::system_clock {};
39+
40+
template <typename D = std::chrono::nanoseconds>
41+
using UtcTime = std::chrono::time_point<UtcClock, D>;
42+
43+
/// Convert a std::time_t to a UtcTime
44+
inline UtcTime<std::chrono::seconds> toUtcTime(std::time_t T) {
45+
using namespace std::chrono;
46+
return UtcTime<seconds>(seconds(T));
47+
}
48+
3649
/// Convert a TimePoint to std::time_t
3750
inline std::time_t toTimeT(TimePoint<> TP) {
3851
using namespace std::chrono;
3952
return system_clock::to_time_t(
4053
time_point_cast<system_clock::time_point::duration>(TP));
4154
}
4255

56+
/// Convert a UtcTime to std::time_t
57+
inline std::time_t toTimeT(UtcTime<> TP) {
58+
using namespace std::chrono;
59+
return system_clock::to_time_t(time_point<system_clock, seconds>(
60+
duration_cast<seconds>(TP.time_since_epoch())));
61+
}
62+
4363
/// Convert a std::time_t to a TimePoint
4464
inline TimePoint<std::chrono::seconds>
4565
toTimePoint(std::time_t T) {
@@ -58,6 +78,7 @@ toTimePoint(std::time_t T, uint32_t nsec) {
5878
} // namespace sys
5979

6080
raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
81+
raw_ostream &operator<<(raw_ostream &OS, sys::UtcTime<> TP);
6182

6283
/// Format provider for TimePoint<>
6384
///
@@ -73,6 +94,11 @@ struct format_provider<sys::TimePoint<>> {
7394
StringRef Style);
7495
};
7596

97+
template <> struct format_provider<sys::UtcTime<std::chrono::seconds>> {
98+
static void format(const sys::UtcTime<std::chrono::seconds> &TP,
99+
llvm::raw_ostream &OS, StringRef Style);
100+
};
101+
76102
namespace detail {
77103
template <typename Period> struct unit { static const char value[]; };
78104
template <typename Period> const char unit<Period>::value[] = "";

llvm/lib/Support/Chrono.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ static inline struct tm getStructTM(TimePoint<> TP) {
4040
return Storage;
4141
}
4242

43+
static inline struct tm getStructTMUtc(UtcTime<> TP) {
44+
struct tm Storage;
45+
std::time_t OurTime = toTimeT(TP);
46+
47+
#if defined(LLVM_ON_UNIX)
48+
struct tm *LT = ::gmtime_r(&OurTime, &Storage);
49+
assert(LT);
50+
(void)LT;
51+
#endif
52+
#if defined(_WIN32)
53+
int Error = ::gmtime_s(&Storage, &OurTime);
54+
assert(!Error);
55+
(void)Error;
56+
#endif
57+
58+
return Storage;
59+
}
60+
4361
raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
4462
struct tm LT = getStructTM(TP);
4563
char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")];
@@ -50,12 +68,10 @@ raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
5068
.count()));
5169
}
5270

53-
void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
54-
StringRef Style) {
71+
template <class T>
72+
static void format(const T &Fractional, struct tm &LT, raw_ostream &OS,
73+
StringRef Style) {
5574
using namespace std::chrono;
56-
TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
57-
auto Fractional = T - Truncated;
58-
struct tm LT = getStructTM(Truncated);
5975
// Handle extensions first. strftime mangles unknown %x on some platforms.
6076
if (Style.empty()) Style = "%Y-%m-%d %H:%M:%S.%N";
6177
std::string Format;
@@ -90,4 +106,23 @@ void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
90106
OS << (Len ? Buffer : "BAD-DATE-FORMAT");
91107
}
92108

109+
void format_provider<UtcTime<std::chrono::seconds>>::format(
110+
const UtcTime<std::chrono::seconds> &T, raw_ostream &OS, StringRef Style) {
111+
using namespace std::chrono;
112+
UtcTime<seconds> Truncated =
113+
UtcTime<seconds>(duration_cast<seconds>(T.time_since_epoch()));
114+
auto Fractional = T - Truncated;
115+
struct tm LT = getStructTMUtc(Truncated);
116+
llvm::format(Fractional, LT, OS, Style);
117+
}
118+
119+
void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
120+
StringRef Style) {
121+
using namespace std::chrono;
122+
TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
123+
auto Fractional = T - Truncated;
124+
struct tm LT = getStructTM(Truncated);
125+
llvm::format(Fractional, LT, OS, Style);
126+
}
127+
93128
} // namespace llvm

llvm/unittests/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ add_llvm_unittest(SupportTests
9191
TypeTraitsTest.cpp
9292
TrailingObjectsTest.cpp
9393
UnicodeTest.cpp
94+
UTCTimeTest.cpp
9495
VersionTupleTest.cpp
9596
VirtualFileSystemTest.cpp
9697
WithColorTest.cpp
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===- unittests/Support/UTCTimeTest.cpp ----------------- ----------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Support/Chrono.h"
10+
#include "gtest/gtest.h"
11+
#include "llvm/Support/CommandLine.h"
12+
#include "llvm/Support/FormatProviders.h"
13+
#include "llvm/Support/FormatVariadic.h"
14+
15+
namespace llvm {
16+
namespace sys {
17+
namespace {
18+
19+
TEST(UTCTime, convertutc) {
20+
// Get the current time.
21+
time_t currentTime;
22+
time(&currentTime);
23+
24+
// Convert with toUtcTime.
25+
SmallString<15> customResultString;
26+
raw_svector_ostream T(customResultString);
27+
T << formatv("{0:%Y-%m-%d %H:%M:%S}", llvm::sys::toUtcTime(currentTime));
28+
29+
// Convert with gmtime.
30+
char gmtimeResultString[20];
31+
std::tm *gmtimeResult = std::gmtime(&currentTime);
32+
assert(gmtimeResult != NULL);
33+
std::strftime(gmtimeResultString, 20, "%Y-%m-%d %H:%M:%S", gmtimeResult);
34+
35+
// Compare the formatted strings.
36+
EXPECT_EQ(customResultString, StringRef(gmtimeResultString, 19));
37+
38+
}
39+
} // namespace
40+
} // namespace sys
41+
} // namespace llvm

0 commit comments

Comments
 (0)