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 _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); 48 } 49 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); 54 } 55 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()}; 60 } 61 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"); 77 # else 78 return _LIBCPP_STATICALLY_WIDEN(_CharT, "us"); 79 # endif 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); 112 else 113 return std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "[{}/{}]s"), _Period::num, _Period::den); 114 } 115 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(); 125 } 126 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))); 137 } 138 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. 146 } 147 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)); 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 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()))); 162 } 163 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]"), 172 __wdi.weekday(), 173 __i)); 174 } 175 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()); 180 } 181 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()); 188 } 189 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()); 194 } 195 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()); 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_last& __mwdl) { 206 return __os << std::format( 207 __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwdl.month(), __mwdl.weekday_last()); 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 year_month& __ym) { 213 return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ym.year(), __ym.month()); 214 } 215 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)); 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_last& __ymdl) { 226 return __os << std::format( 227 __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ymdl.year(), __ymdl.month_day_last()); 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_weekday& __ymwd) { 233 return __os << std::format( 234 __os.getloc(), 235 _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), 236 __ymwd.year(), 237 __ymwd.month(), 238 __ymwd.weekday_indexed()); 239 } 240 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( 245 __os.getloc(), 246 _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}/{:L}"), 247 __ymwdl.year(), 248 __ymwdl.month(), 249 __ymwdl.weekday_last()); 250 } 251 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); 256 } 257 258 } // namespace chrono 259 260 #endif // if _LIBCPP_STD_VER >= 20 261 262 _LIBCPP_END_NAMESPACE_STD 263 264 #endif // _LIBCPP___CHRONO_OSTREAM_H 265