2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___CHRONO_OSTREAM_H
11 #define _LIBCPP___CHRONO_OSTREAM_H
13 #include <__chrono/calendar.h>
14 #include <__chrono/day.h>
15 #include <__chrono/duration.h>
16 #include <__chrono/file_clock.h>
17 #include <__chrono/hh_mm_ss.h>
18 #include <__chrono/month.h>
19 #include <__chrono/month_weekday.h>
20 #include <__chrono/monthday.h>
21 #include <__chrono/statically_widen.h>
22 #include <__chrono/system_clock.h>
23 #include <__chrono/weekday.h>
24 #include <__chrono/year.h>
25 #include <__chrono/year_month.h>
26 #include <__chrono/year_month_day.h>
27 #include <__chrono/year_month_weekday.h>
28 #include <__concepts/same_as.h>
30 #include <__format/format_functions.h>
34 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
35 # pragma GCC system_header
38 _LIBCPP_BEGIN_NAMESPACE_STD
40 #if _LIBCPP_STD_VER >= 20
44 template <class _CharT
, class _Traits
, class _Duration
>
45 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
46 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const sys_time
<_Duration
> __tp
) {
47 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%F %T}"), __tp
);
50 template <class _CharT
, class _Traits
, class _Duration
>
51 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
52 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const file_time
<_Duration
> __tp
) {
53 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%F %T}"), __tp
);
56 template <class _CharT
, class _Traits
, class _Duration
>
57 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
58 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const local_time
<_Duration
> __tp
) {
59 return __os
<< sys_time
<_Duration
>{__tp
.time_since_epoch()};
62 // Depending on the type the return is a const _CharT* or a basic_string<_CharT>
63 template <class _CharT
, class _Period
>
64 _LIBCPP_HIDE_FROM_ABI
auto __units_suffix() {
65 // TODO FMT LWG issue the suffixes are always char and not STATICALLY-WIDEN'ed.
66 if constexpr (same_as
<typename
_Period::type
, atto
>)
67 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "as");
68 else if constexpr (same_as
<typename
_Period::type
, femto
>)
69 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "fs");
70 else if constexpr (same_as
<typename
_Period::type
, pico
>)
71 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ps");
72 else if constexpr (same_as
<typename
_Period::type
, nano
>)
73 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ns");
74 else if constexpr (same_as
<typename
_Period::type
, micro
>)
75 # ifndef _LIBCPP_HAS_NO_UNICODE
76 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "\u00b5s");
78 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "us");
80 else if constexpr (same_as
<typename
_Period::type
, milli
>)
81 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ms");
82 else if constexpr (same_as
<typename
_Period::type
, centi
>)
83 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "cs");
84 else if constexpr (same_as
<typename
_Period::type
, deci
>)
85 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ds");
86 else if constexpr (same_as
<typename
_Period::type
, ratio
<1>>)
87 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "s");
88 else if constexpr (same_as
<typename
_Period::type
, deca
>)
89 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "das");
90 else if constexpr (same_as
<typename
_Period::type
, hecto
>)
91 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "hs");
92 else if constexpr (same_as
<typename
_Period::type
, kilo
>)
93 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ks");
94 else if constexpr (same_as
<typename
_Period::type
, mega
>)
95 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Ms");
96 else if constexpr (same_as
<typename
_Period::type
, giga
>)
97 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Gs");
98 else if constexpr (same_as
<typename
_Period::type
, tera
>)
99 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Ts");
100 else if constexpr (same_as
<typename
_Period::type
, peta
>)
101 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Ps");
102 else if constexpr (same_as
<typename
_Period::type
, exa
>)
103 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Es");
104 else if constexpr (same_as
<typename
_Period::type
, ratio
<60>>)
105 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "min");
106 else if constexpr (same_as
<typename
_Period::type
, ratio
<3600>>)
107 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "h");
108 else if constexpr (same_as
<typename
_Period::type
, ratio
<86400>>)
109 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "d");
110 else if constexpr (_Period::den
== 1)
111 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "[{}]s"), _Period::num
);
113 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "[{}/{}]s"), _Period::num
, _Period::den
);
116 template <class _CharT
, class _Traits
, class _Rep
, class _Period
>
117 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
118 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const duration
<_Rep
, _Period
>& __d
) {
119 basic_ostringstream
<_CharT
, _Traits
> __s
;
120 __s
.flags(__os
.flags());
121 __s
.imbue(__os
.getloc());
122 __s
.precision(__os
.precision());
123 __s
<< __d
.count() << chrono::__units_suffix
<_CharT
, _Period
>();
124 return __os
<< __s
.str();
127 template <class _CharT
, class _Traits
>
128 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>& operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const day
& __d
) {
129 return __os
<< (__d
.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%d}"), __d
)
130 // Note this error differs from the wording of the Standard. The
131 // Standard wording doesn't work well on AIX or Windows. There
132 // the formatted day seems to be either modulo 100 or completely
133 // omitted. Judging by the wording this is valid.
134 // TODO FMT Write a paper of file an LWG issue.
135 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:02} is not a valid day"),
136 static_cast<unsigned>(__d
)));
139 template <class _CharT
, class _Traits
>
140 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
141 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month
& __m
) {
142 return __os
<< (__m
.ok() ? std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%b}"), __m
)
143 : std::format(__os
.getloc(),
144 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{} is not a valid month"),
145 static_cast<unsigned>(__m
))); // TODO FMT Standard mandated locale isn't used.
148 template <class _CharT
, class _Traits
>
149 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
150 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year
& __y
) {
151 return __os
<< (__y
.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%Y}"), __y
)
152 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%Y} is not a valid year"), __y
));
155 template <class _CharT
, class _Traits
>
156 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
157 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const weekday
& __wd
) {
158 return __os
<< (__wd
.ok() ? std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%a}"), __wd
)
159 : std::format(__os
.getloc(), // TODO FMT Standard mandated locale isn't used.
160 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{} is not a valid weekday"),
161 static_cast<unsigned>(__wd
.c_encoding())));
164 template <class _CharT
, class _Traits
>
165 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
166 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const weekday_indexed
& __wdi
) {
167 auto __i
= __wdi
.index();
168 return __os
<< (__i
>= 1 && __i
<= 5
169 ? std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}[{}]"), __wdi
.weekday(), __i
)
170 : std::format(__os
.getloc(),
171 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}[{} is not a valid index]"),
176 template <class _CharT
, class _Traits
>
177 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
178 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const weekday_last
& __wdl
) {
179 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}[last]"), __wdl
.weekday());
182 template <class _CharT
, class _Traits
>
183 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
184 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_day
& __md
) {
185 // TODO FMT The Standard allows 30th of February to be printed.
186 // It would be nice to show an error message instead.
187 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/{}"), __md
.month(), __md
.day());
190 template <class _CharT
, class _Traits
>
191 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
192 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_day_last
& __mdl
) {
193 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/last"), __mdl
.month());
196 template <class _CharT
, class _Traits
>
197 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
198 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_weekday
& __mwd
) {
199 return __os
<< std::format(
200 __os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/{:L}"), __mwd
.month(), __mwd
.weekday_indexed());
203 template <class _CharT
, class _Traits
>
204 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
205 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_weekday_last
& __mwdl
) {
206 return __os
<< std::format(
207 __os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/{:L}"), __mwdl
.month(), __mwdl
.weekday_last());
210 template <class _CharT
, class _Traits
>
211 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
212 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month
& __ym
) {
213 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}"), __ym
.year(), __ym
.month());
216 template <class _CharT
, class _Traits
>
217 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
218 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month_day
& __ymd
) {
219 return __os
<< (__ymd
.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%F}"), __ymd
)
220 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%F} is not a valid date"), __ymd
));
223 template <class _CharT
, class _Traits
>
224 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
225 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month_day_last
& __ymdl
) {
226 return __os
<< std::format(
227 __os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}"), __ymdl
.year(), __ymdl
.month_day_last());
230 template <class _CharT
, class _Traits
>
231 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
232 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month_weekday
& __ymwd
) {
233 return __os
<< std::format(
235 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}/{:L}"),
238 __ymwd
.weekday_indexed());
241 template <class _CharT
, class _Traits
>
242 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
243 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month_weekday_last
& __ymwdl
) {
244 return __os
<< std::format(
246 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}/{:L}"),
249 __ymwdl
.weekday_last());
252 template <class _CharT
, class _Traits
, class _Duration
>
253 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
254 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const hh_mm_ss
<_Duration
> __hms
) {
255 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%T}"), __hms
);
258 } // namespace chrono
260 #endif // if _LIBCPP_STD_VER >= 20
262 _LIBCPP_END_NAMESPACE_STD
264 #endif // _LIBCPP___CHRONO_OSTREAM_H