formatter.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  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. #ifndef _LIBCPP___CHRONO_FORMATTER_H
  10. #define _LIBCPP___CHRONO_FORMATTER_H
  11. #include <__chrono/calendar.h>
  12. #include <__chrono/convert_to_tm.h>
  13. #include <__chrono/day.h>
  14. #include <__chrono/duration.h>
  15. #include <__chrono/hh_mm_ss.h>
  16. #include <__chrono/month.h>
  17. #include <__chrono/month_weekday.h>
  18. #include <__chrono/monthday.h>
  19. #include <__chrono/ostream.h>
  20. #include <__chrono/parser_std_format_spec.h>
  21. #include <__chrono/statically_widen.h>
  22. #include <__chrono/time_point.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/arithmetic.h>
  29. #include <__concepts/same_as.h>
  30. #include <__config>
  31. #include <__format/concepts.h>
  32. #include <__format/format_error.h>
  33. #include <__format/format_functions.h>
  34. #include <__format/format_parse_context.h>
  35. #include <__format/formatter.h>
  36. #include <__format/formatter_output.h>
  37. #include <__format/parser_std_format_spec.h>
  38. #include <__memory/addressof.h>
  39. #include <cmath>
  40. #include <ctime>
  41. #include <sstream>
  42. #include <string>
  43. #include <string_view>
  44. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  45. # pragma GCC system_header
  46. #endif
  47. _LIBCPP_BEGIN_NAMESPACE_STD
  48. #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
  49. namespace __formatter {
  50. /// Formats a time based on a tm struct.
  51. ///
  52. /// This formatter passes the formatting to time_put which uses strftime. When
  53. /// the value is outside the valid range it's unspecified what strftime will
  54. /// output. For example weekday 8 can print 1 when the day is processed modulo
  55. /// 7 since that handles the Sunday for 0-based weekday. It can also print 8 if
  56. /// 7 is handled as a special case.
  57. ///
  58. /// The Standard doesn't specify what to do in this case so the result depends
  59. /// on the result of the underlying code.
  60. ///
  61. /// \pre When the (abbreviated) weekday or month name are used, the caller
  62. /// validates whether the value is valid. So the caller handles that
  63. /// requirement of Table 97: Meaning of conversion specifiers
  64. /// [tab:time.format.spec].
  65. ///
  66. /// When no chrono-specs are provided it uses the stream formatter.
  67. // For tiny ratios it's not possible to convert a duration to a hh_mm_ss. This
  68. // fails compile-time due to the limited precision of the ratio (64-bit is too
  69. // small). Therefore a duration uses its own conversion.
  70. template <class _CharT, class _Tp>
  71. requires(chrono::__is_duration<_Tp>::value)
  72. _LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) {
  73. __sstr << std::use_facet<numpunct<_CharT>>(__sstr.getloc()).decimal_point();
  74. auto __fraction = __value - chrono::duration_cast<chrono::seconds>(__value);
  75. if constexpr (chrono::treat_as_floating_point_v<typename _Tp::rep>)
  76. // When the floating-point value has digits itself they are ignored based
  77. // on the wording in [tab:time.format.spec]
  78. // If the precision of the input cannot be exactly represented with
  79. // seconds, then the format is a decimal floating-point number with a
  80. // fixed format and a precision matching that of the precision of the
  81. // input (or to a microseconds precision if the conversion to
  82. // floating-point decimal seconds cannot be made within 18 fractional
  83. // digits).
  84. //
  85. // This matches the behaviour of MSVC STL, fmtlib interprets this
  86. // differently and uses 3 decimals.
  87. // https://godbolt.org/z/6dsbnW8ba
  88. std::format_to(std::ostreambuf_iterator<_CharT>{__sstr},
  89. _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"),
  90. __fraction.count(),
  91. chrono::hh_mm_ss<_Tp>::fractional_width);
  92. else
  93. std::format_to(std::ostreambuf_iterator<_CharT>{__sstr},
  94. _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"),
  95. __fraction.count(),
  96. chrono::hh_mm_ss<_Tp>::fractional_width);
  97. }
  98. template <class _Tp>
  99. consteval bool __use_fraction() {
  100. if constexpr (chrono::__is_duration<_Tp>::value)
  101. return chrono::hh_mm_ss<_Tp>::fractional_width;
  102. else
  103. return false;
  104. }
  105. template <class _CharT>
  106. _LIBCPP_HIDE_FROM_ABI void __format_year(int __year, basic_stringstream<_CharT>& __sstr) {
  107. if (__year < 0) {
  108. __sstr << _CharT('-');
  109. __year = -__year;
  110. }
  111. // TODO FMT Write an issue
  112. // If the result has less than four digits it is zero-padded with 0 to two digits.
  113. // is less -> has less
  114. // left-padded -> zero-padded, otherwise the proper value would be 000-0.
  115. // Note according to the wording it should be left padded, which is odd.
  116. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:04}"), __year);
  117. }
  118. template <class _CharT>
  119. _LIBCPP_HIDE_FROM_ABI void __format_century(int __year, basic_stringstream<_CharT>& __sstr) {
  120. // TODO FMT Write an issue
  121. // [tab:time.format.spec]
  122. // %C The year divided by 100 using floored division. If the result is a
  123. // single decimal digit, it is prefixed with 0.
  124. bool __negative = __year < 0;
  125. int __century = (__year - (99 * __negative)) / 100; // floored division
  126. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), __century);
  127. }
  128. template <class _CharT, class _Tp>
  129. _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
  130. const _Tp& __value, basic_stringstream<_CharT>& __sstr, basic_string_view<_CharT> __chrono_specs) {
  131. tm __t = std::__convert_to_tm<tm>(__value);
  132. const auto& __facet = std::use_facet<time_put<_CharT>>(__sstr.getloc());
  133. for (auto __it = __chrono_specs.begin(); __it != __chrono_specs.end(); ++__it) {
  134. if (*__it == _CharT('%')) {
  135. auto __s = __it;
  136. ++__it;
  137. // We only handle the types that can't be directly handled by time_put.
  138. // (as an optimization n, t, and % are also handled directly.)
  139. switch (*__it) {
  140. case _CharT('n'):
  141. __sstr << _CharT('\n');
  142. break;
  143. case _CharT('t'):
  144. __sstr << _CharT('\t');
  145. break;
  146. case _CharT('%'):
  147. __sstr << *__it;
  148. break;
  149. case _CharT('C'): {
  150. // strftime's output is only defined in the range [00, 99].
  151. int __year = __t.tm_year + 1900;
  152. if (__year < 1000 || __year > 9999)
  153. __formatter::__format_century(__year, __sstr);
  154. else
  155. __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
  156. } break;
  157. case _CharT('j'):
  158. if constexpr (chrono::__is_duration<_Tp>::value)
  159. // Converting a duration where the period has a small ratio to days
  160. // may fail to compile. This due to loss of precision in the
  161. // conversion. In order to avoid that issue convert to seconds as
  162. // an intemediate step.
  163. __sstr << chrono::duration_cast<chrono::days>(chrono::duration_cast<chrono::seconds>(__value)).count();
  164. else
  165. __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
  166. break;
  167. case _CharT('q'):
  168. if constexpr (chrono::__is_duration<_Tp>::value) {
  169. __sstr << chrono::__units_suffix<_CharT, typename _Tp::period>();
  170. break;
  171. }
  172. __builtin_unreachable();
  173. case _CharT('Q'):
  174. // TODO FMT Determine the proper ideas
  175. // - Should it honour the precision?
  176. // - Shoult it honour the locale setting for the separators?
  177. // The wording for Q doesn't use the word locale and the effect of
  178. // precision is unspecified.
  179. //
  180. // MSVC STL ignores precision but uses separator
  181. // FMT honours precision and has a bug for separator
  182. // https://godbolt.org/z/78b7sMxns
  183. if constexpr (chrono::__is_duration<_Tp>::value) {
  184. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{}"), __value.count());
  185. break;
  186. }
  187. __builtin_unreachable();
  188. case _CharT('S'):
  189. case _CharT('T'):
  190. __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
  191. if constexpr (__use_fraction<_Tp>())
  192. __formatter::__format_sub_seconds(__value, __sstr);
  193. break;
  194. // Unlike time_put and strftime the formatting library requires %Y
  195. //
  196. // [tab:time.format.spec]
  197. // The year as a decimal number. If the result is less than four digits
  198. // it is left-padded with 0 to four digits.
  199. //
  200. // This means years in the range (-1000, 1000) need manual formatting.
  201. // It's unclear whether %EY needs the same treatment. For example the
  202. // Japanese EY contains the era name and year. This is zero-padded to 2
  203. // digits in time_put (note that older glibc versions didn't do
  204. // padding.) However most eras won't reach 100 years, let alone 1000.
  205. // So padding to 4 digits seems unwanted for Japanese.
  206. //
  207. // The same applies to %Ex since that too depends on the era.
  208. //
  209. // %x the locale's date representation is currently doesn't handle the
  210. // zero-padding too.
  211. //
  212. // The 4 digits can be implemented better at a later time. On POSIX
  213. // systems the required information can be extracted by nl_langinfo
  214. // https://man7.org/linux/man-pages/man3/nl_langinfo.3.html
  215. //
  216. // Note since year < -1000 is expected to be rare it uses the more
  217. // expensive year routine.
  218. //
  219. // TODO FMT evaluate the comment above.
  220. # if defined(__GLIBC__) || defined(_AIX)
  221. case _CharT('y'):
  222. // Glibc fails for negative values, AIX for positive values too.
  223. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), (std::abs(__t.tm_year + 1900)) % 100);
  224. break;
  225. # endif // defined(__GLIBC__) || defined(_AIX)
  226. case _CharT('Y'): {
  227. int __year = __t.tm_year + 1900;
  228. if (__year < 1000)
  229. __formatter::__format_year(__year, __sstr);
  230. else
  231. __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
  232. } break;
  233. case _CharT('F'): {
  234. int __year = __t.tm_year + 1900;
  235. if (__year < 1000) {
  236. __formatter::__format_year(__year, __sstr);
  237. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday);
  238. } else
  239. __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
  240. } break;
  241. case _CharT('O'):
  242. if constexpr (__use_fraction<_Tp>()) {
  243. // Handle OS using the normal representation for the non-fractional
  244. // part. There seems to be no locale information regarding how the
  245. // fractional part should be formatted.
  246. if (*(__it + 1) == 'S') {
  247. ++__it;
  248. __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
  249. __formatter::__format_sub_seconds(__value, __sstr);
  250. break;
  251. }
  252. }
  253. [[fallthrough]];
  254. case _CharT('E'):
  255. ++__it;
  256. [[fallthrough]];
  257. default:
  258. __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
  259. break;
  260. }
  261. } else {
  262. __sstr << *__it;
  263. }
  264. }
  265. }
  266. template <class _Tp>
  267. _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) {
  268. if constexpr (same_as<_Tp, chrono::day>)
  269. return true;
  270. else if constexpr (same_as<_Tp, chrono::month>)
  271. return __value.ok();
  272. else if constexpr (same_as<_Tp, chrono::year>)
  273. return true;
  274. else if constexpr (same_as<_Tp, chrono::weekday>)
  275. return true;
  276. else if constexpr (same_as<_Tp, chrono::weekday_indexed>)
  277. return true;
  278. else if constexpr (same_as<_Tp, chrono::weekday_last>)
  279. return true;
  280. else if constexpr (same_as<_Tp, chrono::month_day>)
  281. return true;
  282. else if constexpr (same_as<_Tp, chrono::month_day_last>)
  283. return true;
  284. else if constexpr (same_as<_Tp, chrono::month_weekday>)
  285. return true;
  286. else if constexpr (same_as<_Tp, chrono::month_weekday_last>)
  287. return true;
  288. else if constexpr (same_as<_Tp, chrono::year_month>)
  289. return true;
  290. else if constexpr (same_as<_Tp, chrono::year_month_day>)
  291. return __value.ok();
  292. else if constexpr (same_as<_Tp, chrono::year_month_day_last>)
  293. return __value.ok();
  294. else if constexpr (same_as<_Tp, chrono::year_month_weekday>)
  295. return __value.weekday().ok();
  296. else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>)
  297. return __value.weekday().ok();
  298. else
  299. static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
  300. }
  301. template <class _Tp>
  302. _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) {
  303. if constexpr (same_as<_Tp, chrono::day>)
  304. return true;
  305. else if constexpr (same_as<_Tp, chrono::month>)
  306. return __value.ok();
  307. else if constexpr (same_as<_Tp, chrono::year>)
  308. return true;
  309. else if constexpr (same_as<_Tp, chrono::weekday>)
  310. return __value.ok();
  311. else if constexpr (same_as<_Tp, chrono::weekday_indexed>)
  312. return __value.weekday().ok();
  313. else if constexpr (same_as<_Tp, chrono::weekday_last>)
  314. return __value.weekday().ok();
  315. else if constexpr (same_as<_Tp, chrono::month_day>)
  316. return true;
  317. else if constexpr (same_as<_Tp, chrono::month_day_last>)
  318. return true;
  319. else if constexpr (same_as<_Tp, chrono::month_weekday>)
  320. return __value.weekday_indexed().ok();
  321. else if constexpr (same_as<_Tp, chrono::month_weekday_last>)
  322. return __value.weekday_indexed().ok();
  323. else if constexpr (same_as<_Tp, chrono::year_month>)
  324. return true;
  325. else if constexpr (same_as<_Tp, chrono::year_month_day>)
  326. return __value.ok();
  327. else if constexpr (same_as<_Tp, chrono::year_month_day_last>)
  328. return __value.ok();
  329. else if constexpr (same_as<_Tp, chrono::year_month_weekday>)
  330. return __value.weekday().ok();
  331. else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>)
  332. return __value.weekday().ok();
  333. else
  334. static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
  335. }
  336. template <class _Tp>
  337. _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) {
  338. if constexpr (same_as<_Tp, chrono::day>)
  339. return true;
  340. else if constexpr (same_as<_Tp, chrono::month>)
  341. return __value.ok();
  342. else if constexpr (same_as<_Tp, chrono::year>)
  343. return true;
  344. else if constexpr (same_as<_Tp, chrono::weekday>)
  345. return true;
  346. else if constexpr (same_as<_Tp, chrono::weekday_indexed>)
  347. return true;
  348. else if constexpr (same_as<_Tp, chrono::weekday_last>)
  349. return true;
  350. else if constexpr (same_as<_Tp, chrono::month_day>)
  351. return true;
  352. else if constexpr (same_as<_Tp, chrono::month_day_last>)
  353. return true;
  354. else if constexpr (same_as<_Tp, chrono::month_weekday>)
  355. return true;
  356. else if constexpr (same_as<_Tp, chrono::month_weekday_last>)
  357. return true;
  358. else if constexpr (same_as<_Tp, chrono::year_month>)
  359. return true;
  360. else if constexpr (same_as<_Tp, chrono::year_month_day>)
  361. return __value.ok();
  362. else if constexpr (same_as<_Tp, chrono::year_month_day_last>)
  363. return __value.ok();
  364. else if constexpr (same_as<_Tp, chrono::year_month_weekday>)
  365. return __value.ok();
  366. else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>)
  367. return __value.ok();
  368. else
  369. static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
  370. }
  371. template <class _Tp>
  372. _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) {
  373. if constexpr (same_as<_Tp, chrono::day>)
  374. return true;
  375. else if constexpr (same_as<_Tp, chrono::month>)
  376. return __value.ok();
  377. else if constexpr (same_as<_Tp, chrono::year>)
  378. return true;
  379. else if constexpr (same_as<_Tp, chrono::weekday>)
  380. return true;
  381. else if constexpr (same_as<_Tp, chrono::weekday_indexed>)
  382. return true;
  383. else if constexpr (same_as<_Tp, chrono::weekday_last>)
  384. return true;
  385. else if constexpr (same_as<_Tp, chrono::month_day>)
  386. return __value.month().ok();
  387. else if constexpr (same_as<_Tp, chrono::month_day_last>)
  388. return __value.month().ok();
  389. else if constexpr (same_as<_Tp, chrono::month_weekday>)
  390. return __value.month().ok();
  391. else if constexpr (same_as<_Tp, chrono::month_weekday_last>)
  392. return __value.month().ok();
  393. else if constexpr (same_as<_Tp, chrono::year_month>)
  394. return __value.month().ok();
  395. else if constexpr (same_as<_Tp, chrono::year_month_day>)
  396. return __value.month().ok();
  397. else if constexpr (same_as<_Tp, chrono::year_month_day_last>)
  398. return __value.month().ok();
  399. else if constexpr (same_as<_Tp, chrono::year_month_weekday>)
  400. return __value.month().ok();
  401. else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>)
  402. return __value.month().ok();
  403. else
  404. static_assert(sizeof(_Tp) == 0, "Add the missing type specialization");
  405. }
  406. template <class _CharT, class _Tp>
  407. _LIBCPP_HIDE_FROM_ABI auto
  408. __format_chrono(const _Tp& __value,
  409. auto& __ctx,
  410. __format_spec::__parsed_specifications<_CharT> __specs,
  411. basic_string_view<_CharT> __chrono_specs) -> decltype(__ctx.out()) {
  412. basic_stringstream<_CharT> __sstr;
  413. // [time.format]/2
  414. // 2.1 - the "C" locale if the L option is not present in chrono-format-spec, otherwise
  415. // 2.2 - the locale passed to the formatting function if any, otherwise
  416. // 2.3 - the global locale.
  417. // Note that the __ctx's locale() call does 2.2 and 2.3.
  418. if (__specs.__chrono_.__locale_specific_form_)
  419. __sstr.imbue(__ctx.locale());
  420. else
  421. __sstr.imbue(locale::classic());
  422. if (__chrono_specs.empty())
  423. __sstr << __value;
  424. else {
  425. if constexpr (chrono::__is_duration<_Tp>::value) {
  426. if (__value < __value.zero())
  427. __sstr << _CharT('-');
  428. __formatter::__format_chrono_using_chrono_specs(chrono::abs(__value), __sstr, __chrono_specs);
  429. // TODO FMT When keeping the precision it will truncate the string.
  430. // Note that the behaviour what the precision does isn't specified.
  431. __specs.__precision_ = -1;
  432. } else {
  433. // Test __weekday_name_ before __weekday_ to give a better error.
  434. if (__specs.__chrono_.__weekday_name_ && !__formatter::__weekday_name_ok(__value))
  435. std::__throw_format_error("formatting a weekday name needs a valid weekday");
  436. if (__specs.__chrono_.__weekday_ && !__formatter::__weekday_ok(__value))
  437. std::__throw_format_error("formatting a weekday needs a valid weekday");
  438. if (__specs.__chrono_.__day_of_year_ && !__formatter::__date_ok(__value))
  439. std::__throw_format_error("formatting a day of year needs a valid date");
  440. if (__specs.__chrono_.__week_of_year_ && !__formatter::__date_ok(__value))
  441. std::__throw_format_error("formatting a week of year needs a valid date");
  442. if (__specs.__chrono_.__month_name_ && !__formatter::__month_name_ok(__value))
  443. std::__throw_format_error("formatting a month name from an invalid month number");
  444. __formatter::__format_chrono_using_chrono_specs(__value, __sstr, __chrono_specs);
  445. }
  446. }
  447. // TODO FMT Use the stringstream's view after P0408R7 has been implemented.
  448. basic_string<_CharT> __str = __sstr.str();
  449. return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs);
  450. }
  451. } // namespace __formatter
  452. template <__fmt_char_type _CharT>
  453. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_chrono {
  454. public:
  455. _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(
  456. basic_format_parse_context<_CharT>& __parse_ctx, __format_spec::__fields __fields, __format_spec::__flags __flags)
  457. -> decltype(__parse_ctx.begin()) {
  458. return __parser_.__parse(__parse_ctx, __fields, __flags);
  459. }
  460. template <class _Tp>
  461. _LIBCPP_HIDE_FROM_ABI auto format(const _Tp& __value, auto& __ctx) const -> decltype(__ctx.out()) const {
  462. return __formatter::__format_chrono(
  463. __value, __ctx, __parser_.__parser_.__get_parsed_chrono_specifications(__ctx), __parser_.__chrono_specs_);
  464. }
  465. __format_spec::__parser_chrono<_CharT> __parser_;
  466. };
  467. template <class _Rep, class _Period, __fmt_char_type _CharT>
  468. struct formatter<chrono::duration<_Rep, _Period>, _CharT> : public __formatter_chrono<_CharT> {
  469. public:
  470. using _Base = __formatter_chrono<_CharT>;
  471. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  472. -> decltype(__parse_ctx.begin()) {
  473. // [time.format]/1
  474. // Giving a precision specification in the chrono-format-spec is valid only
  475. // for std::chrono::duration types where the representation type Rep is a
  476. // floating-point type. For all other Rep types, an exception of type
  477. // format_error is thrown if the chrono-format-spec contains a precision
  478. // specification.
  479. //
  480. // Note this doesn't refer to chrono::treat_as_floating_point_v<_Rep>.
  481. if constexpr (std::floating_point<_Rep>)
  482. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono_fractional, __format_spec::__flags::__duration);
  483. else
  484. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__duration);
  485. }
  486. };
  487. template <__fmt_char_type _CharT>
  488. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::day, _CharT>
  489. : public __formatter_chrono<_CharT> {
  490. public:
  491. using _Base = __formatter_chrono<_CharT>;
  492. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  493. -> decltype(__parse_ctx.begin()) {
  494. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day);
  495. }
  496. };
  497. template <__fmt_char_type _CharT>
  498. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month, _CharT>
  499. : public __formatter_chrono<_CharT> {
  500. public:
  501. using _Base = __formatter_chrono<_CharT>;
  502. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  503. -> decltype(__parse_ctx.begin()) {
  504. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month);
  505. }
  506. };
  507. template <__fmt_char_type _CharT>
  508. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year, _CharT>
  509. : public __formatter_chrono<_CharT> {
  510. public:
  511. using _Base = __formatter_chrono<_CharT>;
  512. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  513. -> decltype(__parse_ctx.begin()) {
  514. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year);
  515. }
  516. };
  517. template <__fmt_char_type _CharT>
  518. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday, _CharT>
  519. : public __formatter_chrono<_CharT> {
  520. public:
  521. using _Base = __formatter_chrono<_CharT>;
  522. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  523. -> decltype(__parse_ctx.begin()) {
  524. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday);
  525. }
  526. };
  527. template <__fmt_char_type _CharT>
  528. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_indexed, _CharT>
  529. : public __formatter_chrono<_CharT> {
  530. public:
  531. using _Base = __formatter_chrono<_CharT>;
  532. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  533. -> decltype(__parse_ctx.begin()) {
  534. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday);
  535. }
  536. };
  537. template <__fmt_char_type _CharT>
  538. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_last, _CharT>
  539. : public __formatter_chrono<_CharT> {
  540. public:
  541. using _Base = __formatter_chrono<_CharT>;
  542. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  543. -> decltype(__parse_ctx.begin()) {
  544. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday);
  545. }
  546. };
  547. template <__fmt_char_type _CharT>
  548. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day, _CharT>
  549. : public __formatter_chrono<_CharT> {
  550. public:
  551. using _Base = __formatter_chrono<_CharT>;
  552. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  553. -> decltype(__parse_ctx.begin()) {
  554. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day);
  555. }
  556. };
  557. template <__fmt_char_type _CharT>
  558. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day_last, _CharT>
  559. : public __formatter_chrono<_CharT> {
  560. public:
  561. using _Base = __formatter_chrono<_CharT>;
  562. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  563. -> decltype(__parse_ctx.begin()) {
  564. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month);
  565. }
  566. };
  567. template <__fmt_char_type _CharT>
  568. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday, _CharT>
  569. : public __formatter_chrono<_CharT> {
  570. public:
  571. using _Base = __formatter_chrono<_CharT>;
  572. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  573. -> decltype(__parse_ctx.begin()) {
  574. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday);
  575. }
  576. };
  577. template <__fmt_char_type _CharT>
  578. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday_last, _CharT>
  579. : public __formatter_chrono<_CharT> {
  580. public:
  581. using _Base = __formatter_chrono<_CharT>;
  582. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  583. -> decltype(__parse_ctx.begin()) {
  584. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday);
  585. }
  586. };
  587. template <__fmt_char_type _CharT>
  588. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month, _CharT>
  589. : public __formatter_chrono<_CharT> {
  590. public:
  591. using _Base = __formatter_chrono<_CharT>;
  592. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  593. -> decltype(__parse_ctx.begin()) {
  594. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month);
  595. }
  596. };
  597. template <__fmt_char_type _CharT>
  598. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day, _CharT>
  599. : public __formatter_chrono<_CharT> {
  600. public:
  601. using _Base = __formatter_chrono<_CharT>;
  602. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  603. -> decltype(__parse_ctx.begin()) {
  604. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date);
  605. }
  606. };
  607. template <__fmt_char_type _CharT>
  608. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day_last, _CharT>
  609. : public __formatter_chrono<_CharT> {
  610. public:
  611. using _Base = __formatter_chrono<_CharT>;
  612. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  613. -> decltype(__parse_ctx.begin()) {
  614. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date);
  615. }
  616. };
  617. template <__fmt_char_type _CharT>
  618. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday, _CharT>
  619. : public __formatter_chrono<_CharT> {
  620. public:
  621. using _Base = __formatter_chrono<_CharT>;
  622. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  623. -> decltype(__parse_ctx.begin()) {
  624. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date);
  625. }
  626. };
  627. template <__fmt_char_type _CharT>
  628. struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday_last, _CharT>
  629. : public __formatter_chrono<_CharT> {
  630. public:
  631. using _Base = __formatter_chrono<_CharT>;
  632. _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx)
  633. -> decltype(__parse_ctx.begin()) {
  634. return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date);
  635. }
  636. };
  637. #endif // if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
  638. _LIBCPP_END_NAMESPACE_STD
  639. #endif // _LIBCPP___CHRONO_FORMATTER_H