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