1 //===- Support/Chrono.cpp - Utilities for Timing Manipulation ---*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/Chrono.h"
10 #include "llvm/Config/llvm-config.h"
11 #include "llvm/Support/Format.h"
12 #include "llvm/Support/raw_ostream.h"
18 const char llvm::detail::unit
<std::ratio
<3600>>::value
[] = "h";
19 const char llvm::detail::unit
<std::ratio
<60>>::value
[] = "m";
20 const char llvm::detail::unit
<std::ratio
<1>>::value
[] = "s";
21 const char llvm::detail::unit
<std::milli
>::value
[] = "ms";
22 const char llvm::detail::unit
<std::micro
>::value
[] = "us";
23 const char llvm::detail::unit
<std::nano
>::value
[] = "ns";
25 static inline struct tm
getStructTM(TimePoint
<> TP
) {
27 std::time_t OurTime
= toTimeT(TP
);
29 #if defined(LLVM_ON_UNIX)
30 struct tm
*LT
= ::localtime_r(&OurTime
, &Storage
);
35 int Error
= ::localtime_s(&Storage
, &OurTime
);
43 static inline struct tm
getStructTMUtc(UtcTime
<> TP
) {
45 std::time_t OurTime
= toTimeT(TP
);
47 #if defined(LLVM_ON_UNIX)
48 struct tm
*LT
= ::gmtime_r(&OurTime
, &Storage
);
53 int Error
= ::gmtime_s(&Storage
, &OurTime
);
61 raw_ostream
&operator<<(raw_ostream
&OS
, TimePoint
<> TP
) {
62 struct tm LT
= getStructTM(TP
);
63 char Buffer
[sizeof("YYYY-MM-DD HH:MM:SS")];
64 strftime(Buffer
, sizeof(Buffer
), "%Y-%m-%d %H:%M:%S", <
);
65 return OS
<< Buffer
<< '.'
67 long((TP
.time_since_epoch() % std::chrono::seconds(1))
72 static void format(const T
&Fractional
, struct tm
<
, raw_ostream
&OS
,
74 using namespace std::chrono
;
75 // Handle extensions first. strftime mangles unknown %x on some platforms.
76 if (Style
.empty()) Style
= "%Y-%m-%d %H:%M:%S.%N";
78 raw_string_ostream
FStream(Format
);
79 for (unsigned I
= 0; I
< Style
.size(); ++I
) {
80 if (Style
[I
] == '%' && Style
.size() > I
+ 1) switch (Style
[I
+ 1]) {
81 case 'L': // Milliseconds, from Ruby.
82 FStream
<< llvm::format(
83 "%.3lu", (long)duration_cast
<milliseconds
>(Fractional
).count());
86 case 'f': // Microseconds, from Python.
87 FStream
<< llvm::format(
88 "%.6lu", (long)duration_cast
<microseconds
>(Fractional
).count());
91 case 'N': // Nanoseconds, from date(1).
92 FStream
<< llvm::format(
93 "%.9lu", (long)duration_cast
<nanoseconds
>(Fractional
).count());
96 case '%': // Consume %%, so %%f parses as (%%)f not %(%f)
104 char Buffer
[256]; // Should be enough for anywhen.
105 size_t Len
= strftime(Buffer
, sizeof(Buffer
), Format
.c_str(), <
);
106 OS
<< (Len
? Buffer
: "BAD-DATE-FORMAT");
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
);
119 void format_provider
<TimePoint
<>>::format(const TimePoint
<> &T
, raw_ostream
&OS
,
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
);