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
15 #if _LIBCPP_HAS_LOCALIZATION
17 # include <__chrono/calendar.h>
18 # include <__chrono/day.h>
19 # include <__chrono/duration.h>
20 # include <__chrono/file_clock.h>
21 # include <__chrono/hh_mm_ss.h>
22 # include <__chrono/local_info.h>
23 # include <__chrono/month.h>
24 # include <__chrono/month_weekday.h>
25 # include <__chrono/monthday.h>
26 # include <__chrono/statically_widen.h>
27 # include <__chrono/sys_info.h>
28 # include <__chrono/system_clock.h>
29 # include <__chrono/weekday.h>
30 # include <__chrono/year.h>
31 # include <__chrono/year_month.h>
32 # include <__chrono/year_month_day.h>
33 # include <__chrono/year_month_weekday.h>
34 # include <__chrono/zoned_time.h>
35 # include <__concepts/same_as.h>
36 # include <__format/format_functions.h>
37 # include <__fwd/ostream.h>
41 # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
42 # pragma GCC system_header
45 _LIBCPP_BEGIN_NAMESPACE_STD
47 # if _LIBCPP_STD_VER >= 20
51 template <class _CharT
, class _Traits
, class _Duration
>
52 requires(!treat_as_floating_point_v
<typename
_Duration::rep
> && _Duration
{1} < days
{1})
53 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
54 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const sys_time
<_Duration
>& __tp
) {
55 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%F %T}"), __tp
);
58 template <class _CharT
, class _Traits
>
59 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
60 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const sys_days
& __dp
) {
61 return __os
<< year_month_day
{__dp
};
64 template <class _CharT
, class _Traits
, class _Duration
>
65 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
66 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const file_time
<_Duration
> __tp
) {
67 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%F %T}"), __tp
);
70 template <class _CharT
, class _Traits
, class _Duration
>
71 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
72 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const local_time
<_Duration
> __tp
) {
73 return __os
<< sys_time
<_Duration
>{__tp
.time_since_epoch()};
76 // Depending on the type the return is a const _CharT* or a basic_string<_CharT>
77 template <class _CharT
, class _Period
>
78 _LIBCPP_HIDE_FROM_ABI
auto __units_suffix() {
79 // TODO FMT LWG issue the suffixes are always char and not STATICALLY-WIDEN'ed.
80 if constexpr (same_as
<typename
_Period::type
, atto
>)
81 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "as");
82 else if constexpr (same_as
<typename
_Period::type
, femto
>)
83 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "fs");
84 else if constexpr (same_as
<typename
_Period::type
, pico
>)
85 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ps");
86 else if constexpr (same_as
<typename
_Period::type
, nano
>)
87 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ns");
88 else if constexpr (same_as
<typename
_Period::type
, micro
>)
89 # if _LIBCPP_HAS_UNICODE
90 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "\u00b5s");
92 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "us");
94 else if constexpr (same_as
<typename
_Period::type
, milli
>)
95 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ms");
96 else if constexpr (same_as
<typename
_Period::type
, centi
>)
97 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "cs");
98 else if constexpr (same_as
<typename
_Period::type
, deci
>)
99 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ds");
100 else if constexpr (same_as
<typename
_Period::type
, ratio
<1>>)
101 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "s");
102 else if constexpr (same_as
<typename
_Period::type
, deca
>)
103 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "das");
104 else if constexpr (same_as
<typename
_Period::type
, hecto
>)
105 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "hs");
106 else if constexpr (same_as
<typename
_Period::type
, kilo
>)
107 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ks");
108 else if constexpr (same_as
<typename
_Period::type
, mega
>)
109 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Ms");
110 else if constexpr (same_as
<typename
_Period::type
, giga
>)
111 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Gs");
112 else if constexpr (same_as
<typename
_Period::type
, tera
>)
113 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Ts");
114 else if constexpr (same_as
<typename
_Period::type
, peta
>)
115 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Ps");
116 else if constexpr (same_as
<typename
_Period::type
, exa
>)
117 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "Es");
118 else if constexpr (same_as
<typename
_Period::type
, ratio
<60>>)
119 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "min");
120 else if constexpr (same_as
<typename
_Period::type
, ratio
<3600>>)
121 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "h");
122 else if constexpr (same_as
<typename
_Period::type
, ratio
<86400>>)
123 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "d");
124 else if constexpr (_Period::den
== 1)
125 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "[{}]s"), _Period::num
);
127 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "[{}/{}]s"), _Period::num
, _Period::den
);
130 template <class _CharT
, class _Traits
, class _Rep
, class _Period
>
131 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
132 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const duration
<_Rep
, _Period
>& __d
) {
133 basic_ostringstream
<_CharT
, _Traits
> __s
;
134 __s
.flags(__os
.flags());
135 __s
.imbue(__os
.getloc());
136 __s
.precision(__os
.precision());
137 __s
<< __d
.count() << chrono::__units_suffix
<_CharT
, _Period
>();
138 return __os
<< __s
.str();
141 template <class _CharT
, class _Traits
>
142 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>& operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const day
& __d
) {
143 return __os
<< (__d
.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%d}"), __d
)
144 // Note this error differs from the wording of the Standard. The
145 // Standard wording doesn't work well on AIX or Windows. There
146 // the formatted day seems to be either modulo 100 or completely
147 // omitted. Judging by the wording this is valid.
148 // TODO FMT Write a paper of file an LWG issue.
149 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:02} is not a valid day"),
150 static_cast<unsigned>(__d
)));
153 template <class _CharT
, class _Traits
>
154 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
155 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month
& __m
) {
156 return __os
<< (__m
.ok() ? std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%b}"), __m
)
157 : std::format(__os
.getloc(),
158 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{} is not a valid month"),
159 static_cast<unsigned>(__m
))); // TODO FMT Standard mandated locale isn't used.
162 template <class _CharT
, class _Traits
>
163 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
164 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year
& __y
) {
165 return __os
<< (__y
.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%Y}"), __y
)
166 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%Y} is not a valid year"), __y
));
169 template <class _CharT
, class _Traits
>
170 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
171 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const weekday
& __wd
) {
172 return __os
<< (__wd
.ok() ? std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%a}"), __wd
)
173 : std::format(__os
.getloc(), // TODO FMT Standard mandated locale isn't used.
174 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{} is not a valid weekday"),
175 static_cast<unsigned>(__wd
.c_encoding())));
178 template <class _CharT
, class _Traits
>
179 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
180 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const weekday_indexed
& __wdi
) {
181 auto __i
= __wdi
.index();
182 return __os
<< (__i
>= 1 && __i
<= 5
183 ? std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}[{}]"), __wdi
.weekday(), __i
)
184 : std::format(__os
.getloc(),
185 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}[{} is not a valid index]"),
190 template <class _CharT
, class _Traits
>
191 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
192 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const weekday_last
& __wdl
) {
193 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}[last]"), __wdl
.weekday());
196 template <class _CharT
, class _Traits
>
197 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
198 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_day
& __md
) {
199 // TODO FMT The Standard allows 30th of February to be printed.
200 // It would be nice to show an error message instead.
201 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/{}"), __md
.month(), __md
.day());
204 template <class _CharT
, class _Traits
>
205 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
206 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_day_last
& __mdl
) {
207 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/last"), __mdl
.month());
210 template <class _CharT
, class _Traits
>
211 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
212 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_weekday
& __mwd
) {
213 return __os
<< std::format(
214 __os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/{:L}"), __mwd
.month(), __mwd
.weekday_indexed());
217 template <class _CharT
, class _Traits
>
218 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
219 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const month_weekday_last
& __mwdl
) {
220 return __os
<< std::format(
221 __os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L}/{:L}"), __mwdl
.month(), __mwdl
.weekday_last());
224 template <class _CharT
, class _Traits
>
225 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
226 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month
& __ym
) {
227 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}"), __ym
.year(), __ym
.month());
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_day
& __ymd
) {
233 return __os
<< (__ymd
.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%F}"), __ymd
)
234 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "{:%F} is not a valid date"), __ymd
));
237 template <class _CharT
, class _Traits
>
238 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
239 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month_day_last
& __ymdl
) {
240 return __os
<< std::format(
241 __os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}"), __ymdl
.year(), __ymdl
.month_day_last());
244 template <class _CharT
, class _Traits
>
245 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
246 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month_weekday
& __ymwd
) {
247 return __os
<< std::format(
249 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}/{:L}"),
252 __ymwd
.weekday_indexed());
255 template <class _CharT
, class _Traits
>
256 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
257 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const year_month_weekday_last
& __ymwdl
) {
258 return __os
<< std::format(
260 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}/{:L}/{:L}"),
263 __ymwdl
.weekday_last());
266 template <class _CharT
, class _Traits
, class _Duration
>
267 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
268 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const hh_mm_ss
<_Duration
> __hms
) {
269 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%T}"), __hms
);
272 # if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
274 template <class _CharT
, class _Traits
>
275 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
276 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const sys_info
& __info
) {
277 // __info.abbrev is always std::basic_string<char>.
278 // Since these strings typically are short the conversion should be cheap.
279 std::basic_string
<_CharT
> __abbrev
{__info
.abbrev
.begin(), __info
.abbrev
.end()};
280 return __os
<< std::format(
281 _LIBCPP_STATICALLY_WIDEN(_CharT
, "[{:%F %T}, {:%F %T}) {:%T} {:%Q%q} \"{}\""),
284 hh_mm_ss
{__info
.offset
},
289 template <class _CharT
, class _Traits
>
290 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
291 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const local_info
& __info
) {
292 auto __result
= [&]() -> basic_string
<_CharT
> {
293 switch (__info
.result
) {
294 case local_info::unique
:
295 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "unique");
296 case local_info::nonexistent
:
297 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "non-existent");
298 case local_info::ambiguous
:
299 return _LIBCPP_STATICALLY_WIDEN(_CharT
, "ambiguous");
302 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT
, "unspecified result ({})"), __info
.result
);
306 return __os
<< std::format(
307 _LIBCPP_STATICALLY_WIDEN(_CharT
, "{}: {{{}, {}}}"), __result(), __info
.first
, __info
.second
);
310 # if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
311 template <class _CharT
, class _Traits
, class _Duration
, class _TimeZonePtr
>
312 _LIBCPP_HIDE_FROM_ABI basic_ostream
<_CharT
, _Traits
>&
313 operator<<(basic_ostream
<_CharT
, _Traits
>& __os
, const zoned_time
<_Duration
, _TimeZonePtr
>& __tp
) {
314 return __os
<< std::format(__os
.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT
, "{:L%F %T %Z}"), __tp
);
317 # endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
319 } // namespace chrono
321 # endif // if _LIBCPP_STD_VER >= 20
323 _LIBCPP_END_NAMESPACE_STD
325 #endif // _LIBCPP_HAS_LOCALIZATION
327 #endif // _LIBCPP___CHRONO_OSTREAM_H