1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 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 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___CHRONO_OSTREAM_H 11 #define _LIBCPP___CHRONO_OSTREAM_H 12 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> 29 #include <__config> 30 #include <__format/format_functions.h> 31 #include <ostream> 32 #include <ratio> 33 34 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 35 # pragma GCC system_header 36 #endif 37 38 _LIBCPP_BEGIN_NAMESPACE_STD 39 40 #if _LIBCPP_STD_VER >= 20 41 42 namespace chrono { 43 44 template <class _CharT, class _Traits, class _Duration> 45 requires(!treat_as_floating_point_v<typename _Duration::rep> && _Duration{1} < days{1}) 46 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 47 operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_time<_Duration>& __tp) { 48 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp); 49 } 50 51 template <class _CharT, class _Traits> 52 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 53 operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_days& __dp) { 54 return __os << year_month_day{__dp}; 55 } 56 57 template <class _CharT, class _Traits, class _Duration> 58 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 59 operator<<(basic_ostream<_CharT, _Traits>& __os, const file_time<_Duration> __tp) { 60 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp); 61 } 62 63 template <class _CharT, class _Traits, class _Duration> 64 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 65 operator<<(basic_ostream<_CharT, _Traits>& __os, const local_time<_Duration> __tp) { 66 return __os << sys_time<_Duration>{__tp.time_since_epoch()}; 67 } 68 69 // Depending on the type the return is a const _CharT* or a basic_string<_CharT> 70 template <class _CharT, class _Period> 71 _LIBCPP_HIDE_FROM_ABI auto __units_suffix() { 72 // TODO FMT LWG issue the suffixes are always char and not STATICALLY-WIDEN'ed. 73 if constexpr (same_as<typename _Period::type, atto>) 74 return _LIBCPP_STATICALLY_WIDEN(_CharT, "as"); 75 else if constexpr (same_as<typename _Period::type, femto>) 76 return _LIBCPP_STATICALLY_WIDEN(_CharT, "fs"); 77 else if constexpr (same_as<typename _Period::type, pico>) 78 return _LIBCPP_STATICALLY_WIDEN(_CharT, "ps"); 79 else if constexpr (same_as<typename _Period::type, nano>) 80 return _LIBCPP_STATICALLY_WIDEN(_CharT, "ns"); 81 else if constexpr (same_as<typename _Period::type, micro>) 82 # ifndef _LIBCPP_HAS_NO_UNICODE 83 return _LIBCPP_STATICALLY_WIDEN(_CharT, "\u00b5s"); 84 # else 85 return _LIBCPP_STATICALLY_WIDEN(_CharT, "us"); 86 # endif 87 else if constexpr (same_as<typename _Period::type, milli>) 88 return _LIBCPP_STATICALLY_WIDEN(_CharT, "ms"); 89 else if constexpr (same_as<typename _Period::type, centi>) 90 return _LIBCPP_STATICALLY_WIDEN(_CharT, "cs"); 91 else if constexpr (same_as<typename _Period::type, deci>) 92 return _LIBCPP_STATICALLY_WIDEN(_CharT, "ds"); 93 else if constexpr (same_as<typename _Period::type, ratio<1>>) 94 return _LIBCPP_STATICALLY_WIDEN(_CharT, "s"); 95 else if constexpr (same_as<typename _Period::type, deca>) 96 return _LIBCPP_STATICALLY_WIDEN(_CharT, "das"); 97 else if constexpr (same_as<typename _Period::type, hecto>) 98 return _LIBCPP_STATICALLY_WIDEN(_CharT, "hs"); 99 else if constexpr (same_as<typename _Period::type, kilo>) 100 return _LIBCPP_STATICALLY_WIDEN(_CharT, "ks"); 101 else if constexpr (same_as<typename _Period::type, mega>) 102 return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ms"); 103 else if constexpr (same_as<typename _Period::type, giga>) 104 return _LIBCPP_STATICALLY_WIDEN(_CharT, "Gs"); 105 else if constexpr (same_as<typename _Period::type, tera>) 106 return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ts"); 107 else if constexpr (same_as<typename _Period::type, peta>) 108 return _LIBCPP_STATICALLY_WIDEN(_CharT, "Ps"); 109 else if constexpr (same_as<typename _Period::type, exa>) 110 return _LIBCPP_STATICALLY_WIDEN(_CharT, "Es"); 111 else if constexpr (same_as<typename _Period::type, ratio<60>>) 112 return _LIBCPP_STATICALLY_WIDEN(_CharT, "min"); 113 else if constexpr (same_as<typename _Period::type, ratio<3600>>) 114 return _LIBCPP_STATICALLY_WIDEN(_CharT, "h"); 115 else if constexpr (same_as<typename _Period::type, ratio<86400>>) 116 return _LIBCPP_STATICALLY_WIDEN(_CharT, "d"); 117 else if constexpr (_Period::den == 1) 118 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "[{}]s"), _Period::num); 119 else 120 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "[{}/{}]s"), _Period::num, _Period::den); 121 } 122 123 template <class _CharT, class _Traits, class _Rep, class _Period> 124 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 125 operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d) { 126 basic_ostringstream<_CharT, _Traits> __s; 127 __s.flags(__os.flags()); 128 __s.imbue(__os.getloc()); 129 __s.precision(__os.precision()); 130 __s << __d.count() << chrono::__units_suffix<_CharT, _Period>(); 131 return __os << __s.str(); 132 } 133 134 template <class _CharT, class _Traits> 135 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) { 136 return __os << (__d.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d) 137 // Note this error differs from the wording of the Standard. The 138 // Standard wording doesn't work well on AIX or Windows. There 139 // the formatted day seems to be either modulo 100 or completely 140 // omitted. Judging by the wording this is valid. 141 // TODO FMT Write a paper of file an LWG issue. 142 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), 143 static_cast<unsigned>(__d))); 144 } 145 146 template <class _CharT, class _Traits> 147 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 148 operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) { 149 return __os << (__m.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%b}"), __m) 150 : std::format(__os.getloc(), 151 _LIBCPP_STATICALLY_WIDEN(_CharT, "{} is not a valid month"), 152 static_cast<unsigned>(__m))); // TODO FMT Standard mandated locale isn't used. 153 } 154 155 template <class _CharT, class _Traits> 156 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 157 operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y) { 158 return __os << (__y.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y}"), __y) 159 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y} is not a valid year"), __y)); 160 } 161 162 template <class _CharT, class _Traits> 163 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 164 operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { 165 return __os << (__wd.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%a}"), __wd) 166 : std::format(__os.getloc(), // TODO FMT Standard mandated locale isn't used. 167 _LIBCPP_STATICALLY_WIDEN(_CharT, "{} is not a valid weekday"), 168 static_cast<unsigned>(__wd.c_encoding()))); 169 } 170 171 template <class _CharT, class _Traits> 172 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 173 operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { 174 auto __i = __wdi.index(); 175 return __os << (__i >= 1 && __i <= 5 176 ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{}]"), __wdi.weekday(), __i) 177 : std::format(__os.getloc(), 178 _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[{} is not a valid index]"), 179 __wdi.weekday(), 180 __i)); 181 } 182 183 template <class _CharT, class _Traits> 184 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 185 operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_last& __wdl) { 186 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[last]"), __wdl.weekday()); 187 } 188 189 template <class _CharT, class _Traits> 190 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 191 operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { 192 // TODO FMT The Standard allows 30th of February to be printed. 193 // It would be nice to show an error message instead. 194 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{}"), __md.month(), __md.day()); 195 } 196 197 template <class _CharT, class _Traits> 198 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 199 operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day_last& __mdl) { 200 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/last"), __mdl.month()); 201 } 202 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& __mwd) { 206 return __os << std::format( 207 __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwd.month(), __mwd.weekday_indexed()); 208 } 209 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_last& __mwdl) { 213 return __os << std::format( 214 __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwdl.month(), __mwdl.weekday_last()); 215 } 216 217 template <class _CharT, class _Traits> 218 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 219 operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym) { 220 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ym.year(), __ym.month()); 221 } 222 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& __ymd) { 226 return __os << (__ymd.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F}"), __ymd) 227 : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F} is not a valid date"), __ymd)); 228 } 229 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_last& __ymdl) { 233 return __os << std::format( 234 __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ymdl.year(), __ymdl.month_day_last()); 235 } 236 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_weekday& __ymwd) { 240 return __os << std::format( 241 __os.getloc(), 242 _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), 243 __ymwd.year(), 244 __ymwd.month(), 245 __ymwd.weekday_indexed()); 246 } 247 248 template <class _CharT, class _Traits> 249 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 250 operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl) { 251 return __os << std::format( 252 __os.getloc(), 253 _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), 254 __ymwdl.year(), 255 __ymwdl.month(), 256 __ymwdl.weekday_last()); 257 } 258 259 template <class _CharT, class _Traits, class _Duration> 260 _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 261 operator<<(basic_ostream<_CharT, _Traits>& __os, const hh_mm_ss<_Duration> __hms) { 262 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%T}"), __hms); 263 } 264 265 } // namespace chrono 266 267 #endif // if _LIBCPP_STD_VER >= 20 268 269 _LIBCPP_END_NAMESPACE_STD 270 271 #endif // _LIBCPP___CHRONO_OSTREAM_H 272