[libcxx-commits] [libcxx] [libc++][chrono] P0355R7 Implement from_stream and parse (PR #227590)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 20 01:32:00 PDT 2026


https://github.com/emmett2020 updated https://github.com/llvm/llvm-project/pull/227590

>From c19c95cba9037acae270a190481710f0d85a4b2a Mon Sep 17 00:00:00 2001
From: Emmett <emmettzhang2020 at outlook.com>
Date: Mon, 28 Sep 2026 16:01:35 +0800
Subject: [PATCH 1/6] [libc++][chrono] Implement from_stream and parse

---
 libcxx/include/CMakeLists.txt                 |    3 +
 libcxx/include/__chrono/from_stream.h         | 1712 +++++++++++++++++
 libcxx/include/__chrono/parse.h               |  226 +++
 libcxx/include/__chrono/parser_data.h         |  146 ++
 libcxx/include/chrono                         |  112 ++
 libcxx/include/module.modulemap.in            |    3 +
 libcxx/modules/std/chrono.inc                 |    6 +-
 libcxx/test/libcxx/time/from_stream.pass.cpp  |  164 ++
 .../std/time/time.parse/from_stream.pass.cpp  |  463 +++++
 .../test/std/time/time.parse/parse.pass.cpp   |  176 ++
 10 files changed, 3009 insertions(+), 2 deletions(-)
 create mode 100644 libcxx/include/__chrono/from_stream.h
 create mode 100644 libcxx/include/__chrono/parse.h
 create mode 100644 libcxx/include/__chrono/parser_data.h
 create mode 100644 libcxx/test/libcxx/time/from_stream.pass.cpp
 create mode 100644 libcxx/test/std/time/time.parse/from_stream.pass.cpp
 create mode 100644 libcxx/test/std/time/time.parse/parse.pass.cpp

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 2219c69f99addc..88c6ca83b1e6b0 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -266,6 +266,7 @@ set(files
   __chrono/exception.h
   __chrono/file_clock.h
   __chrono/formatter.h
+  __chrono/from_stream.h
   __chrono/gps_clock.h
   __chrono/hh_mm_ss.h
   __chrono/high_resolution_clock.h
@@ -277,6 +278,8 @@ set(files
   __chrono/month_weekday.h
   __chrono/monthday.h
   __chrono/ostream.h
+  __chrono/parse.h
+  __chrono/parser_data.h
   __chrono/parser_std_format_spec.h
   __chrono/statically_widen.h
   __chrono/steady_clock.h
diff --git a/libcxx/include/__chrono/from_stream.h b/libcxx/include/__chrono/from_stream.h
new file mode 100644
index 00000000000000..bb5d5af9d1696b
--- /dev/null
+++ b/libcxx/include/__chrono/from_stream.h
@@ -0,0 +1,1712 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CHRONO_FROM_STREAM_H
+#define _LIBCPP___CHRONO_FROM_STREAM_H
+
+#include <__config>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  include <__chrono/calendar.h>
+#  include <__chrono/concepts.h>
+#  include <__chrono/day.h>
+#  include <__chrono/duration.h>
+#  include <__chrono/file_clock.h>
+#  include <__chrono/gps_clock.h>
+#  include <__chrono/hh_mm_ss.h>
+#  include <__chrono/month.h>
+#  include <__chrono/monthday.h>
+#  include <__chrono/parser_data.h>
+#  include <__chrono/statically_widen.h>
+#  include <__chrono/system_clock.h>
+#  include <__chrono/tai_clock.h>
+#  include <__chrono/time_point.h>
+#  include <__chrono/tzdb.h>
+#  include <__chrono/tzdb_list.h>
+#  include <__chrono/utc_clock.h>
+#  include <__chrono/weekday.h>
+#  include <__chrono/year.h>
+#  include <__chrono/year_month.h>
+#  include <__chrono/year_month_day.h>
+#  include <__fwd/memory.h>
+#  include <__fwd/string.h>
+#  include <__iterator/istreambuf_iterator.h>
+#  include <__locale_dir/ctype.h>
+#  include <__locale_dir/locale.h>
+#  include <__locale_dir/num.h>
+#  include <__locale_dir/time.h>
+#  include <__memory/addressof.h>
+#  include <__type_traits/common_type.h>
+#  include <__utility/move.h>
+#  include <cctype>
+#  include <cstdint>
+#  include <ctime>
+#  include <istream>
+#  include <limits>
+#  include <ratio>
+#  include <string>
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+_LIBCPP_PUSH_MACROS
+#  include <__undef_macros>
+
+#  if _LIBCPP_STD_VER >= 20
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace chrono {
+struct __parse_options {
+  // The number of fractional digits used to determine the default width of %S.
+  unsigned __default_fractional_width_ = 0;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr bool __allows_fraction() const { return __default_fractional_width_ != 0; }
+};
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI constexpr __parse_options __get_parse_options() {
+  if constexpr (__is_duration_v<_Tp>) {
+    constexpr unsigned __width = hh_mm_ss<_Tp>::fractional_width;
+    // Types such as duration<double> have fractional_width == 0 but can store 1.5 seconds.
+    // Use __subsecond_precision as the default number of fractional digits for %S.
+    if constexpr (__width == 0 && treat_as_floating_point_v<typename _Tp::rep>)
+      return {__fields_storage::__subsecond_precision};
+    else
+      return {__width};
+  } else if constexpr (__is_time_point<_Tp>) {
+    return chrono::__get_parse_options<typename _Tp::duration>();
+  } else {
+    return {};
+  }
+}
+
+// Check an inclusive range without narrowing parsed int or int64_t fields.
+_LIBCPP_HIDE_FROM_ABI constexpr bool __in_range(int64_t __value, int64_t __lo, int64_t __hi) {
+  return __lo <= __value && __value <= __hi;
+}
+
+_LIBCPP_HIDE_FROM_ABI constexpr int64_t __pow10(unsigned __exp) {
+  int64_t __result = 1;
+  for (unsigned __i = 0; __i < __exp; ++__i)
+    __result *= 10;
+  return __result;
+}
+
+struct __read_digits_result {
+  uint64_t __value       = 0;
+  unsigned __digits_read = 0;
+  bool __overflow        = false;
+};
+
+_LIBCPP_HIDE_FROM_ABI constexpr bool __width_allowed(char __spec) {
+  switch (__spec) {
+  case 'C':
+  case 'd':
+  case 'e':
+  case 'F':
+  case 'g':
+  case 'G':
+  case 'H':
+  case 'I':
+  case 'j':
+  case 'm':
+  case 'M':
+  case 'S':
+  case 'u':
+  case 'U':
+  case 'V':
+  case 'w':
+  case 'W':
+  case 'y':
+  case 'Y':
+    return true;
+  default:
+    return false;
+  }
+}
+
+// Returns whether [time.parse] permits '__modifier' for '__spec'.
+_LIBCPP_HIDE_FROM_ABI constexpr bool __modifier_allowed(char __modifier, char __spec) {
+  if (__modifier == 'E')
+    switch (__spec) {
+    case 'c':
+    case 'C':
+    case 'x':
+    case 'X':
+    case 'y':
+    case 'Y':
+    case 'z':
+      return true;
+    default:
+      return false;
+    }
+
+  switch (__spec) {
+  case 'd':
+  case 'e':
+  case 'H':
+  case 'I':
+  case 'm':
+  case 'M':
+  case 'S':
+  case 'U':
+  case 'w':
+  case 'W':
+  case 'y':
+  case 'z':
+    return true;
+  default:
+    return false;
+  }
+}
+
+template <class _CharT, class _Traits>
+class __from_stream_parser {
+  // Share the input stream and local error state across all parsing operations.
+  basic_istream<_CharT, _Traits>& __is_;
+  ios_base::iostate& __state_;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI __from_stream_parser(basic_istream<_CharT, _Traits>& __is, ios_base::iostate& __state) noexcept
+      : __is_(__is), __state_(__state) {}
+
+  _LIBCPP_HIDE_FROM_ABI bool __fail() const noexcept {
+    return (__state_ & (ios_base::failbit | ios_base::badbit)) != 0;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI bool __peek(_CharT& __c) {
+    if (__state_ != ios_base::goodbit)
+      return false;
+
+    typename _Traits::int_type __i = __is_.rdbuf()->sgetc();
+    if (_Traits::eq_int_type(__i, _Traits::eof())) {
+      __state_ |= ios_base::eofbit;
+      return false;
+    }
+
+    __c = _Traits::to_char_type(__i);
+    return true;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI void __consume() {
+    // A character is required, but the input has already reached EOF.
+    if (__state_ & ios_base::eofbit) {
+      __state_ |= ios_base::failbit;
+      return;
+    }
+
+    const auto __i = __is_.rdbuf()->sbumpc();
+    if (_Traits::eq_int_type(__i, _Traits::eof()))
+      __state_ |= ios_base::eofbit | ios_base::failbit;
+  }
+
+  // Extracts digits and reports their value, count, and overflow status.
+  // Stops after consuming the first digit that would overflow '__max_value'.
+  _LIBCPP_HIDE_FROM_ABI __read_digits_result __read_digits(unsigned __max_digits, uint64_t __max_value) {
+    uint64_t __result      = 0;
+    unsigned __digits_read = 0;
+
+    for (_CharT __c{}; __digits_read < __max_digits && __peek(__c);) {
+      if (__c < _CharT('0') || __c > _CharT('9'))
+        break;
+      __consume();
+      ++__digits_read;
+
+      const uint64_t __digit = static_cast<uint64_t>(__c - _CharT('0'));
+      if (__result > __max_value / 10 || (__result == __max_value / 10 && __digit > __max_value % 10))
+        return {__result, __digits_read, true};
+      __result = __result * 10 + __digit;
+    }
+
+    return {__result, __digits_read, false};
+  }
+
+  // Reads an integer without a sign into int. Returns the number of digits read.
+  // Failure leaves '__value' unchanged.
+  _LIBCPP_HIDE_FROM_ABI unsigned __read_unsigned(unsigned __max_digits, int& __value) {
+    auto __result = __read_digits(__max_digits, (numeric_limits<int>::max)());
+
+    if (__result.__digits_read == 0 || __result.__overflow)
+      __state_ |= ios_base::failbit;
+    else
+      __value = static_cast<int>(__result.__value);
+
+    return __result.__digits_read;
+  }
+
+  // Reads an integer with an optional '+' or '-'. Failure leaves '__value' unchanged.
+  // The width includes an optional sign.
+  _LIBCPP_HIDE_FROM_ABI void __read_signed(unsigned __width, int& __value) {
+    bool __negative = false;
+    if (_CharT __c{}; __width != 0 && __peek(__c) && (_Traits::eq(__c, _CharT('-')) || _Traits::eq(__c, _CharT('+')))) {
+      __negative = _Traits::eq(__c, _CharT('-'));
+      __consume();
+      --__width;
+    }
+
+    const uint64_t __positive_limit = static_cast<uint64_t>((numeric_limits<int>::max)());
+    const uint64_t __negative_limit = __positive_limit + 1;
+    const uint64_t __limit          = __negative ? __negative_limit : __positive_limit;
+
+    auto __result = __read_digits(__width, __limit);
+    if (__result.__digits_read == 0 || __result.__overflow) {
+      __state_ |= ios_base::failbit;
+      return;
+    }
+
+    if (__negative)
+      __value = static_cast<int>(-static_cast<int64_t>(__result.__value));
+    else
+      __value = static_cast<int>(__result.__value);
+  }
+
+  // Parses one locale-dependent conversion specifier with time_get.
+  _LIBCPP_HIDE_FROM_ABI bool __read_with_time_get(tm& __tm, char __spec, char __modifier = 0) {
+    using _Iter  = istreambuf_iterator<_CharT, _Traits>;
+    using _Facet = time_get<_CharT, _Iter>;
+
+    const _Facet& __tf = std::use_facet<_Facet>(__is_.getloc());
+    __tf.get(_Iter(__is_), _Iter(), __is_, __state_, std::addressof(__tm), __spec, __modifier);
+
+    // time_get may report only eofbit for incomplete locale formats
+    // (e.g. "01:30" parsed with %X in the classic locale), causing truncated
+    // input to be accepted here. Fix format completeness checking in time_get.
+    //
+    // Propagate eofbit as well as parse failures. Reaching EOF after a
+    // successful match is not itself a parsing failure.
+    return !__fail();
+  }
+
+  // Parses a locale-dependent month name into a one-based month.
+  _LIBCPP_HIDE_FROM_ABI void __read_month_name(int& __value) {
+    tm __tm{};
+    if (__read_with_time_get(__tm, 'b')) {
+      if (__tm.tm_mon == (numeric_limits<int>::max)())
+        __state_ |= ios_base::failbit;
+      else
+        __value = __tm.tm_mon + 1; // tm_mon is 0-based [0, 11].
+    }
+  }
+
+  // Parses a locale-dependent weekday name using the chrono::weekday convention.
+  _LIBCPP_HIDE_FROM_ABI void __read_weekday_name(int& __value) {
+    tm __tm{};
+    if (__read_with_time_get(__tm, 'a'))
+      __value = __tm.tm_wday; // tm_wday is already [0, 6], Sunday == 0.
+  }
+
+  // time_get reports %p through tm_hour. Starting at zero leaves AM as 0
+  // and changes PM to 12.
+  _LIBCPP_HIDE_FROM_ABI void __read_am_pm(bool& __is_pm) {
+    tm __tm{};
+    if (__read_with_time_get(__tm, 'p'))
+      __is_pm = __tm.tm_hour == 12;
+  }
+
+  // Parses an O-modified field through time_get and converts its tm member.
+  _LIBCPP_HIDE_FROM_ABI void __read_alternative_field(char __spec, int& __field) {
+    tm __tm{};
+    if (!__read_with_time_get(__tm, __spec, 'O'))
+      return;
+
+    switch (__spec) {
+    case 'd':
+    case 'e':
+      __field = __tm.tm_mday;
+      break;
+    case 'm':
+      if (__tm.tm_mon == (numeric_limits<int>::max)())
+        __state_ |= ios_base::failbit;
+      else
+        __field = __tm.tm_mon + 1;
+      break;
+    case 'H':
+      __field = __tm.tm_hour;
+      break;
+    case 'I':
+      // Keep the 12-hour value separate from %p until the fields are combined.
+      __field = __tm.tm_hour == 0 ? 12 : __tm.tm_hour;
+      break;
+    case 'M':
+      __field = __tm.tm_min;
+      break;
+    case 'w':
+      __field = __tm.tm_wday;
+      break;
+    case 'y': {
+      // tm_year is relative to 1900; %Oy supplies only the last two digits.
+      int64_t __year = static_cast<int64_t>(__tm.tm_year) + 1900;
+      __field        = static_cast<int>((__year < 0 ? -__year : __year) % 100);
+      break;
+    }
+    default:
+      __state_ |= ios_base::failbit;
+      return;
+    }
+  }
+
+  // Parses %S and its optional fractional part. '__width' includes the decimal point.
+  _LIBCPP_HIDE_FROM_ABI void
+  __read_seconds(unsigned __width, bool __allow_fraction, int& __seconds, int64_t& __subseconds) {
+    constexpr unsigned __precision = __fields_storage::__subsecond_precision;
+    const auto __integer           = __read_digits(__width, (numeric_limits<int>::max)());
+    if (__integer.__overflow) {
+      __state_ |= ios_base::failbit;
+      return;
+    }
+
+    unsigned __remaining = __width - __integer.__digits_read;
+    __read_digits_result __fraction{};
+    _CharT __c{};
+    const _CharT __decimal_point = std::use_facet<numpunct<_CharT> >(__is_.getloc()).decimal_point();
+    if (__allow_fraction && __remaining != 0 && __peek(__c) && _Traits::eq(__c, __decimal_point)) {
+      __consume();
+      --__remaining;
+      __fraction =
+          __read_digits(__remaining < __precision ? __remaining : __precision, (numeric_limits<int64_t>::max)());
+      __remaining -= __fraction.__digits_read;
+      // Consume excess fractional digits within the field width, discarding them without rounding.
+      while (__remaining != 0 && __peek(__c) && _CharT('0') <= __c && __c <= _CharT('9')) {
+        __consume();
+        --__remaining;
+      }
+    }
+
+    // Either side of the decimal point may be empty, but at least one digit is required.
+    if (__integer.__digits_read == 0 && __fraction.__digits_read == 0) {
+      __state_ |= ios_base::failbit;
+      return;
+    }
+
+    // The fraction is stored scaled to attoseconds, so that the conversion to the
+    // target's precision does not depend on the number of digits that were read.
+    __seconds    = static_cast<int>(__integer.__value);
+    __subseconds = static_cast<int64_t>(__fraction.__value) * chrono::__pow10(__precision - __fraction.__digits_read);
+  }
+
+  // Parses %z as [+|-]hh[mm], and %Ez/%Oz as [+|-]h[h][:mm].
+  _LIBCPP_HIDE_FROM_ABI void __read_utc_offset(bool __is_modified, int& __value) {
+    _CharT __c{};
+    if (!__peek(__c)) {
+      __state_ |= ios_base::failbit;
+      return;
+    }
+    int __sign = 1;
+    if (_Traits::eq(__c, _CharT('-'))) {
+      __sign = -1;
+      __consume();
+    } else if (_Traits::eq(__c, _CharT('+'))) {
+      __consume();
+    }
+
+    int __hours            = 0;
+    unsigned __digits_read = __read_unsigned(2, __hours);
+
+    // %z requires exactly two hour digits, while %Ez and %Oz allow one or two.
+    if (__fail() || (!__is_modified && __digits_read != 2)) {
+      __state_ |= ios_base::failbit;
+      return;
+    }
+
+    // The minutes are optional in both forms, but the modified form requires the
+    // colon before them, and a colon requires the minutes to follow.
+    int __minutes = 0;
+    bool __has_minutes{};
+    if (__is_modified) {
+      __has_minutes = __peek(__c) && _Traits::eq(__c, _CharT(':'));
+      if (__has_minutes)
+        __consume();
+    } else {
+      __has_minutes = __peek(__c) && __c >= _CharT('0') && __c <= _CharT('9');
+    }
+
+    if (__has_minutes && __read_unsigned(2, __minutes) != 2) {
+      __state_ |= ios_base::failbit;
+      return;
+    }
+
+    __value = __sign * (__hours * 60 + __minutes);
+  }
+
+  // Parses a nonempty %Z token containing alphanumerics or '_', '/', '-', and '+'.
+  _LIBCPP_HIDE_FROM_ABI void __read_time_zone_abbrev(basic_string<_CharT, _Traits>& __abbrev) {
+    const auto& __ctype = std::use_facet<ctype<_CharT> >(__is_.getloc());
+    __abbrev.clear();
+
+    for (_CharT __c{}; __peek(__c);) {
+      char __narrow = __ctype.narrow(__c, '\0');
+      if (!std::isdigit(static_cast<unsigned char>(__narrow)) && ('a' > __narrow || __narrow > 'z') &&
+          ('A' > __narrow || __narrow > 'Z') && __narrow != '_' && __narrow != '/' && __narrow != '-' &&
+          __narrow != '+')
+        break;
+
+      __consume();
+      __abbrev.push_back(__c);
+    }
+
+    if (__abbrev.empty())
+      __state_ |= ios_base::failbit;
+  }
+
+  // Parses '__fmt' into '__f', setting failbit on a mismatch.
+  _LIBCPP_HIDE_FROM_ABI void __parse(
+      const _CharT* __fmt, __fields_storage& __f, basic_string<_CharT, _Traits>& __abbrev, __parse_options __options) {
+    const auto& __ctype = std::use_facet<ctype<_CharT> >(__is_.getloc());
+
+    auto __skip_one_whitespace = [&] {
+      _CharT __c{};
+      if (!__peek(__c) || !__ctype.is(ctype_base::space, __c))
+        return false;
+      __consume();
+      return true;
+    };
+
+    auto __match = [&](_CharT __expected) {
+      _CharT __c{};
+      if (!__peek(__c) || !_Traits::eq(__c, __expected)) {
+        __state_ |= ios_base::failbit;
+        return;
+      }
+      __consume();
+    };
+
+    // Accept repeated fields only when their values agree.
+    auto __assign = [&](auto& __field, auto __value, __fields_set __field_bit) {
+      if (__f.__has(__field_bit) && __field != __value) {
+        __state_ |= ios_base::failbit;
+        return false;
+      }
+      __field = __value;
+      __f.__set(__field_bit);
+      return true;
+    };
+
+    auto __assign_seconds = [&](int __seconds, int64_t __subseconds) {
+      // Repeated seconds fields must agree in both their integer and fractional parts.
+      if (__f.__has(__fields_set::__seconds) && (__f.__seconds_ != __seconds || __f.__subseconds_ != __subseconds)) {
+        __state_ |= ios_base::failbit;
+        return false;
+      }
+
+      __f.__seconds_    = __seconds;
+      __f.__subseconds_ = __subseconds;
+      __f.__set(__fields_set::__seconds);
+      return true;
+    };
+
+    auto __assign_date = [&](const tm& __tm) {
+      const int64_t __year = static_cast<int64_t>(__tm.tm_year) + 1900;
+      if (__year > (numeric_limits<int>::max)() || __tm.tm_mon == (numeric_limits<int>::max)()) {
+        __state_ |= ios_base::failbit;
+        return false;
+      }
+      return __assign(__f.__year_, static_cast<int>(__year), __fields_set::__year) &&
+             __assign(__f.__month_, __tm.tm_mon + 1, __fields_set::__month) &&
+             __assign(__f.__day_, __tm.tm_mday, __fields_set::__day) &&
+             (__tm.tm_wday == -1 || __assign(__f.__weekday_, __tm.tm_wday, __fields_set::__weekday));
+    };
+
+    auto __assign_time = [&](const tm& __tm) {
+      return __assign(__f.__hours_, __tm.tm_hour, __fields_set::__hours) &&
+             __assign(__f.__minutes_, __tm.tm_min, __fields_set::__minutes) && __assign_seconds(__tm.tm_sec, 0);
+    };
+
+    while (*__fmt != _CharT('\0')) {
+      if (__fail())
+        return;
+
+      if (__ctype.is(ctype_base::space, *__fmt)) {
+        while (__skip_one_whitespace()) {
+        }
+        ++__fmt;
+        continue;
+      }
+
+      if (*__fmt != _CharT('%')) {
+        __match(*__fmt);
+        ++__fmt;
+        continue;
+      }
+
+      ++__fmt;
+
+      unsigned __width = 0;
+      bool __has_width = false;
+      while (_CharT('0') <= *__fmt && *__fmt <= _CharT('9')) {
+        __has_width            = true;
+        const unsigned __digit = static_cast<unsigned>(*__fmt - _CharT('0'));
+        if (__width > ((numeric_limits<unsigned>::max)() - __digit) / 10) {
+          __state_ |= ios_base::failbit;
+          return;
+        }
+        __width = __width * 10 + __digit;
+        ++__fmt;
+      }
+
+      char __modifier = '\0';
+      if (*__fmt == _CharT('E') || *__fmt == _CharT('O')) {
+        __modifier = static_cast<char>(*__fmt == _CharT('E') ? 'E' : 'O');
+        ++__fmt;
+      }
+
+      if (__has_width && __modifier != '\0') {
+        __state_ |= ios_base::failbit;
+        return;
+      }
+
+      char __spec = __ctype.narrow(*__fmt, '\0');
+
+      if ((__has_width && !__width_allowed(__spec)) || (__modifier != 0 && !__modifier_allowed(__modifier, __spec))) {
+        __state_ |= ios_base::failbit;
+        return;
+      }
+
+      int __value{};
+      switch (__spec) {
+      case 'a':
+      case 'A':
+        __read_weekday_name(__value);
+        if (!__fail())
+          __assign(__f.__weekday_, __value, __fields_set::__weekday);
+        break;
+
+      case 'b':
+      case 'h':
+      case 'B':
+        __read_month_name(__value);
+        if (!__fail())
+          __assign(__f.__month_, __value, __fields_set::__month);
+        break;
+
+      case 'c': {
+        tm __tm{};
+        // The locale's format may omit the weekday. Use -1 to distinguish an
+        // unparsed weekday from Sunday, whose tm_wday value is 0.
+        __tm.tm_wday = -1;
+        if (__read_with_time_get(__tm, __spec, __modifier) && __assign_date(__tm))
+          __assign_time(__tm);
+        break;
+      }
+
+      case 'C':
+        if (__modifier == 'E') {
+          // time_get does not support %C; parse %EC numerically.
+          __read_signed(2, __value);
+        } else {
+          __read_signed(__has_width ? __width : 2, __value);
+        }
+        if (!__fail())
+          __assign(__f.__century_, __value, __fields_set::__century);
+        break;
+
+      case 'd':
+      case 'e':
+        if (__modifier == 'O')
+          __read_alternative_field(__spec, __value);
+        else
+          __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__day_, __value, __fields_set::__day);
+        break;
+
+      case 'D':
+        __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "%m/%d/%y"), __f, __abbrev, __options);
+        break;
+
+      case 'F':
+        // A width on %F applies only to %Y.
+        __read_signed(__has_width ? __width : 4, __value);
+        if (!__fail() && __assign(__f.__year_, __value, __fields_set::__year)) {
+          __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "-%m-%d"), __f, __abbrev, __options);
+        }
+        break;
+
+      case 'g':
+        __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail()) {
+          if (!__in_range(__value, 0, 99))
+            __state_ |= ios_base::failbit;
+          else
+            __assign(__f.__iso_year_of_century_, __value, __fields_set::__iso_year_of_century);
+        }
+        break;
+
+      case 'G':
+        __read_signed(__has_width ? __width : 4, __value);
+        if (!__fail())
+          __assign(__f.__iso_year_, __value, __fields_set::__iso_year);
+        break;
+
+      case 'H':
+        if (__modifier == 'O')
+          __read_alternative_field(__spec, __value);
+        else
+          __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__hours_, __value, __fields_set::__hours);
+        break;
+
+      case 'I':
+        if (__modifier == 'O')
+          __read_alternative_field(__spec, __value);
+        else
+          __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__hour12_, __value, __fields_set::__hour12);
+        break;
+
+      case 'j':
+        // The day of the year for a calendar type; a plain number of days when
+        // the target is a duration, in which case it is not limited to [1, 366].
+        __read_unsigned(__has_width ? __width : 3, __value);
+        if (!__fail())
+          __assign(__f.__day_of_year_, __value, __fields_set::__day_of_year);
+        break;
+
+      case 'm':
+        if (__modifier == 'O')
+          __read_alternative_field(__spec, __value);
+        else
+          __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__month_, __value, __fields_set::__month);
+        break;
+
+      case 'M':
+        if (__modifier == 'O')
+          __read_alternative_field(__spec, __value);
+        else
+          __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__minutes_, __value, __fields_set::__minutes);
+        break;
+
+      case 'p': {
+        bool __is_pm{};
+        __read_am_pm(__is_pm);
+        if (!__fail())
+          __assign(__f.__is_pm_, __is_pm, __fields_set::__am_pm);
+        break;
+      }
+
+      case 'r':
+      case 'X': {
+        tm __tm{};
+        if (__read_with_time_get(__tm, __spec, __modifier))
+          __assign_time(__tm);
+        break;
+      }
+
+      case 'R':
+        __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "%H:%M"), __f, __abbrev, __options);
+        break;
+
+      case 'T':
+        __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "%H:%M:%S"), __f, __abbrev, __options);
+        break;
+
+      case 'S': {
+        // The target type determines whether fractions are allowed; the width only
+        // limits the number of characters consumed.
+        unsigned __default_width = __options.__allows_fraction() ? 3 + __options.__default_fractional_width_ : 2;
+        // time_get ignores the O modifier; parse %OS using ordinary digits.
+        int64_t __subseconds{};
+        __read_seconds(__has_width ? __width : __default_width, __options.__allows_fraction(), __value, __subseconds);
+        if (!__fail())
+          __assign_seconds(__value, __subseconds);
+        break;
+      }
+
+      case 'u': {
+        int __weekday = 0;
+        __read_unsigned(__has_width ? __width : 1, __weekday);
+        if (!__fail()) {
+          if (!__in_range(__weekday, 1, 7))
+            __state_ |= ios_base::failbit;
+          else
+            __assign(__f.__weekday_, __weekday % 7, __fields_set::__weekday);
+        }
+        break;
+      }
+
+      case 'w': {
+        if (__modifier == 'O')
+          __read_alternative_field(__spec, __value);
+        else
+          __read_unsigned(__has_width ? __width : 1, __value);
+        if (!__fail())
+          __assign(__f.__weekday_, __value, __fields_set::__weekday);
+        break;
+      }
+
+      case 'U':
+        // time_get does not support %U; parse %OU numerically.
+        __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__week_sun_, __value, __fields_set::__week_sun);
+        break;
+
+      case 'V':
+        __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__iso_week_, __value, __fields_set::__iso_week);
+        break;
+
+      case 'W':
+        // time_get does not support %W; parse %OW numerically.
+        __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__week_mon_, __value, __fields_set::__week_mon);
+        break;
+
+      case 'x': {
+        tm __tm{};
+        // The locale's format may omit the weekday. Use -1 to distinguish an
+        // unparsed weekday from Sunday, whose tm_wday value is 0.
+        __tm.tm_wday = -1;
+        if (__read_with_time_get(__tm, __spec, __modifier))
+          __assign_date(__tm);
+        break;
+      }
+
+      case 'y':
+        if (__modifier == 'O')
+          __read_alternative_field(__spec, __value);
+        else if (__modifier == 'E') {
+          tm __tm{};
+          if (__read_with_time_get(__tm, __spec, __modifier)) {
+            const int64_t __year = static_cast<int64_t>(__tm.tm_year) + 1900;
+            __value              = static_cast<int>((__year < 0 ? -__year : __year) % 100);
+          }
+        } else
+          __read_unsigned(__has_width ? __width : 2, __value);
+        if (!__fail())
+          __assign(__f.__year_of_century_, __value, __fields_set::__year_of_century);
+        break;
+
+      case 'Y':
+        if (__modifier == 'E') {
+          tm __tm{};
+          if (__read_with_time_get(__tm, __spec, __modifier)) {
+            const int64_t __year = static_cast<int64_t>(__tm.tm_year) + 1900;
+            if (__year > (numeric_limits<int>::max)())
+              __state_ |= ios_base::failbit;
+            else
+              __value = static_cast<int>(__year);
+          }
+        } else
+          __read_signed(__has_width ? __width : 4, __value);
+        if (!__fail())
+          __assign(__f.__year_, __value, __fields_set::__year);
+        break;
+
+      case 'z':
+        __read_utc_offset(__modifier != 0, __value);
+        if (!__fail())
+          __assign(__f.__utc_offset_, __value, __fields_set::__utc_offset);
+        break;
+
+      case 'Z': {
+        basic_string<_CharT, _Traits> __parsed;
+        __read_time_zone_abbrev(__parsed);
+        if (!__fail()) {
+          // A parsed abbreviation is nonempty; an empty string means no prior %Z.
+          if (!__abbrev.empty() && __abbrev != __parsed)
+            __state_ |= ios_base::failbit;
+          else
+            __abbrev = std::move(__parsed);
+        }
+        break;
+      }
+
+      case 'n':
+        // %n matches exactly one white space character, %t at most one. Combining
+        // them and a literal space matches a range, e.g. "%n%t%t" matches one to
+        // three white space characters.
+        if (!__skip_one_whitespace())
+          __state_ |= ios_base::failbit;
+        break;
+      case 't':
+        __skip_one_whitespace();
+        break;
+      case '%':
+        __match(_CharT('%'));
+        break;
+      default:
+        __state_ |= ios_base::failbit;
+        return;
+      }
+      ++__fmt;
+    }
+  }
+};
+
+_LIBCPP_HIDE_FROM_ABI inline int64_t __compose_year(int __century, int __last_two_digits) {
+  // %C uses floored division; %y and %g contain the absolute last two digits.
+  return static_cast<int64_t>(__century) * 100 +
+         (__century < 0 && __last_two_digits != 0 ? 100 - __last_two_digits : __last_two_digits);
+}
+
+// Construct a candidate year from %C/%y or %Y, then check consistency with any
+// other supplied year fields. Store the result only if it is representable.
+_LIBCPP_HIDE_FROM_ABI inline bool __try_get_year(const __fields_storage& __f, int& __result) {
+  int64_t __year{};
+
+  if (__f.__has(__fields_set::__year_of_century)) {
+    if (!__in_range(__f.__year_of_century_, 0, 99))
+      return false;
+
+    // Use an explicit century or full year before falling back to the default century.
+    if (__f.__has(__fields_set::__century)) {
+      __year = __compose_year(__f.__century_, __f.__year_of_century_);
+    } else if (__f.__has(__fields_set::__year)) {
+      __year = __f.__year_;
+      if ((__year < 0 ? -__year : __year) % 100 != __f.__year_of_century_)
+        return false;
+    } else {
+      __year = (__f.__year_of_century_ <= 68 ? 2000 : 1900) + __f.__year_of_century_;
+    }
+
+    // Check the constructed year against %Y, if supplied.
+    if (__f.__has(__fields_set::__year) && __f.__year_ != __year)
+      return false;
+  } else if (__f.__has(__fields_set::__year)) {
+    __year = __f.__year_;
+
+    // Check the year obtained from %Y against %C, if supplied.
+    if (__f.__has(__fields_set::__century) && __f.__century_ != __year / 100 - (__year % 100 < 0))
+      return false;
+  } else {
+    return false;
+  }
+
+  if (!__in_range(__year, static_cast<int>((year::min)()), static_cast<int>((year::max)())))
+    return false;
+
+  __result = static_cast<int>(__year);
+  return true;
+}
+
+// Converts an ISO year (%G, or expanded %g), week (%V), and weekday (%u/%w)
+// to sys_days.
+_LIBCPP_HIDE_FROM_ABI inline bool __iso_week_to_sys_days(int64_t __g, int __v, weekday __wd, sys_days& __result) {
+  const int __min_year = static_cast<int>((year::min)());
+  const int __max_year = static_cast<int>((year::max)());
+  if (!__in_range(__g, __min_year - 1, __max_year + 1) || !__in_range(__v, 1, 53))
+    return false;
+
+  const days __year_length{__g % 4 == 0 && (__g % 100 != 0 || __g % 400 == 0) ? 366 : 365};
+  // An ISO year can extend one year beyond chrono::year's range. Anchor its
+  // January 1 in a representable year before doing arithmetic in sys_days.
+  sys_days __jan1;
+  if (__g < __min_year)
+    __jan1 = sys_days{(year::min)() / January / 1} - __year_length;
+  else if (__g > __max_year)
+    __jan1 = sys_days{(year::max)() / January / 1} + days{(year::max)().is_leap() ? 366 : 365};
+  else
+    __jan1 = sys_days{year{static_cast<int>(__g)} / January / 1};
+
+  // ISO week 1 contains __g-01-04 and starts on Monday.
+  // Compute days from 1970-01-01 to __g/__v/__wd in four parts:
+  // 1. Days from 1970-01-01 to __g-01-04.
+  // 2. Subtract the initial partial week from that week's Monday to __g-01-04.
+  // 3. (__v - 1) complete weeks preceding the requested week.
+  // 4. The final partial week from Monday to __wd.
+  sys_days __jan4 = __jan1 + days{3};
+  weekday __jan4_wd{__jan4};
+  sys_days __week1_start = __jan4 - days{static_cast<int>(__jan4_wd.iso_encoding()) - 1};
+  sys_days __date        = __week1_start + weeks{__v - 1} + days{static_cast<int>(__wd.iso_encoding()) - 1};
+
+  // Reject a nonexistent week: the Thursday of the result's week must fall in
+  // the ISO year '__g'.
+  sys_days __thursday = __date + days{4 - static_cast<int>(__wd.iso_encoding())};
+  if (__thursday < __jan1 || __thursday >= __jan1 + __year_length)
+    return false;
+
+  // Check before converting to year_month_day, which could wrap the year.
+  if (__date < sys_days{(year::min)() / January / 1} || __date > sys_days{(year::max)() / December / 31})
+    return false;
+
+  __result = __date;
+  return true;
+}
+
+// Converts a calendar year (%Y or %C/%y), week (%U/%W), and weekday (%u/%w)
+// to sys_days, including week zero.
+// The caller must supply a valid year.
+_LIBCPP_HIDE_FROM_ABI inline bool
+__week_to_sys_days(int __year, int __week, weekday __first, weekday __wd, sys_days& __result) {
+  if (!__in_range(__week, 0, 53))
+    return false;
+
+  // Compute days from 1970-01-01 to __year/__week/__wd in four parts:
+  // 1. Days from 1970-01-01 to __year-01-01.
+  // 2. The initial partial week from __year-01-01 to the next week start (__first).
+  // 3. (__week - 1) complete weeks preceding the requested week.
+  // 4. The final partial week from the week's start (__first) to __wd.
+  sys_days __jan1{year{__year} / January / 1};
+  sys_days __week1_start = __jan1 + (__first - weekday{__jan1});
+  sys_days __date        = __week1_start + weeks{__week - 1} + (__wd - __first);
+  if (year_month_day{__date}.year() != year{__year})
+    return false;
+
+  __result = __date;
+  return true;
+}
+
+// Construct a valid date from the first complete combination of parsed fields.
+_LIBCPP_HIDE_FROM_ABI inline bool __make_date(const __fields_storage& __f, year_month_day& __result) {
+  // Calendar-year combinations use %Y or a year obtained from %C/%y.
+  if (int __year{}; __try_get_year(__f, __year)) {
+    // Calendar date: %Y %m %d, also supplied by formats such as %F, %D, or %x.
+    if (__f.__has(__fields_set::__month | __fields_set::__day)) {
+      if (!__in_range(__f.__month_, 1, 12) || !__in_range(__f.__day_, 1, 31))
+        return false;
+
+      const year_month_day __ymd{
+          year{__year}, month{static_cast<unsigned>(__f.__month_)}, day{static_cast<unsigned>(__f.__day_)}};
+      if (!__ymd.ok())
+        return false;
+      __result = __ymd;
+      return true;
+    }
+
+    // Ordinal date: %Y %j.
+    if (__f.__has(__fields_set::__day_of_year)) {
+      if (!__in_range(__f.__day_of_year_, 1, year{__year}.is_leap() ? 366 : 365))
+        return false;
+
+      __result = year_month_day{sys_days{year{__year} / January / 1} + days{__f.__day_of_year_ - 1}};
+      return true;
+    }
+
+    // Week date: %Y with %U or %W and a weekday (%a/%A/%u/%w).
+    if (__f.__has(__fields_set::__weekday) && __f.__has_any(__fields_set::__week_sun | __fields_set::__week_mon)) {
+      if (!__in_range(__f.__weekday_, 0, 6))
+        return false;
+      const bool __use_sunday = __f.__has(__fields_set::__week_sun);
+      sys_days __date{};
+      if (!__week_to_sys_days(
+              __year,
+              __use_sunday ? __f.__week_sun_ : __f.__week_mon_,
+              __use_sunday ? Sunday : Monday,
+              weekday{static_cast<unsigned>(__f.__weekday_)},
+              __date))
+        return false;
+
+      __result = year_month_day{__date};
+      return true;
+    }
+  }
+
+  // ISO week date: %G (or expanded %g), %V, and a weekday (%a/%A/%u/%w).
+  if (__f.__has(__fields_set::__iso_week | __fields_set::__weekday) &&
+      __f.__has_any(__fields_set::__iso_year | __fields_set::__iso_year_of_century)) {
+    // Use %G when supplied; expand %g only if needed to construct the date.
+    int64_t __iso_year{};
+    if (!__f.__has(__fields_set::__iso_year)) {
+      int __century = __f.__iso_year_of_century_ <= 68 ? 20 : 19;
+      if (__f.__has(__fields_set::__century))
+        __century = __f.__century_;
+      else if (__f.__has(__fields_set::__year))
+        __century = __f.__year_ / 100 - (__f.__year_ % 100 < 0);
+      else if (__f.__has(__fields_set::__year_of_century))
+        __century = __f.__year_of_century_ <= 68 ? 20 : 19;
+      __iso_year = __compose_year(__century, __f.__iso_year_of_century_);
+    } else {
+      __iso_year = __f.__iso_year_;
+    }
+    sys_days __date{};
+    if (!__in_range(__f.__weekday_, 0, 6) ||
+        !__iso_week_to_sys_days(__iso_year, __f.__iso_week_, weekday{static_cast<unsigned>(__f.__weekday_)}, __date))
+      return false;
+
+    __result = year_month_day{__date};
+    return true;
+  }
+
+  return false;
+}
+
+// Compare all parsed date fields with a valid date, including fields that do
+// not form a complete representation on their own, e.g. %F followed by only %G.
+_LIBCPP_HIDE_FROM_ABI inline bool __validate_date(const __fields_storage& __f, const year_month_day& __ymd) {
+  auto __matches = [&](__fields_set __field_bit, int __parsed, int __expected) {
+    return !__f.__has(__field_bit) || __parsed == __expected;
+  };
+
+  // Calendar year: %Y, %C, and %y, including a standalone %C.
+  const auto __year = static_cast<int>(__ymd.year());
+  if (!__matches(__fields_set::__year, __f.__year_, __year) ||
+      !__matches(__fields_set::__century, __f.__century_, __year / 100 - (__year % 100 < 0)) ||
+      !__matches(__fields_set::__year_of_century, __f.__year_of_century_, (__year < 0 ? -__year : __year) % 100))
+    return false;
+
+  // Without %C or %Y, %y denotes a year in [1969, 2068], not just matching last digits.
+  if (__f.__has(__fields_set::__year_of_century) && !__f.__has_any(__fields_set::__century | __fields_set::__year) &&
+      !__in_range(__year, 1969, 2068))
+    return false;
+
+  // Month (%m/%b/%B/%h), day (%d/%e), and weekday (%a/%A/%u/%w).
+  const sys_days __date{__ymd};
+  const weekday __weekday{__date};
+  if (!__matches(__fields_set::__month, __f.__month_, static_cast<unsigned>(__ymd.month())) ||
+      !__matches(__fields_set::__day, __f.__day_, static_cast<unsigned>(__ymd.day())) ||
+      !__matches(__fields_set::__weekday, __f.__weekday_, __weekday.c_encoding()))
+    return false;
+
+  // Day of year (%j) and Sunday-/Monday-based week numbers (%U/%W).
+  const sys_days __jan1{__ymd.year() / January / 1};
+  const int __day_of_year = static_cast<int>((__date - __jan1).count()) + 1;
+  if (!__matches(__fields_set::__day_of_year, __f.__day_of_year_, __day_of_year) ||
+      !__matches(__fields_set::__week_sun,
+                 __f.__week_sun_,
+                 (__day_of_year - static_cast<int>(__weekday.c_encoding()) + 6) / 7) ||
+      !__matches(__fields_set::__week_mon,
+                 __f.__week_mon_,
+                 (__day_of_year - (static_cast<int>(__weekday.iso_encoding()) - 1) + 6) / 7))
+    return false;
+
+  if (__f.__has_any(__fields_set::__iso_year | __fields_set::__iso_year_of_century | __fields_set::__iso_week)) {
+    // Find the Thursday of the week containing __date.
+    // Its calendar year is the ISO year: adjust __iso_year and __iso_jan1
+    // if that Thursday falls in the previous or next calendar year.
+    // Compute the ISO week number from that Thursday's distance from __iso_jan1,
+    // then compare the ISO year and week with any supplied %G/%g and %V fields.
+    // Keep __iso_year as int because it can exceed chrono::year's valid range
+    // near year::min()/max().
+    const sys_days __thursday  = __date + days{4 - static_cast<int>(__weekday.iso_encoding())};
+    const sys_days __next_jan1 = __jan1 + days{__ymd.year().is_leap() ? 366 : 365};
+    int __iso_year             = __year;
+    sys_days __iso_jan1        = __jan1;
+    if (__thursday < __jan1) {
+      // This week's Thursday falls in the previous calendar year, so the ISO year is __year - 1.
+      --__iso_year;
+      const bool __is_leap = __iso_year % 4 == 0 && (__iso_year % 100 != 0 || __iso_year % 400 == 0);
+      __iso_jan1 -= days{__is_leap ? 366 : 365};
+    } else if (__thursday >= __next_jan1) {
+      ++__iso_year;
+      __iso_jan1 = __next_jan1;
+    }
+    const int __iso_week = static_cast<int>((__thursday - __iso_jan1).count()) / 7 + 1;
+    if (!__matches(__fields_set::__iso_year, __f.__iso_year_, __iso_year) ||
+        !__matches(__fields_set::__iso_year_of_century,
+                   __f.__iso_year_of_century_,
+                   (__iso_year < 0 ? -__iso_year : __iso_year) % 100) ||
+        !__matches(__fields_set::__iso_week, __f.__iso_week_, __iso_week))
+      return false;
+  }
+
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __try_get_date(const __fields_storage& __f, sys_days& __result) {
+  // First construct a valid candidate, e.g. from %F/%x, %Y %j, or %G %V %u.
+  year_month_day __ymd{};
+  if (!__make_date(__f, __ymd))
+    return false;
+
+  // Then check all parsed date fields, including incomplete representations
+  // such as a standalone %G or %V alongside %F.
+  if (!__validate_date(__f, __ymd))
+    return false;
+
+  __result = sys_days{__ymd};
+  return true;
+}
+
+// Validate and combine %H, %I, and %p, storing the hour only on success.
+_LIBCPP_HIDE_FROM_ABI inline bool __try_get_hour(const __fields_storage& __f, int& __result) {
+  int __hour{};
+  if (__f.__has(__fields_set::__hours)) {
+    // %H determines the hour; check agreement with %I and %p if supplied.
+    __hour = __f.__hours_;
+    if (!__in_range(__hour, 0, 23))
+      return false;
+    if (__f.__has(__fields_set::__hour12)) {
+      const int __hour12 = static_cast<int>(chrono::make12(hours{__hour}).count());
+      if (__f.__hour12_ != __hour12)
+        return false;
+    }
+    if (__f.__has(__fields_set::__am_pm) && (__hour >= 12) != __f.__is_pm_)
+      return false;
+  } else if (__f.__has(__fields_set::__hour12)) {
+    // Without %H, %I requires %p to distinguish AM from PM.
+    if (!__in_range(__f.__hour12_, 1, 12) || !__f.__has(__fields_set::__am_pm))
+      return false;
+    __hour = static_cast<int>(chrono::make24(hours{__f.__hour12_}, __f.__is_pm_).count());
+  } else {
+    // Default to zero when neither hour field was supplied.
+    __hour = 0;
+  }
+
+  __result = __hour;
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __validate_minute(const __fields_storage& __f) {
+  return !__f.__has(__fields_set::__minutes) || __in_range(__f.__minutes_, 0, 59);
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __validate_second(const __fields_storage& __f, int __max_second) {
+  return (!__f.__has(__fields_set::__seconds) || __in_range(__f.__seconds_, 0, __max_second)) && __f.__subseconds_ >= 0;
+}
+
+// Validate the time-of-day fields and combine their whole seconds only on success.
+_LIBCPP_HIDE_FROM_ABI inline bool
+__try_get_time_of_day(const __fields_storage& __f, seconds& __result, int __max_second = 59) {
+  int __hour{};
+  if (!__try_get_hour(__f, __hour) || !__validate_minute(__f) || !__validate_second(__f, __max_second))
+    return false;
+
+  __result = hours{__hour} + minutes{__f.__minutes_} + seconds{__f.__seconds_};
+  return true;
+}
+
+template <class _Duration, class _Unit>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __can_represent() {
+  return treat_as_floating_point_v<typename _Duration::rep> ||
+         ratio_less_equal_v<typename _Duration::period, typename _Unit::period>;
+}
+
+// Reject fields whose units are finer than the target precision.
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI bool __validate_time_precision(const __fields_storage& __f) {
+  if constexpr (!chrono::__can_represent<_Duration, days>())
+    return false;
+
+  if constexpr (!chrono::__can_represent<_Duration, hours>()) {
+    if (__f.__has_any(__fields_set::__hours | __fields_set::__hour12 | __fields_set::__am_pm))
+      return false;
+  }
+
+  if constexpr (!chrono::__can_represent<_Duration, minutes>()) {
+    if (__f.__has(__fields_set::__minutes))
+      return false;
+  }
+
+  if constexpr (!chrono::__can_represent<_Duration, seconds>()) {
+    if (__f.__has(__fields_set::__seconds))
+      return false;
+  }
+
+  return true;
+}
+
+// Convert whole seconds and a nonnegative attosecond fraction together.
+// Overflow in duration conversion and accumulation is not checked.
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI _Duration __make_duration(int64_t __seconds, int64_t __subseconds) {
+  if constexpr (treat_as_floating_point_v<typename _Duration::rep>) {
+    constexpr auto __scale = chrono::__pow10(__fields_storage::__subsecond_precision);
+    const duration<long double> __value{
+        static_cast<long double>(__seconds) + static_cast<long double>(__subseconds) / __scale};
+    return chrono::duration_cast<_Duration>(__value);
+  } else {
+    using _HMS         = hh_mm_ss<_Duration>;
+    using _Precision   = typename _HMS::precision;
+    _Precision __value = chrono::duration_cast<_Precision>(seconds{__seconds});
+    __value += _Precision{static_cast<typename _Precision::rep>(
+        __subseconds / chrono::__pow10(__fields_storage::__subsecond_precision - _HMS::fractional_width))};
+    return chrono::duration_cast<_Duration>(__value);
+  }
+}
+
+// Builders validate parsed fields and convert them to the requested type.
+
+template <class _Rep, class _Period>
+_LIBCPP_HIDE_FROM_ABI bool __from_fields(const __fields_storage& __f, duration<_Rep, _Period>& __result) {
+  if (!chrono::__validate_time_precision<duration<_Rep, _Period>>(__f))
+    return false;
+
+  // Durations can represent only elapsed days and time-of-day fields.
+  // UTC offsets and time zone abbreviations are allowed but do not contribute to the duration.
+  constexpr auto __duration_components =
+      __fields_set::__day_of_year | __fields_set::__hours | __fields_set::__hour12 | __fields_set::__minutes |
+      __fields_set::__seconds;
+  if (!__f.__has_only(__duration_components | __fields_set::__am_pm))
+    return false;
+
+  // Require at least one numeric component; %p alone is insufficient.
+  if (!__f.__has_any(__duration_components))
+    return false;
+
+  seconds __time_of_day{};
+  // Use clock-time ranges for %H, %M, and %S; %j supplies any additional days.
+  if (__f.__day_of_year_ < 0 || !__try_get_time_of_day(__f, __time_of_day))
+    return false;
+
+  // Sum the components in seconds; when parsing a duration, %j denotes a day count, not a day of the year.
+  const seconds __whole_seconds = chrono::duration_cast<seconds>(days{__f.__day_of_year_}) + __time_of_day;
+
+  __result = chrono::__make_duration<duration<_Rep, _Period>>(__whole_seconds.count(), __f.__subseconds_);
+  return true;
+}
+
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI bool __from_fields(const __fields_storage& __f, sys_time<_Duration>& __result) {
+  if (!chrono::__validate_time_precision<_Duration>(__f))
+    return false;
+
+  sys_days __date{};
+  if (!__try_get_date(__f, __date))
+    return false;
+
+  // sys_time does not represent leap seconds, so seconds must be in [0, 59].
+  seconds __time_of_day{};
+  if (!__try_get_time_of_day(__f, __time_of_day))
+    return false;
+
+  // %z gives the offset of the parsed time from UTC, so it is subtracted to
+  // arrive at the UTC time sys_time holds. It is zero when %z was not used.
+  // Combine whole seconds before converting to avoid overflowing conversion
+  // ratios from days or minutes to fine target precisions.
+  const seconds __whole_seconds = __date.time_since_epoch() + __time_of_day - minutes{__f.__utc_offset_};
+  using _Precision              = common_type_t<_Duration, seconds>;
+  __result                      = sys_time<_Duration>{
+      chrono::floor<_Duration>(chrono::__make_duration<_Precision>(__whole_seconds.count(), __f.__subseconds_))};
+  return true;
+}
+
+// A parsed UTC offset is not applied to local_time.
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI bool __from_fields(const __fields_storage& __f, local_time<_Duration>& __result) {
+  if (!chrono::__validate_time_precision<_Duration>(__f))
+    return false;
+
+  sys_days __date{};
+  if (!__try_get_date(__f, __date))
+    return false;
+
+  seconds __time_of_day{};
+  if (!__try_get_time_of_day(__f, __time_of_day))
+    return false;
+
+  // Combine whole seconds before converting to the target precision.
+  const seconds __whole_seconds = __date.time_since_epoch() + __time_of_day;
+  using _Precision              = common_type_t<_Duration, seconds>;
+  __result                      = local_time<_Duration>{
+      chrono::floor<_Duration>(chrono::__make_duration<_Precision>(__whole_seconds.count(), __f.__subseconds_))};
+  return true;
+}
+
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI bool __from_fields(const __fields_storage& __f, file_time<_Duration>& __result) {
+  sys_time<_Duration> __st{};
+  if (!chrono::__from_fields(__f, __st))
+    return false;
+
+  __result = file_clock::from_sys(__st);
+  return true;
+}
+
+#    if _LIBCPP_HAS_EXPERIMENTAL_TZDB && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI bool __from_fields(const __fields_storage& __f, utc_time<_Duration>& __result) {
+  if (!chrono::__validate_time_precision<_Duration>(__f))
+    return false;
+
+  sys_days __date{};
+  if (!__try_get_date(__f, __date))
+    return false;
+
+  // utc_time can represent leap seconds, so the seconds field may be 60.
+  seconds __time_of_day{};
+  if (!__try_get_time_of_day(__f, __time_of_day, 60))
+    return false;
+
+  const sys_seconds __sys = __date + __time_of_day - minutes{__f.__utc_offset_};
+  utc_seconds __time;
+  if (__f.__seconds_ == 60) {
+    // Convert the preceding second, then advance into the possible leap second.
+    // This also handles offsets that put the leap second on a different local date.
+    __time = utc_clock::from_sys(__sys - seconds{1}) + seconds{1};
+    if (!chrono::get_leap_second_info(__time).is_leap_second)
+      return false;
+  } else {
+    // Reject the UTC second removed by a negative leap second.
+    for (const auto& __leap : chrono::get_tzdb().leap_seconds) {
+      if (__sys < __leap.date()) {
+        if (__leap.value() < seconds{0} && __sys >= __leap.date() + __leap.value())
+          return false;
+        break;
+      }
+    }
+    __time = utc_clock::from_sys(__sys);
+  }
+  using _Precision = common_type_t<_Duration, seconds>;
+  __result         = utc_time<_Duration>{chrono::floor<_Duration>(
+      chrono::__make_duration<_Precision>(__time.time_since_epoch().count(), __f.__subseconds_))};
+  return true;
+}
+
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI bool __from_fields(const __fields_storage& __f, tai_time<_Duration>& __result) {
+  if (!chrono::__validate_time_precision<_Duration>(__f))
+    return false;
+
+  sys_days __date{};
+  if (!__try_get_date(__f, __date))
+    return false;
+
+  seconds __time_of_day{};
+  if (!__try_get_time_of_day(__f, __time_of_day))
+    return false;
+
+  constexpr sys_days __tai_epoch{-days{4383}}; // 1958-01-01.
+  const seconds __whole_seconds = __date - __tai_epoch + __time_of_day - minutes{__f.__utc_offset_};
+  using _Precision              = common_type_t<_Duration, seconds>;
+  __result                      = tai_time<_Duration>{
+      chrono::floor<_Duration>(chrono::__make_duration<_Precision>(__whole_seconds.count(), __f.__subseconds_))};
+  return true;
+}
+
+template <class _Duration>
+_LIBCPP_HIDE_FROM_ABI bool __from_fields(const __fields_storage& __f, gps_time<_Duration>& __result) {
+  if (!chrono::__validate_time_precision<_Duration>(__f))
+    return false;
+
+  sys_days __date{};
+  if (!__try_get_date(__f, __date))
+    return false;
+
+  seconds __time_of_day{};
+  if (!__try_get_time_of_day(__f, __time_of_day))
+    return false;
+
+  constexpr sys_days __gps_epoch{days{3657}}; // 1980-01-06.
+  const seconds __whole_seconds = __date - __gps_epoch + __time_of_day - minutes{__f.__utc_offset_};
+  using _Precision              = common_type_t<_Duration, seconds>;
+  __result                      = gps_time<_Duration>{
+      chrono::floor<_Duration>(chrono::__make_duration<_Precision>(__whole_seconds.count(), __f.__subseconds_))};
+  return true;
+}
+#    endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
+
+// Calendrical results reject fields they cannot represent. UTC offsets are
+// excluded from these checks; time zone abbreviations are stored separately.
+_LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, day& __result) {
+  if (!__f.__has_exactly(__fields_set::__day))
+    return false;
+
+  if (!__in_range(__f.__day_, 1, 31))
+    return false;
+
+  __result = day{static_cast<unsigned>(__f.__day_)};
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, month& __result) {
+  if (!__f.__has_exactly(__fields_set::__month))
+    return false;
+
+  if (!__in_range(__f.__month_, 1, 12))
+    return false;
+
+  __result = month{static_cast<unsigned>(__f.__month_)};
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, year& __result) {
+  constexpr auto __year_fields = __fields_set::__year | __fields_set::__century | __fields_set::__year_of_century;
+  if (!__f.__has_only(__year_fields))
+    return false;
+
+  int __year{};
+  if (!__try_get_year(__f, __year))
+    return false;
+
+  __result = year{__year};
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, weekday& __result) {
+  if (!__f.__has_exactly(__fields_set::__weekday))
+    return false;
+
+  if (!__in_range(__f.__weekday_, 0, 6))
+    return false;
+
+  __result = weekday{static_cast<unsigned>(__f.__weekday_)};
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, month_day& __result) {
+  if (!__f.__has_only(__fields_set::__month | __fields_set::__day | __fields_set::__day_of_year))
+    return false;
+
+  int __month{};
+  int __day{};
+  if (__f.__has(__fields_set::__day_of_year)) {
+    // Without a year, only days through February 28 are unambiguous.
+    if (!__in_range(__f.__day_of_year_, 1, 59))
+      return false;
+    __month = __f.__day_of_year_ <= 31 ? 1 : 2;
+    __day   = __f.__day_of_year_ <= 31 ? __f.__day_of_year_ : __f.__day_of_year_ - 31;
+    if ((__f.__has(__fields_set::__month) && __f.__month_ != __month) ||
+        (__f.__has(__fields_set::__day) && __f.__day_ != __day))
+      return false;
+  } else {
+    if (!__f.__has(__fields_set::__month | __fields_set::__day))
+      return false;
+    __month = __f.__month_;
+    __day   = __f.__day_;
+  }
+
+  if (!__in_range(__month, 1, 12) || !__in_range(__day, 1, 31))
+    return false;
+
+  month_day __md{month{static_cast<unsigned>(__month)}, day{static_cast<unsigned>(__day)}};
+  if (!__md.ok())
+    return false;
+
+  __result = __md;
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, year_month& __result) {
+  constexpr auto __year_fields = __fields_set::__year | __fields_set::__century | __fields_set::__year_of_century;
+  if (!__f.__has_exactly(__fields_set::__month, __year_fields))
+    return false;
+
+  int __year{};
+  if (!__try_get_year(__f, __year))
+    return false;
+
+  if (!__in_range(__f.__month_, 1, 12))
+    return false;
+
+  __result = year_month{year{__year}, month{static_cast<unsigned>(__f.__month_)}};
+  return true;
+}
+
+_LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, year_month_day& __result) {
+  constexpr auto __date_fields =
+      __fields_set::__year | __fields_set::__century | __fields_set::__year_of_century | __fields_set::__month |
+      __fields_set::__day | __fields_set::__iso_year | __fields_set::__iso_year_of_century | __fields_set::__iso_week |
+      __fields_set::__weekday | __fields_set::__day_of_year | __fields_set::__week_sun | __fields_set::__week_mon;
+  if (!__f.__has_only(__date_fields))
+    return false;
+
+  // Resolve the date and check that all supplied date fields agree.
+  sys_days __date{};
+  if (!__try_get_date(__f, __date))
+    return false;
+
+  __result = year_month_day{__date};
+  return true;
+}
+
+template <class _Tp, class _CharT, class _Traits, class _Alloc>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+__from_stream(basic_istream<_CharT, _Traits>& __is,
+              const _CharT* __fmt,
+              _Tp& __value,
+              basic_string<_CharT, _Traits, _Alloc>* __abbrev,
+              minutes* __offset) {
+  ios_base::iostate __state = ios_base::goodbit;
+  constexpr bool __noskipws = true;
+  typename basic_istream<_CharT, _Traits>::sentry __s{__is, __noskipws};
+
+  if (__s) {
+#    if _LIBCPP_HAS_EXCEPTIONS
+    try {
+#    endif
+      __fields_storage __f{};
+      basic_string<_CharT, _Traits> __parsed_abbrev;
+      constexpr auto __options = chrono::__get_parse_options<_Tp>();
+
+      // Parse the input according to the format and collect the fields.
+      __from_stream_parser<_CharT, _Traits> __parser{__is, __state};
+      __parser.__parse(__fmt, __f, __parsed_abbrev, __options);
+      if (!__parser.__fail()) {
+        if (__abbrev && !__parsed_abbrev.empty())
+          __abbrev->assign(__parsed_abbrev.data(), __parsed_abbrev.size());
+        if (__offset && __f.__has(__fields_set::__utc_offset))
+          *__offset = minutes{__f.__utc_offset_};
+
+        // Resolve and validate the fields needed to construct the requested result.
+        _Tp __result{};
+        if (!chrono::__from_fields(__f, __result)) {
+          __state |= ios_base::failbit;
+        } else {
+          __value = __result;
+        }
+      }
+#    if _LIBCPP_HAS_EXCEPTIONS
+    } catch (...) {
+      __state |= ios_base::badbit;
+      __is.__setstate_nothrow(__state);
+      if (__is.exceptions() & ios_base::badbit)
+        throw;
+    }
+#    endif
+    // Keep exceptions requested for failbit or eofbit outside the input handler.
+    __is.setstate(__state);
+  }
+
+  return __is;
+}
+
+template <class _CharT, class _Traits, class _Rep, class _Period, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            duration<_Rep, _Period>& __d,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __d, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Duration, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            sys_time<_Duration>& __tp,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __tp, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Duration, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            local_time<_Duration>& __tp,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __tp, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Duration, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            file_time<_Duration>& __tp,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __tp, __abbrev, __offset);
+}
+
+#    if _LIBCPP_HAS_EXPERIMENTAL_TZDB && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
+template <class _CharT, class _Traits, class _Duration, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            utc_time<_Duration>& __tp,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __tp, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Duration, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            tai_time<_Duration>& __tp,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __tp, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Duration, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            gps_time<_Duration>& __tp,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __tp, __abbrev, __offset);
+}
+#    endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
+
+template <class _CharT, class _Traits, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            day& __d,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __d, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            month& __m,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __m, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            year& __y,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __y, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            weekday& __wd,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __wd, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            month_day& __md,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __md, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            year_month& __ym,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __ym, __abbrev, __offset);
+}
+
+template <class _CharT, class _Traits, class _Alloc = allocator<_CharT>>
+_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
+from_stream(basic_istream<_CharT, _Traits>& __is,
+            const _CharT* __fmt,
+            year_month_day& __ymd,
+            basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
+            minutes* __offset                               = nullptr) {
+  return chrono::__from_stream(__is, __fmt, __ymd, __abbrev, __offset);
+}
+
+} // namespace chrono
+
+_LIBCPP_END_NAMESPACE_STD
+
+#  endif
+
+_LIBCPP_POP_MACROS
+
+#endif
+
+#endif //_LIBCPP___CHRONO_FROM_STREAM_H
diff --git a/libcxx/include/__chrono/parse.h b/libcxx/include/__chrono/parse.h
new file mode 100644
index 00000000000000..55831d2c68a6f4
--- /dev/null
+++ b/libcxx/include/__chrono/parse.h
@@ -0,0 +1,226 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CHRONO_PARSE_H
+#define _LIBCPP___CHRONO_PARSE_H
+
+#include <__config>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  include <__chrono/duration.h>
+#  include <__chrono/from_stream.h>
+#  include <__fwd/istream.h>
+#  include <__fwd/memory.h>
+#  include <__fwd/string.h>
+#  include <__memory/addressof.h>
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+#  if _LIBCPP_STD_VER >= 20
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace chrono {
+
+namespace __parse_details {
+
+// Block ordinary lookup so from_stream is found only through ADL.
+void from_stream() = delete;
+
+// parse() stores the format and output references in a manipulator.
+// operator>> supplies the input stream and calls the matching from_stream overload.
+// Separate manipulator types preserve the four from_stream argument lists.
+// _Format preserves the value category of fmt (lvalue) or fmt.c_str() (prvalue).
+
+template <class _CharT, class _Traits, class _Parsable, class _Format>
+struct __parse_manip {
+  const _CharT* __fmt_;
+  _Parsable* __tp_;
+
+  _LIBCPP_HIDE_FROM_ABI __parse_manip(const _CharT* __fmt, _Parsable* __tp) : __fmt_(__fmt), __tp_(__tp) {}
+
+  __parse_manip(const __parse_manip&)            = delete;
+  __parse_manip& operator=(const __parse_manip&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
+  operator>>(basic_istream<_CharT, _Traits>& __is, __parse_manip&& __manip) {
+    // NOLINTNEXTLINE(libcpp-robust-against-adl) [time.parse] requires ADL.
+    from_stream(__is, static_cast<_Format>(__manip.__fmt_), *__manip.__tp_);
+    return __is;
+  }
+};
+
+template <class _CharT, class _Traits, class _Parsable, class _Format, class _Alloc = allocator<_CharT>>
+struct __parse_manip_offset {
+  const _CharT* __fmt_;
+  _Parsable* __tp_;
+  minutes* __offset_;
+
+  _LIBCPP_HIDE_FROM_ABI __parse_manip_offset(const _CharT* __fmt, _Parsable* __tp, minutes* __offset)
+      : __fmt_(__fmt), __tp_(__tp), __offset_(__offset) {}
+
+  __parse_manip_offset(const __parse_manip_offset&)            = delete;
+  __parse_manip_offset& operator=(const __parse_manip_offset&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
+  operator>>(basic_istream<_CharT, _Traits>& __is, __parse_manip_offset&& __manip) {
+    // NOLINTNEXTLINE(libcpp-robust-against-adl) [time.parse] requires ADL.
+    from_stream(__is,
+                static_cast<_Format>(__manip.__fmt_),
+                *__manip.__tp_,
+                static_cast<basic_string<_CharT, _Traits, _Alloc>*>(nullptr),
+                static_cast<minutes*>(__manip.__offset_));
+    return __is;
+  }
+};
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable, class _Format>
+struct __parse_manip_abbrev {
+  const _CharT* __fmt_;
+  _Parsable* __tp_;
+  basic_string<_CharT, _Traits, _Alloc>* __abbrev_;
+
+  _LIBCPP_HIDE_FROM_ABI
+  __parse_manip_abbrev(const _CharT* __fmt, _Parsable* __tp, basic_string<_CharT, _Traits, _Alloc>* __abbrev)
+      : __fmt_(__fmt), __tp_(__tp), __abbrev_(__abbrev) {}
+
+  __parse_manip_abbrev(const __parse_manip_abbrev&)            = delete;
+  __parse_manip_abbrev& operator=(const __parse_manip_abbrev&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
+  operator>>(basic_istream<_CharT, _Traits>& __is, __parse_manip_abbrev&& __manip) {
+    // NOLINTNEXTLINE(libcpp-robust-against-adl) [time.parse] requires ADL.
+    from_stream(__is,
+                static_cast<_Format>(__manip.__fmt_),
+                *__manip.__tp_,
+                static_cast<basic_string<_CharT, _Traits, _Alloc>*>(__manip.__abbrev_));
+    return __is;
+  }
+};
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable, class _Format>
+struct __parse_manip_abbrev_offset {
+  const _CharT* __fmt_;
+  _Parsable* __tp_;
+  basic_string<_CharT, _Traits, _Alloc>* __abbrev_;
+  minutes* __offset_;
+
+  _LIBCPP_HIDE_FROM_ABI __parse_manip_abbrev_offset(
+      const _CharT* __fmt, _Parsable* __tp, basic_string<_CharT, _Traits, _Alloc>* __abbrev, minutes* __offset)
+      : __fmt_(__fmt), __tp_(__tp), __abbrev_(__abbrev), __offset_(__offset) {}
+
+  __parse_manip_abbrev_offset(const __parse_manip_abbrev_offset&)            = delete;
+  __parse_manip_abbrev_offset& operator=(const __parse_manip_abbrev_offset&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI friend basic_istream<_CharT, _Traits>&
+  operator>>(basic_istream<_CharT, _Traits>& __is, __parse_manip_abbrev_offset&& __manip) {
+    // NOLINTNEXTLINE(libcpp-robust-against-adl) [time.parse] requires ADL.
+    from_stream(__is,
+                static_cast<_Format>(__manip.__fmt_),
+                *__manip.__tp_,
+                static_cast<basic_string<_CharT, _Traits, _Alloc>*>(__manip.__abbrev_),
+                static_cast<minutes*>(__manip.__offset_));
+    return __is;
+  }
+};
+
+// [time.parse]: a Parsable is anything from_stream can read, with the trailing
+// arguments the selected parse overload passes on. The call is unqualified, so
+// a user-defined type that provides its own from_stream is parsable as well.
+// _Format and _Args model the types and value categories of the format and trailing arguments.
+template <class _Parsable, class _CharT, class _Traits, class _Format, class... _Args>
+concept __parsable =
+    requires(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt, _Parsable& __tp, _Args... __args) {
+      // NOLINTNEXTLINE(libcpp-robust-against-adl) [time.parse] requires ADL.
+      from_stream(__is, static_cast<_Format>(__fmt), __tp, static_cast<_Args>(__args)...);
+    };
+
+} // namespace __parse_details
+
+template <class _CharT, class _Parsable>
+  requires __parse_details::__parsable<_Parsable, _CharT, char_traits<_CharT>, const _CharT*&>
+_LIBCPP_HIDE_FROM_ABI __parse_details::__parse_manip<_CharT, char_traits<_CharT>, _Parsable, const _CharT*&>
+parse(const _CharT* __fmt, _Parsable& __tp) {
+  return {__fmt, std::addressof(__tp)};
+}
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable>
+  requires __parse_details::__parsable<_Parsable, _CharT, _Traits, const _CharT*>
+_LIBCPP_HIDE_FROM_ABI __parse_details::__parse_manip<_CharT, _Traits, _Parsable, const _CharT*>
+parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt, _Parsable& __tp) {
+  return {__fmt.c_str(), std::addressof(__tp)};
+}
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable>
+  requires __parse_details::
+      __parsable<_Parsable, _CharT, _Traits, const _CharT*&, basic_string<_CharT, _Traits, _Alloc>*>
+    _LIBCPP_HIDE_FROM_ABI __parse_details::__parse_manip_abbrev<_CharT, _Traits, _Alloc, _Parsable, const _CharT*&>
+    parse(const _CharT* __fmt, _Parsable& __tp, basic_string<_CharT, _Traits, _Alloc>& __abbrev) {
+  return {__fmt, std::addressof(__tp), std::addressof(__abbrev)};
+}
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable>
+  requires __parse_details::
+      __parsable<_Parsable, _CharT, _Traits, const _CharT*, basic_string<_CharT, _Traits, _Alloc>*>
+    _LIBCPP_HIDE_FROM_ABI __parse_details::__parse_manip_abbrev<_CharT, _Traits, _Alloc, _Parsable, const _CharT*>
+    parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt,
+          _Parsable& __tp,
+          basic_string<_CharT, _Traits, _Alloc>& __abbrev) {
+  return {__fmt.c_str(), std::addressof(__tp), std::addressof(__abbrev)};
+}
+
+template <class _CharT, class _Parsable>
+  requires __parse_details::
+      __parsable<_Parsable, _CharT, char_traits<_CharT>, const _CharT*&, basic_string<_CharT>*, minutes*>
+    _LIBCPP_HIDE_FROM_ABI __parse_details::__parse_manip_offset<_CharT, char_traits<_CharT>, _Parsable, const _CharT*&>
+    parse(const _CharT* __fmt, _Parsable& __tp, minutes& __offset) {
+  return {__fmt, std::addressof(__tp), std::addressof(__offset)};
+}
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable>
+  requires __parse_details::
+      __parsable<_Parsable, _CharT, _Traits, const _CharT*, basic_string<_CharT, _Traits, _Alloc>*, minutes*>
+    _LIBCPP_HIDE_FROM_ABI __parse_details::__parse_manip_offset<_CharT, _Traits, _Parsable, const _CharT*, _Alloc>
+    parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt, _Parsable& __tp, minutes& __offset) {
+  return {__fmt.c_str(), std::addressof(__tp), std::addressof(__offset)};
+}
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable>
+  requires __parse_details::
+      __parsable<_Parsable, _CharT, _Traits, const _CharT*&, basic_string<_CharT, _Traits, _Alloc>*, minutes*>
+    _LIBCPP_HIDE_FROM_ABI
+    __parse_details::__parse_manip_abbrev_offset<_CharT, _Traits, _Alloc, _Parsable, const _CharT*&>
+    parse(const _CharT* __fmt, _Parsable& __tp, basic_string<_CharT, _Traits, _Alloc>& __abbrev, minutes& __offset) {
+  return {__fmt, std::addressof(__tp), std::addressof(__abbrev), std::addressof(__offset)};
+}
+
+template <class _CharT, class _Traits, class _Alloc, class _Parsable>
+  requires __parse_details::
+      __parsable<_Parsable, _CharT, _Traits, const _CharT*, basic_string<_CharT, _Traits, _Alloc>*, minutes*>
+    _LIBCPP_HIDE_FROM_ABI
+    __parse_details::__parse_manip_abbrev_offset<_CharT, _Traits, _Alloc, _Parsable, const _CharT*>
+    parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt,
+          _Parsable& __tp,
+          basic_string<_CharT, _Traits, _Alloc>& __abbrev,
+          minutes& __offset) {
+  return {__fmt.c_str(), std::addressof(__tp), std::addressof(__abbrev), std::addressof(__offset)};
+}
+
+} // namespace chrono
+
+_LIBCPP_END_NAMESPACE_STD
+
+#  endif
+
+#endif
+
+#endif //_LIBCPP___CHRONO_PARSE_H
diff --git a/libcxx/include/__chrono/parser_data.h b/libcxx/include/__chrono/parser_data.h
new file mode 100644
index 00000000000000..fda046ca3752c6
--- /dev/null
+++ b/libcxx/include/__chrono/parser_data.h
@@ -0,0 +1,146 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CHRONO_PARSER_DATA_H
+#define _LIBCPP___CHRONO_PARSER_DATA_H
+
+#include <__config>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  include <cstdint>
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+#  if _LIBCPP_STD_VER >= 20
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace chrono {
+
+// Fields supplied by the parsed format directives.
+enum class __fields_set : uint32_t {
+  __none    = 0,
+  __year    = 1 << 0,
+  __month   = 1 << 1,
+  __day     = 1 << 2,
+  __hours   = 1 << 3,
+  __minutes = 1 << 4,
+  __seconds = 1 << 5,
+
+  __iso_year = 1 << 6,
+  __iso_week = 1 << 7,
+  __weekday  = 1 << 8,
+
+  __century         = 1 << 9,
+  __year_of_century = 1 << 10,
+
+  __hour12 = 1 << 11,
+  __am_pm  = 1 << 12,
+
+  __day_of_year = 1 << 13,
+  __week_sun    = 1 << 14,
+  __week_mon    = 1 << 15,
+
+  __utc_offset = 1 << 16,
+
+  __iso_year_of_century = 1 << 17,
+};
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set operator|(__fields_set __lhs, __fields_set __rhs) {
+  return static_cast<__fields_set>(static_cast<uint32_t>(__lhs) | static_cast<uint32_t>(__rhs));
+}
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set operator&(__fields_set __lhs, __fields_set __rhs) {
+  return static_cast<__fields_set>(static_cast<uint32_t>(__lhs) & static_cast<uint32_t>(__rhs));
+}
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set operator~(__fields_set __fields) {
+  return static_cast<__fields_set>(~static_cast<uint32_t>(__fields));
+}
+
+_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set& operator|=(__fields_set& __lhs, __fields_set __rhs) {
+  return __lhs = __lhs | __rhs;
+}
+
+// Fields collected while parsing. Date/time construction and validation do not
+// modify these values or their presence flags.
+struct __fields_storage {
+  int __year_  = 0;
+  int __month_ = 0;
+  int __day_   = 0;
+  // Time-of-day fields.
+  int __hours_   = 0;
+  int __minutes_ = 0;
+  int __seconds_ = 0;
+  // Fractional seconds are stored as an integer number of attoseconds.
+  static constexpr unsigned __subsecond_precision = 18;
+  int64_t __subseconds_                           = 0;
+
+  // __weekday_ uses [0, 6], with Sunday == 0.
+  int __iso_year_            = 0;
+  int __iso_year_of_century_ = 0;
+  int __iso_week_            = 0;
+  int __weekday_             = 0;
+
+  int __century_         = 0;
+  int __year_of_century_ = 0;
+
+  int __hour12_ = 0;
+  bool __is_pm_ = false;
+
+  // For durations, __day_of_year_ is a number of days and is not limited to [1, 366].
+  int __day_of_year_ = 0;
+  int __week_sun_    = 0;
+  int __week_mon_    = 0;
+
+  // Minutes east of UTC.
+  int __utc_offset_ = 0;
+
+  __fields_set __present_ = __fields_set::__none;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __set(__fields_set __field_bit) { __present_ |= __field_bit; }
+
+  // Check whether all specified fields are present, allowing additional fields.
+  // __utc_offset is checked like any other field.
+  _LIBCPP_HIDE_FROM_ABI constexpr bool __has(__fields_set __parts) const { return (__present_ & __parts) == __parts; }
+
+  // Check whether at least one specified field is present, allowing additional fields.
+  // __utc_offset is checked like any other field.
+  _LIBCPP_HIDE_FROM_ABI constexpr bool __has_any(__fields_set __parts) const {
+    return (__present_ & __parts) != __fields_set::__none;
+  }
+
+  // Allow only these fields, without requiring all of them to be present.
+  // Ignore __utc_offset so callers do not have to explicitly allow it each time.
+  _LIBCPP_HIDE_FROM_ABI constexpr bool __has_only(__fields_set __allowed) const {
+    const auto __fields = __present_ & ~__fields_set::__utc_offset;
+    return (__fields & ~__allowed) == __fields_set::__none;
+  }
+
+  // Require every required field and allow only optional fields in addition.
+  // The two sets must be disjoint. Exclude the UTC offset from this check
+  // so callers do not have to explicitly allow __utc_offset each time.
+  _LIBCPP_HIDE_FROM_ABI constexpr bool
+  __has_exactly(__fields_set __required, __fields_set __optional = __fields_set::__none) const {
+    const auto __fields = __present_ & ~__fields_set::__utc_offset;
+    return (__fields & ~__optional) == __required;
+  }
+};
+
+} // namespace chrono
+
+_LIBCPP_END_NAMESPACE_STD
+
+#  endif
+#endif
+
+#endif //_LIBCPP___CHRONO_PARSER_DATA_H
diff --git a/libcxx/include/chrono b/libcxx/include/chrono
index a7fd8428a652cc..cde8ec911d8c19 100644
--- a/libcxx/include/chrono
+++ b/libcxx/include/chrono
@@ -228,6 +228,12 @@ template<class charT, class traits, class Rep, class Period>       // C++20
     operator<<(basic_ostream<charT, traits>& os,
                const duration<Rep, Period>& d);
 
+template<class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                duration<Rep, Period>& d, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // time_point arithmetic (all constexpr in C++14)
 template <class Clock, class Duration1, class Rep2, class Period2>
   time_point<Clock, typename common_type<Duration1, duration<Rep2, Period2>>::type>
@@ -309,6 +315,12 @@ template<class charT, class traits>                    // C++20
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const sys_days& dp);
 
+template<class charT, class traits, class Duration, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                sys_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.clock.utc], class utc_clock
 class utc_clock {                                      // C++20
 public:
@@ -336,6 +348,12 @@ template<class charT, class traits, class Duration>     // C++20
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const utc_time<Duration>& t);
 
+template<class charT, class traits, class Duration, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                utc_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 struct leap_second_info {                               // C++20
   bool    is_leap_second;
   seconds elapsed;
@@ -372,6 +390,12 @@ template<class charT, class traits, class Duration>     // C++20
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t);
 
+template<class charT, class traits, class Duration, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                tai_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.clock.gps], class gps_clock
 class gps_clock {                                      // C++20
 public:
@@ -399,6 +423,12 @@ template<class charT, class traits, class Duration>     // C++20
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& t);
 
+template<class charT, class traits, class Duration, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                gps_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 class file_clock                                        // C++20
 {
 public:
@@ -424,6 +454,12 @@ template<class charT, class traits, class Duration>     // C++20
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const file_time<Duration>& tp);
 
+template<class charT, class traits, class Duration, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                file_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 class steady_clock
 {
 public:
@@ -449,6 +485,12 @@ template<class charT, class traits, class Duration>     // C++20
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const local_time<Duration>& tp);
 
+template<class charT, class traits, class Duration, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                local_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.last] class last_spec    // C++20
 struct last_spec;
 
@@ -465,6 +507,12 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const day& d);
 
+template<class charT, class traits, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                day& d, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.month] class month    // C++20
 class month;
 constexpr bool operator==(const month& x, const month& y) noexcept;
@@ -478,6 +526,12 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const month& m);
 
+template<class charT, class traits, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                month& m, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.year] class year    // C++20
 class year;
 constexpr bool operator==(const year& x, const year& y) noexcept;
@@ -491,6 +545,12 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const year& y);
 
+template<class charT, class traits, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                year& y, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.wd] class weekday    // C++20
 class weekday;
 
@@ -503,6 +563,12 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const weekday& wd);
 
+template<class charT, class traits, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                weekday& wd, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.wdidx] class weekday_indexed    // C++20
 
 class weekday_indexed;
@@ -531,6 +597,12 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const month_day& md);
 
+template<class charT, class traits, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                month_day& md, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.mdlast] class month_day_last    // C++20
 class month_day_last;
 
@@ -578,6 +650,12 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const year_month& ym);
 
+template<class charT, class traits, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                year_month& ym, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.ymd] class year_month_day class    // C++20
 year_month_day;
 
@@ -595,6 +673,12 @@ template<class charT, class traits>
   basic_ostream<charT, traits>&
     operator<<(basic_ostream<charT, traits>& os, const year_month_day& ymd);
 
+template<class charT, class traits, class Alloc = allocator<charT>> // C++20
+  basic_istream<charT, traits>&
+    from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+                year_month_day& ymd, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+                minutes* offset = nullptr);
+
 // [time.cal.ymdlast] class year_month_day_last    // C++20
 class year_month_day_last;
 
@@ -996,6 +1080,31 @@ namespace std {
 } // namespace std
 
 namespace chrono {
+// [time.parse], parsing
+template<class charT, class Parsable> // C++20
+  unspecified parse(const charT* fmt, Parsable& tp);
+template<class charT, class traits, class Alloc, class Parsable> // C++20
+  unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp);
+
+template<class charT, class traits, class Alloc, class Parsable> // C++20
+  unspecified parse(const charT* fmt, Parsable& tp,
+                    basic_string<charT, traits, Alloc>& abbrev);
+template<class charT, class traits, class Alloc, class Parsable> // C++20
+  unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
+                    basic_string<charT, traits, Alloc>& abbrev);
+
+template<class charT, class Parsable> // C++20
+  unspecified parse(const charT* fmt, Parsable& tp, minutes& offset);
+template<class charT, class traits, class Alloc, class Parsable> // C++20
+  unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, minutes& offset);
+
+template<class charT, class traits, class Alloc, class Parsable> // C++20
+  unspecified parse(const charT* fmt, Parsable& tp,
+                    basic_string<charT, traits, Alloc>& abbrev, minutes& offset);
+template<class charT, class traits, class Alloc, class Parsable> // C++20
+  unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp,
+                    basic_string<charT, traits, Alloc>& abbrev, minutes& offset);
+
 // calendrical constants
 inline constexpr last_spec                              last{};       // C++20
 inline constexpr chrono::weekday                        Sunday{0};    // C++20
@@ -1119,7 +1228,10 @@ namespace std {
 
 #    if _LIBCPP_HAS_LOCALIZATION
 #      include <__chrono/formatter.h>
+#      include <__chrono/from_stream.h>
 #      include <__chrono/ostream.h>
+#      include <__chrono/parse.h>
+#      include <__chrono/parser_data.h>
 #      include <__chrono/parser_std_format_spec.h>
 #      include <__chrono/statically_widen.h>
 #    endif
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 76a9df3820e3e4..6feec2bdca5014 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -974,6 +974,7 @@ module std {
     module exception                  { header "__chrono/exception.h" }
     module file_clock                 { header "__chrono/file_clock.h" }
     module formatter                  { header "__chrono/formatter.h" }
+    module from_stream                { header "__chrono/from_stream.h" }
     module gps_clock {
       header "__chrono/gps_clock.h"
       export std.chrono.time_point
@@ -1001,6 +1002,8 @@ module std {
     module month                      { header "__chrono/month.h" }
     module monthday                   { header "__chrono/monthday.h" }
     module ostream                    { header "__chrono/ostream.h" }
+    module parse                      { header "__chrono/parse.h" }
+    module parser_data                { header "__chrono/parser_data.h" }
     module parser_std_format_spec     { header "__chrono/parser_std_format_spec.h" }
     module statically_widen           { header "__chrono/statically_widen.h" }
     module steady_clock {
diff --git a/libcxx/modules/std/chrono.inc b/libcxx/modules/std/chrono.inc
index d771559d15107a..bf5f00b6b4c402 100644
--- a/libcxx/modules/std/chrono.inc
+++ b/libcxx/modules/std/chrono.inc
@@ -52,8 +52,8 @@ export namespace std {
     // [time.duration.io], duration I/O
 #if _LIBCPP_HAS_LOCALIZATION
     using std::chrono::operator<<;
+    using std::chrono::from_stream;
 #endif
-    // using std::chrono::from_stream;
 
     // convenience typedefs
     using std::chrono::days;
@@ -256,7 +256,9 @@ export namespace std {
 #endif
 
   namespace chrono {
-    // using std::chrono::parse;
+#if _LIBCPP_HAS_LOCALIZATION
+    using std::chrono::parse;
+#endif
 
     // calendrical constants
     using std::chrono::last;
diff --git a/libcxx/test/libcxx/time/from_stream.pass.cpp b/libcxx/test/libcxx/time/from_stream.pass.cpp
new file mode 100644
index 00000000000000..6584dce08f10fa
--- /dev/null
+++ b/libcxx/test/libcxx/time/from_stream.pass.cpp
@@ -0,0 +1,164 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-localization
+
+#include <cassert>
+#include <chrono>
+#include <cstdint>
+#include <limits>
+#include <locale>
+#include <sstream>
+#include <string>
+
+#include "make_string.h"
+#include "test_macros.h"
+
+#define STR(S) MAKE_STRING(CharT, S)
+
+template <class CharT>
+void test_read_digits() {
+  struct TestCase {
+    std::basic_string<CharT> input;
+    unsigned width;
+    std::uint64_t limit;
+    std::uint64_t value;
+    unsigned count;
+    bool overflow;
+    CharT next;
+  };
+  const TestCase cases[] = {
+      // Read ordinary digits, stopping at the width or a non-digit.
+      {STR("12345"), 2, 12, 12, 2, false, CharT('3')},
+      {STR("0012X"), 5, 12, 12, 4, false, CharT('X')},
+      // No digits are consumed when the width is zero or the input is not numeric.
+      {STR("12"), 0, 12, 0, 0, false, CharT('1')},
+      {STR("X"), 1, 12, 0, 0, false, CharT('X')},
+      // Stop as soon as the next digit would exceed the limit.
+      {STR("12345"), 5, 12, 12, 3, true, CharT('4')},
+      {STR("13X"), 3, 12, 1, 2, true, CharT('X')},
+  };
+  for (const auto& c : cases) {
+    std::basic_istringstream<CharT> stream(c.input);
+    std::ios_base::iostate state = std::ios_base::goodbit;
+    std::chrono::__from_stream_parser<CharT, std::char_traits<CharT>> parser{stream, state};
+    auto result = parser.__read_digits(c.width, c.limit);
+    assert(result.__value == c.value);
+    assert(result.__digits_read == c.count);
+    assert(result.__overflow == c.overflow);
+    assert(state == std::ios_base::goodbit); // Reporting failure is the caller's responsibility.
+    assert(stream.peek() == c.next);
+  }
+}
+
+void test_read_signed() {
+  struct TestCase {
+    std::string input;
+    int expected;
+  };
+  const TestCase cases[] = {
+      // Ordinary values, with and without an explicit sign.
+      {"123", 123},
+      {"+123", 123},
+      {"-123", -123},
+      // The negative limit has no positive counterpart in int.
+      {std::to_string(std::numeric_limits<int>::min()), std::numeric_limits<int>::min()},
+  };
+  for (const auto& c : cases) {
+    std::istringstream stream{c.input};
+    int result                   = -1;
+    std::ios_base::iostate state = std::ios_base::goodbit;
+    std::chrono::__from_stream_parser<char, std::char_traits<char>> parser{stream, state};
+    parser.__read_signed(static_cast<unsigned>(c.input.size()), result);
+    assert(!(state & (std::ios_base::failbit | std::ios_base::badbit)));
+    assert(result == c.expected);
+  }
+}
+
+void test_field_queries() {
+  using Fields         = std::chrono::__fields_storage;
+  using Parts          = std::chrono::__fields_set;
+  constexpr auto check = [] {
+    Fields fields;
+    assert(!fields.__has(Parts::__day));
+    assert(!fields.__has_any(Parts::__day | Parts::__month));
+    fields.__set(Parts::__utc_offset);
+    assert(fields.__has(Parts::__utc_offset));
+    assert(!fields.__has_exactly(Parts::__day));
+    fields.__set(Parts::__day);
+    // __has_only and __has_exactly ignore the UTC offset field.
+    assert(fields.__has_only(Parts::__day));
+    assert(fields.__has_exactly(Parts::__day));
+    assert(fields.__has(Parts::__day | Parts::__utc_offset));
+    assert(fields.__has_any(Parts::__day | Parts::__month));
+    assert(!fields.__has(Parts::__day | Parts::__month));
+    assert(fields.__has_only(Parts::__day | Parts::__month));
+    assert(fields.__has_exactly(Parts::__day, Parts::__month));
+    fields.__set(Parts::__month);
+    assert(!fields.__has_only(Parts::__day));
+    assert(!fields.__has_exactly(Parts::__day));
+    assert(fields.__has_exactly(Parts::__day, Parts::__month));
+    assert(fields.__has_exactly(Parts::__day | Parts::__month));
+    return true;
+  };
+  static_assert(check());
+  assert(check());
+}
+
+template <class CharT, class T>
+void check_repeated_field(const std::basic_string<CharT>& format,
+                          const std::basic_string<CharT>& matching,
+                          const std::basic_string<CharT>& conflicting,
+                          T expected) {
+  {
+    std::basic_istringstream<CharT> stream(matching);
+    stream.imbue(std::locale::classic());
+    T result{};
+    std::chrono::from_stream(stream, format.c_str(), result);
+    assert(!stream.fail());
+    assert(result == expected);
+  }
+  {
+    std::basic_istringstream<CharT> stream(conflicting);
+    stream.imbue(std::locale::classic());
+    T result{};
+    std::chrono::from_stream(stream, format.c_str(), result);
+    assert(stream.fail());
+  }
+}
+
+template <class CharT>
+void test_repeated_fields() {
+  using namespace std::chrono;
+  // libc++ accepts equal repetitions and rejects conflicting values.
+  check_repeated_field(STR("%d %d"), STR("01 01"), STR("01 02"), day{1});
+
+  // Compound formats and locale formats share the same parsed fields.
+  check_repeated_field(STR("%F %x"), STR("2026-07-20 07/20/26"), STR("2026-07-20 07/21/26"), 2026y / July / 20);
+
+  // Compare fractional values, not their spelling; locale seconds have no fraction.
+  check_repeated_field(STR("%S %S"), STR("1.25 1.250"), STR("1.25 1.5"), 1250ms);
+  check_repeated_field(STR("%S %X"), STR("1.0 00:00:01"), STR("1.5 00:00:01"), 1000ms);
+
+  // Zone fields are checked even without output pointers.
+  check_repeated_field(STR("%d %z %Ez"), STR("01 +0100 +1:00"), STR("01 +0100 +2:00"), day{1});
+  check_repeated_field(STR("%d %Z %Z"), STR("01 UTC UTC"), STR("01 UTC GMT"), day{1});
+}
+
+int main(int, char**) {
+  test_read_signed();
+  test_field_queries();
+  test_read_digits<char>();
+  test_repeated_fields<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test_read_digits<wchar_t>();
+  test_repeated_fields<wchar_t>();
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/time/time.parse/from_stream.pass.cpp b/libcxx/test/std/time/time.parse/from_stream.pass.cpp
new file mode 100644
index 00000000000000..fa722f7093c7e5
--- /dev/null
+++ b/libcxx/test/std/time/time.parse/from_stream.pass.cpp
@@ -0,0 +1,463 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-localization
+// XFAIL: availability-tzdb-missing && !libcpp-has-no-experimental-tzdb && !no-tzdb && !no-filesystem
+
+// <chrono>
+// from_stream overloads for calendar types, durations, and time points.
+
+#include <cassert>
+#include <chrono>
+#include <initializer_list>
+#include <limits>
+#include <locale>
+#include <ratio>
+#include <sstream>
+#include <string>
+
+#include "make_string.h"
+#include "test_macros.h"
+
+#define STR(S) MAKE_STRING(CharT, S)
+
+template <class CharT, class T>
+void check(const std::basic_string<CharT>& input, const std::basic_string<CharT>& format, T expected) {
+  std::basic_istringstream<CharT> stream(input);
+  stream.imbue(std::locale::classic());
+  T result{};
+  std::chrono::from_stream(stream, format.c_str(), result);
+  assert(!stream.fail());
+  assert(result == expected);
+}
+
+template <class T, class CharT>
+void check_failure(const std::basic_string<CharT>& input, const std::basic_string<CharT>& format) {
+  std::basic_istringstream<CharT> stream(input);
+  stream.imbue(std::locale::classic());
+  T result{};
+  std::chrono::from_stream(stream, format.c_str(), result);
+  assert(stream.fail());
+}
+
+template <class CharT>
+void test_calendar_types() {
+  using namespace std::chrono;
+  check(STR("15"), STR("%d"), day{15});
+  check(STR(" 15"), STR("%n%e"), day{15});
+  // Zone fields are consumed even when their output pointers are null.
+  check(STR("15 UTC +0130"), STR("%d %Z %z"), day{15});
+  check_failure<day>(STR("02-15"), STR("%m-%d"));
+  check_failure<day>(STR("15 00"), STR("%d %H"));
+  check_failure<day>(STR("32"), STR("%d"));
+
+  check(STR("02"), STR("%m"), February);
+  check(STR("Feb"), STR("%b"), February);
+  check_failure<month>(STR("13"), STR("%m"));
+
+  check(STR("2026"), STR("%Y"), 2026y);
+
+  check(STR("Mon"), STR("%a"), Monday);
+  check(STR("1"), STR("%u"), Monday);
+  check_failure<weekday>(STR("7"), STR("%w"));
+
+  check(STR("02-15"), STR("%m-%d"), February / 15);
+  check(STR("02-29"), STR("%m-%d"), February / 29);
+  check(STR("32"), STR("%j"), February / 1);
+  check_failure<month_day>(STR("60"), STR("%j"));
+  check_failure<month_day>(STR("02-30"), STR("%m-%d"));
+  check_failure<month_day>(STR("02"), STR("%m"));
+
+  check(STR("2026-02"), STR("%Y-%m"), 2026y / February);
+  check_failure<year_month>(STR("2026-13"), STR("%Y-%m"));
+
+  const year_month_day date = 2026y / February / 15;
+  check(STR("2026-02-15"), STR("%F"), date);
+  check(STR("2026 046"), STR("%Y %j"), date);
+  check(STR("2026-W07-7"), STR("%G-W%V-%u"), date);
+  check(STR("68 69-W01-1"), STR("%y %g-W%V-%u"), 2068y / December / 31);
+  check(STR("-32768-W53-6"), STR("%6G-W%V-%u"), (year::min)() / January / 1);
+  check(STR("2026 07 0"), STR("%Y %U %w"), date);
+  check(STR("2026 06 7"), STR("%Y %W %u"), date);
+  check(STR("2026-02-15 Sun"), STR("%F %a"), date);
+  check_failure<year_month_day>(STR("2026-02-15 Mon"), STR("%F %a"));
+  check_failure<year_month_day>(STR("2026-02-30"), STR("%F"));
+  check_failure<year_month_day>(STR("2026-02"), STR("%Y-%m"));
+  check_failure<year_month_day>(STR("2021-W53-5"), STR("%G-W%V-%u"));
+}
+
+template <class CharT>
+void test_format() {
+  using namespace std::chrono;
+  const sys_seconds date      = sys_days{2026y / July / 20};
+  const sys_seconds date_time = date + 13h + 45min + 30s;
+
+  // Individual and compound directives.
+  check(STR("2026-07-20 13:45:30"), STR("%Y-%m-%d %H:%M:%S"), date_time);
+  check(STR("2026-07-7"), STR("%Y-%m-%e"), sys_seconds{sys_days{2026y / July / 7}});
+  check(STR("2026-07-20 13:45:30"), STR("%F %T"), date_time);
+  check(STR("2026-07-20 13:45"), STR("%F %R"), date + 13h + 45min);
+  check(STR("07/20/26"), STR("%D"), date);
+  check(STR("30"), STR("%S"), 30s);
+
+  // Named fields and locale-specific date/time formats in the classic locale.
+  check(STR("Monday"), STR("%A"), Monday);
+  check(STR("July"), STR("%B"), July);
+  check(STR("Jul"), STR("%h"), July);
+  check(STR("Mon Jul 20 13:45:30 2026"), STR("%c"), date_time);
+  check_failure<sys_seconds>(STR("Tue Jul 20 13:45:30 2026"), STR("%c"));
+  check(STR("07/20/26"), STR("%x"), date);
+
+  // A width on %F applies only to %Y.
+  check(STR("002026-07-20"), STR("%6F"), date);
+  check(STR("26-W30-1"), STR("%g-W%V-%u"), date);
+
+  // Literals and whitespace, including a match of zero whitespace characters.
+  check(STR("2026-07-20%"), STR("%F%%"), date);
+  check(STR("2026\t07\t20"), STR("%Y%t%m%t%d"), date);
+  check(STR("   2026-07-20"), STR(" %F"), date);
+  check(STR("2026-07-20"), STR(" %Y-%m-%d"), date);
+
+  check_failure<sys_seconds>(STR("2026/07/20"), STR("%Y-%m-%d"));
+  check_failure<sys_seconds>(STR("13:45:30"), STR("%H:%M:%S"));
+  check_failure<sys_seconds>(STR("2026-07-xx"), STR("%Y-%m-%d"));
+  check_failure<sys_seconds>(STR("2026-07- 7"), STR("%Y-%m-%e"));
+}
+
+template <class CharT>
+void test_width_overflow() {
+  using namespace std::chrono;
+  std::basic_ostringstream<CharT> format;
+  format << CharT('%') << std::numeric_limits<unsigned>::max() << STR("0S");
+
+  // Reject an overflowing format width before reading the input.
+  std::basic_istringstream<CharT> stream{STR("1.25!")};
+  milliseconds result{};
+  from_stream(stream, format.str().c_str(), result);
+  assert(stream.fail());
+  stream.clear();
+  assert(stream.peek() == CharT('1'));
+}
+
+template <class CharT>
+void test_date_consistency() {
+  using namespace std::chrono;
+  const year_month_day feb1 = 2026y / February / 1;
+  const year_month_day jan1 = 2021y / January / 1;
+
+  // An ordinal date must agree with the supplied month.
+  check(STR("2026 032 02"), STR("%Y %j %m"), feb1);
+  check_failure<year_month_day>(STR("2026 032 03"), STR("%Y %j %m"));
+
+  // An ISO week date must agree with the calendar year, even across a year boundary.
+  check(STR("2020-W53-5 2021"), STR("%G-W%V-%u %Y"), jan1);
+  check_failure<year_month_day>(STR("2020-W53-5 2020"), STR("%G-W%V-%u %Y"));
+  check(STR("1926-W01-1 26"), STR("%G-W%V-%u %g"), 1926y / January / 4);
+}
+
+template <class CharT>
+void test_modifier_E() {
+  using namespace std::chrono;
+  const sys_seconds date = sys_days{2026y / July / 20};
+
+  check(STR("Mon Jul 20 13:45:30 2026"), STR("%Ec"), date + 13h + 45min + 30s);
+  check(STR("07/20/26"), STR("%Ex"), date);
+
+  // Numeric years in the classic locale.
+  for (const auto& format : {STR("%EC %Ey-%m-%d"), STR("%EC %EY-%m-%d")}) {
+    std::basic_istringstream<CharT> stream(format == STR("%EC %Ey-%m-%d") ? STR("20 26-07-20") : STR("20 2026-07-20"));
+    stream.imbue(std::locale::classic());
+    sys_seconds result{};
+    from_stream(stream, format.c_str(), result);
+    assert(!stream.fail());
+    assert(result == date);
+  }
+
+  // Parse a century and a UTC offset.
+  {
+    std::basic_istringstream<CharT> stream(STR("20 26-07-20 +4:30"));
+    stream.imbue(std::locale::classic());
+    sys_seconds result{};
+    from_stream(stream, STR("%EC %y-%m-%d %Ez").c_str(), result);
+    assert(!stream.fail());
+    assert(result == date - 4h - 30min);
+  }
+}
+
+template <class CharT>
+void test_modifier_O() {
+  using namespace std::chrono;
+  const sys_seconds date = sys_days{2026y / July / 20};
+
+  check(STR("2026-07-20"), STR("%Y-%m-%Oe"), date);
+
+  // Parse numeric fields, including twelve o'clock with PM.
+  {
+    std::basic_istringstream<CharT> stream(STR("26-07-20 13:45 1!"));
+    stream.imbue(std::locale::classic());
+    sys_seconds result{};
+    from_stream(stream, STR("%Oy-%Om-%Od %OH:%OM %Ow").c_str(), result);
+    assert(!stream.fail());
+    assert(result == date + 13h + 45min);
+    assert(stream.peek() == CharT('!'));
+  }
+  {
+    std::basic_istringstream<CharT> stream(STR("2026-07-20 12 PM"));
+    stream.imbue(std::locale::classic());
+    sys_seconds result{};
+    from_stream(stream, STR("%F %OI %p").c_str(), result);
+    assert(!stream.fail());
+    assert(result == date + 12h);
+  }
+
+  // %OS, %OU and %OW parse numerically; %Oz uses the offset parser.
+  {
+    std::basic_istringstream<CharT> stream(STR("2026-07-20 13:45:30.125 +4:30"));
+    stream.imbue(std::locale::classic());
+    sys_time<milliseconds> result{};
+    from_stream(stream, STR("%F %H:%M:%OS %Oz").c_str(), result);
+    assert(!stream.fail());
+    assert(result == date + 13h + 45min + 30s + 125ms - 4h - 30min);
+  }
+  for (const auto& format : {STR("%Y %OU %w"), STR("%Y %OW %w")}) {
+    std::basic_istringstream<CharT> stream(STR("2026 29 1"));
+    stream.imbue(std::locale::classic());
+    sys_seconds result{};
+    from_stream(stream, format.c_str(), result);
+    assert(!stream.fail());
+    assert(result == date);
+  }
+}
+
+template <class CharT>
+struct comma_numpunct : std::numpunct<CharT> {
+  CharT do_decimal_point() const override { return CharT(','); }
+};
+
+template <class CharT>
+void test_fractional_seconds() {
+  using namespace std::chrono;
+  check(STR("1.25"), STR("%S"), 1250ms);
+  check(STR(".5"), STR("%S"), 500ms);
+  check(STR("1."), STR("%S"), 1000ms);
+  check(STR(".5!"), STR("%2S!"), 500ms);
+  // Floating-point representations allow fractions even with a whole-second period.
+  check(STR("12.125s"), STR("%Ss"), duration<double>{12.125});
+  // An explicit width controls consumption independently of the target precision.
+  check(STR("1.2345!"), STR("%6S!"), 1234ms);
+
+  // An integer seconds target leaves the decimal point unread, regardless of width.
+  for (const auto& format : {STR("%S"), STR("%6S")}) {
+    std::basic_istringstream<CharT> stream(STR("1.25"));
+    stream.imbue(std::locale::classic());
+    duration<int> result{};
+    from_stream(stream, format.c_str(), result);
+    assert(!stream.fail());
+    assert(result == 1s);
+    assert(stream.peek() == CharT('.'));
+  }
+  {
+    std::basic_istringstream<CharT> stream(STR("1,25!"));
+    stream.imbue(std::locale(std::locale::classic(), new comma_numpunct<CharT>));
+    milliseconds result{};
+    from_stream(stream, STR("%S").c_str(), result);
+    assert(!stream.fail());
+    assert(result == 1250ms);
+    assert(stream.peek() == CharT('!'));
+  }
+  {
+    // The width includes the decimal point and limits the fractional digits.
+    std::basic_istringstream<CharT> stream(STR("1.234"));
+    stream.imbue(std::locale::classic());
+    milliseconds result{};
+    from_stream(stream, STR("%3S").c_str(), result);
+    assert(!stream.fail());
+    assert(result == 1200ms);
+    assert(stream.peek() == CharT('3'));
+  }
+}
+
+template <class CharT>
+void test_time_points() {
+  using namespace std::chrono;
+  const sys_seconds expected = sys_days{2026y / July / 20} + 13h + 45min + 30s;
+  auto test = [&](auto value) { check(STR("20 26-07-20 01:45:30 PM"), STR("%C %y-%m-%d %I:%M:%S %p"), value); };
+  test(expected);
+  test(local_seconds{expected.time_since_epoch()});
+  test(file_clock::from_sys(expected));
+
+  check(STR("2026-07-20"), STR("%F"), sys_days{2026y / July / 20});
+  // A days target rejects time-of-day fields even when the UTC offset would cancel them.
+  check_failure<sys_days>(STR("2026-07-20 04:00 +0400"), STR("%F %R %z"));
+  check(STR("1969-12-31 23:59:59.5"), STR("%F %T"), sys_time<milliseconds>{-500ms});
+  check(STR("1970-01-01 00:00:12.125!"), STR("%F %T!"), sys_time<duration<double>>{duration<double>{12.125}});
+  check(STR("1970-01-01 00:00:01"), STR("%F %T"), sys_time<duration<long long, std::atto>>{1s});
+
+#if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&                             \
+    !defined(TEST_HAS_NO_FILESYSTEM)
+  // Combine the date and time of day before rounding to a unit that does not divide a day.
+  using SevenSeconds = duration<long long, std::ratio<7>>;
+  check(STR("1958-01-02 00:02"), STR("%F %R"), tai_time<SevenSeconds>{SevenSeconds{12360}});
+#endif
+}
+
+#if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&                             \
+    !defined(TEST_HAS_NO_FILESYSTEM)
+template <class CharT>
+void test_utc_leap_seconds() {
+  using namespace std::chrono;
+  const utc_seconds leap = utc_clock::from_sys(sys_days{2017y / January / 1}) - 1s;
+  check(STR("2016-12-31 23:59:60"), STR("%F %T"), leap);
+  check(STR("2017-01-01 00:59:60.5 +0100"), STR("%F %T %z"), leap + 500ms);
+  check_failure<utc_seconds>(STR("2026-07-20 12:00:60"), STR("%F %T"));
+}
+#endif
+
+template <class CharT>
+void test_year_fields() {
+  using namespace std::chrono;
+  check(STR("+123"), STR("%4Y"), year{123});
+  check(STR("-123"), STR("%4Y"), year{-123});
+  check(STR("0"), STR("%Y"), year{0});
+
+  // Two-digit years use a default century unless %C or %Y supplies one.
+  check(STR("68"), STR("%y"), year{2068});
+  check(STR("69"), STR("%y"), year{1969});
+  check(STR("20 26"), STR("%C %y"), 2026y);
+  check(STR("-20 76"), STR("%3C %y"), year{-1976});
+  check(STR("2026 20"), STR("%Y %C"), 2026y);
+  check(STR("1926 26"), STR("%Y %y"), 1926y);
+  check(STR("1926-07-20 26"), STR("%F %y"), 1926y / July / 20);
+
+  // A sign consumes one character of the field's width.
+  {
+    std::basic_istringstream<CharT> stream(STR("+123"));
+    stream.imbue(std::locale::classic());
+    year result{};
+    from_stream(stream, STR("%3Y").c_str(), result);
+    assert(!stream.fail());
+    assert(result == year{12});
+    assert(stream.peek() == CharT('3'));
+  }
+
+  check_failure<year>(STR("100"), STR("%3y"));
+  check_failure<year>(STR("+1"), STR("%1Y"));
+  check_failure<year>(STR("2026 25"), STR("%Y %y"));
+  check_failure<year>(STR("20"), STR("%C"));
+}
+
+template <class CharT>
+void test_duration() {
+  using namespace std::chrono;
+  // Parse time-of-day and day-count components.
+  for (const auto& format : {STR("%T"), STR("%X"), STR("%EX")})
+    check(STR("01:30:00"), format, 5400s);
+  check(STR("01:30:00 AM"), STR("%r"), 5400s);
+  check(STR("PM 01:30"), STR("%p %I:%M"), 810min);
+  check(STR("2"), STR("%j"), days{2});
+  check(STR("2 01:30"), STR("%j %R"), 48h + 90min);
+  check(STR("23:59:59"), STR("%T"), 23h + 59min + 59s);
+
+  check_failure<seconds>(STR("15 01"), STR("%d %H"));
+  check_failure<hours>(STR("01:30"), STR("%R"));
+  check_failure<minutes>(STR("PM"), STR("%p"));
+  check_failure<minutes>(STR("60"), STR("%M"));
+  check_failure<seconds>(STR("60"), STR("%S"));
+}
+
+template <class CharT>
+void test_hours() {
+  using namespace std::chrono;
+  // %H can disambiguate %I without %p, in either input order.
+  check(STR("13 01 PM"), STR("%H %I %p"), 13h);
+  check(STR("13 01"), STR("%H %I"), 13h);
+  check(STR("01 13"), STR("%I %H"), 13h);
+  check(STR("00 12"), STR("%H %I"), 0h);
+  check(STR("12 12"), STR("%H %I"), 12h);
+
+  check_failure<minutes>(STR("14 01"), STR("%H %I"));
+  check_failure<minutes>(STR("13 AM"), STR("%H %p"));
+  check_failure<hours>(STR("24"), STR("%H"));
+  check_failure<minutes>(STR("13 PM"), STR("%I %p"));
+}
+
+template <class CharT>
+void test_duration_conversion() {
+  using namespace std::chrono;
+
+  check(STR("42"), STR("%S"), duration<unsigned>{42});
+  check(STR("1.25"), STR("%S"), duration<double, std::milli>{1250});
+  // A 1.5-second integer tick is coarser than the seconds field.
+  check_failure<duration<int, std::ratio<3, 2>>>(STR("1.5"), STR("%S"));
+}
+
+template <class CharT>
+void test_offsets() {
+  using namespace std::chrono;
+  const sys_seconds date = sys_days{2026y / July / 20};
+  check(STR("2026-07-20 04"), STR("%F %z"), date - 4h);
+  check(STR("2026-07-20 0430"), STR("%F %z"), date - 4h - 30min);
+  check(STR("2026-07-20 -0130"), STR("%F %z"), date + 90min);
+  // Offset minutes are not clock-minute fields restricted to 0-59.
+  check(STR("2026-07-20 +0160"), STR("%F %z"), date - 120min);
+
+  check(STR("2026-07-20 4"), STR("%F %Ez"), date - 4h);
+  check(STR("2026-07-20 +4:30"), STR("%F %Ez"), date - 4h - 30min);
+  check(STR("2026-07-20 +4:30"), STR("%F %Oz"), date - 4h - 30min);
+  check(STR("2026-07-20 -4:30"), STR("%F %Ez"), date + 4h + 30min);
+
+  // Basic hours and any supplied minutes require two digits.
+  check_failure<sys_seconds>(STR("2026-07-20 019"), STR("%F %z"));
+  check_failure<sys_seconds>(STR("2026-07-20 4:9"), STR("%F %Ez"));
+  check_failure<sys_seconds>(STR("2026-07-20 4"), STR("%F %z"));
+}
+
+template <class CharT>
+void test_abbrev() {
+  using namespace std::chrono;
+  std::basic_istringstream<CharT> stream(STR("2026-07-20 a_1/+B-2!"));
+  stream.imbue(std::locale::classic());
+  sys_days result{};
+  std::basic_string<CharT> abbrev = STR("original");
+  from_stream(stream, STR("%F %Z").c_str(), result, &abbrev);
+  assert(!stream.fail());
+  assert(result == sys_days{2026y / July / 20});
+  assert(abbrev == STR("a_1/+B-2"));
+  assert(stream.peek() == CharT('!'));
+}
+
+template <class CharT>
+void test() {
+  test_calendar_types<CharT>();
+  test_format<CharT>();
+  test_width_overflow<CharT>();
+  test_date_consistency<CharT>();
+  test_modifier_E<CharT>();
+  test_modifier_O<CharT>();
+  test_fractional_seconds<CharT>();
+  test_year_fields<CharT>();
+  test_duration<CharT>();
+  test_hours<CharT>();
+  test_duration_conversion<CharT>();
+  test_time_points<CharT>();
+#if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&                             \
+    !defined(TEST_HAS_NO_FILESYSTEM)
+  test_utc_leap_seconds<CharT>();
+#endif
+  test_offsets<CharT>();
+  test_abbrev<CharT>();
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/time/time.parse/parse.pass.cpp b/libcxx/test/std/time/time.parse/parse.pass.cpp
new file mode 100644
index 00000000000000..e1f894f3184149
--- /dev/null
+++ b/libcxx/test/std/time/time.parse/parse.pass.cpp
@@ -0,0 +1,176 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: no-localization
+
+// <chrono>
+// parse: string and pointer formats, optional outputs, constraints, and ADL.
+
+#include <cassert>
+#include <chrono>
+#include <concepts>
+#include <locale>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "make_string.h"
+#include "test_macros.h"
+
+#define STR(S) MAKE_STRING(CharT, S)
+
+template <class... Args>
+concept CanParse = requires(Args&&... args) { std::chrono::parse(std::forward<Args>(args)...); };
+
+namespace custom {
+template <int Arity>
+struct value {
+  int count = 0;
+};
+
+template <class CharT, class Traits>
+std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, value<3>& out) {
+  assert(fmt[0] == CharT('#'));
+  return is >> out.count;
+}
+
+template <class CharT, class Traits, class Alloc>
+std::basic_istream<CharT, Traits>&
+from_stream(std::basic_istream<CharT, Traits>& is,
+            const CharT* fmt,
+            value<4>& out,
+            std::basic_string<CharT, Traits, Alloc>* abbrev) {
+  assert(fmt[0] == CharT('#'));
+  assert(abbrev != nullptr);
+  *abbrev = STR("custom");
+  return is >> out.count;
+}
+
+template <class CharT, class Traits, class Alloc>
+std::basic_istream<CharT, Traits>&
+from_stream(std::basic_istream<CharT, Traits>& is,
+            const CharT* fmt,
+            value<5>& out,
+            std::basic_string<CharT, Traits, Alloc>* abbrev,
+            std::chrono::minutes* offset) {
+  assert(fmt[0] == CharT('#'));
+  assert(offset != nullptr);
+  if (abbrev)
+    *abbrev = STR("custom");
+  *offset = std::chrono::minutes{90};
+  return is >> out.count;
+}
+
+struct not_parsable {};
+} // namespace custom
+
+template <class CharT, class Format, int Arity>
+void check_constraints() {
+  using String  = std::basic_string<CharT>;
+  using Value   = custom::value<Arity>;
+  using Minutes = std::chrono::minutes;
+  static_assert(CanParse<const Format&, Value&> == (Arity == 3));
+  static_assert(CanParse<const Format&, Value&, String&> == (Arity == 4));
+  static_assert(CanParse<const Format&, Value&, Minutes&> == (Arity == 5));
+  static_assert(CanParse<const Format&, Value&, String&, Minutes&> == (Arity == 5));
+}
+
+template <class CharT, class Format>
+void test_constraints() {
+  check_constraints<CharT, Format, 3>();
+  check_constraints<CharT, Format, 4>();
+  check_constraints<CharT, Format, 5>();
+  static_assert(!CanParse<const Format&, custom::not_parsable&>);
+  static_assert(!CanParse<const Format&, const custom::value<3>&>);
+  static_assert(!CanParse<const Format&, custom::value<3>>);
+}
+
+template <class CharT, class Format>
+void test_adl() {
+  using String              = std::basic_string<CharT>;
+  const auto format_storage = STR("#");
+  const Format fmt{format_storage.c_str()};
+  {
+    std::basic_istringstream<CharT> is(STR("7"));
+    custom::value<3> result{};
+    auto& returned = is >> std::chrono::parse(fmt, result);
+    assert(&returned == &is);
+    assert(!is.fail());
+    assert(result.count == 7);
+  }
+  {
+    std::basic_istringstream<CharT> is(STR("7"));
+    custom::value<5> result{};
+    String abbrev;
+    std::chrono::minutes offset{};
+    is >> std::chrono::parse(fmt, result, abbrev, offset);
+    assert(!is.fail());
+    assert(result.count == 7);
+    assert(abbrev == STR("custom"));
+    assert(offset == std::chrono::minutes{90});
+  }
+}
+
+template <class CharT, class Format>
+void test_chrono_overloads() {
+  using namespace std::chrono;
+  const sys_seconds date    = sys_days{2026y / July / 20};
+  const auto format_storage = STR("%F %Z %z");
+  const Format fmt{format_storage.c_str()};
+  // Test both format types, with and without optional outputs.
+  {
+    std::basic_istringstream<CharT> is(STR("2026-07-20 UTC +0130!"));
+    is.imbue(std::locale::classic());
+    sys_seconds result{};
+    static_assert(std::same_as<decltype(is >> parse(fmt, result)), std::basic_istream<CharT>&>);
+    auto& returned = is >> parse(fmt, result);
+    assert(&returned == &is);
+    assert(!is.fail());
+    assert(result == date - 90min);
+    assert(is.peek() == CharT('!'));
+  }
+  {
+    std::basic_istringstream<CharT> is(STR("2026-07-20 UTC +0130!"));
+    is.imbue(std::locale::classic());
+    sys_seconds result{};
+    std::basic_string<CharT> abbrev;
+    minutes offset{};
+    is >> parse(fmt, result, abbrev, offset);
+    assert(!is.fail());
+    assert(result == date - 90min);
+    assert(is.peek() == CharT('!'));
+    assert(abbrev == STR("UTC"));
+    assert(offset == 90min);
+  }
+
+  // A parsing failure is visible on the original stream.
+  std::basic_istringstream<CharT> is(STR("invalid"));
+  is.imbue(std::locale::classic());
+  sys_seconds result{};
+  is >> parse(fmt, result);
+  assert(is.fail());
+}
+
+template <class CharT>
+void test() {
+  test_constraints<CharT, const CharT*>();
+  test_constraints<CharT, std::basic_string<CharT>>();
+  test_adl<CharT, const CharT*>();
+  test_adl<CharT, std::basic_string<CharT>>();
+  test_chrono_overloads<CharT, const CharT*>();
+  test_chrono_overloads<CharT, std::basic_string<CharT>>();
+}
+
+int main(int, char**) {
+  test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  test<wchar_t>();
+#endif
+  return 0;
+}

>From 7794b3a67600abd388f5c815a3007554d77304d5 Mon Sep 17 00:00:00 2001
From: Emmett <emmettzhang2020 at outlook.com>
Date: Thu, 1 Oct 2026 23:09:35 +0800
Subject: [PATCH 2/6] fix some review comments and CI failure

---
 libcxx/docs/Status/Cxx20Issues.csv           | 14 +++++++-------
 libcxx/docs/Status/Cxx23Issues.csv           |  4 ++--
 libcxx/docs/Status/Cxx26Issues.csv           |  4 ++--
 libcxx/include/__chrono/from_stream.h        |  4 ++++
 libcxx/include/__chrono/parser_data.h        | 14 ++++++++++----
 libcxx/test/libcxx/time/from_stream.pass.cpp |  2 +-
 6 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index e4ff0f28b5d33c..d00cbd31ad8780 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -164,16 +164,16 @@
 "`LWG3231 <https://wg21.link/LWG3231>`__","``year_month_day_last::day``\  specification does not cover ``!ok()``\  values","2019-11 (Belfast)","|Nothing To Do|","","`#103862 <https://github.com/llvm/llvm-project/issues/103862>`__",""
 "`LWG3225 <https://wg21.link/LWG3225>`__","``zoned_time``\  converting constructor shall not be ``noexcept``\ ","2019-11 (Belfast)","|Complete|","19","`#103863 <https://github.com/llvm/llvm-project/issues/103863>`__",""
 "`LWG3190 <https://wg21.link/LWG3190>`__","``std::allocator::allocate``\  sometimes returns too little storage","2019-11 (Belfast)","|Complete|","14","`#103864 <https://github.com/llvm/llvm-project/issues/103864>`__",""
-"`LWG3218 <https://wg21.link/LWG3218>`__","Modifier for ``%d``\  parse flag does not match POSIX and ``format``\  specification","2019-11 (Belfast)","","","`#100258 <https://github.com/llvm/llvm-project/issues/100258>`__",""
+"`LWG3218 <https://wg21.link/LWG3218>`__","Modifier for ``%d``\  parse flag does not match POSIX and ``format``\  specification","2019-11 (Belfast)","|Partial|","","`#100258 <https://github.com/llvm/llvm-project/issues/100258>`__","``%Od`` is accepted, but parsing locale-specific alternative digits is not implemented."
 "`LWG3224 <https://wg21.link/LWG3224>`__","``zoned_time``\  constructor from ``TimeZonePtr``\  does not specify initialization of ``tp_``\ ","2019-11 (Belfast)","|Complete|","19","`#103865 <https://github.com/llvm/llvm-project/issues/103865>`__",""
 "`LWG3230 <https://wg21.link/LWG3230>`__","Format specifier ``%y/%Y``\  is missing locale alternative versions","2019-11 (Belfast)","|Complete|","16","`#103868 <https://github.com/llvm/llvm-project/issues/103868>`__",""
 "`LWG3232 <https://wg21.link/LWG3232>`__","Inconsistency in ``zoned_time``\  deduction guides","2019-11 (Belfast)","|Complete|","19","`#103869 <https://github.com/llvm/llvm-project/issues/103869>`__",""
 "`LWG3222 <https://wg21.link/LWG3222>`__","P0574R1 introduced preconditions on non-existent parameters","2019-11 (Belfast)","","","`#100259 <https://github.com/llvm/llvm-project/issues/100259>`__",""
 "`LWG3221 <https://wg21.link/LWG3221>`__","Result of ``year_month``\  arithmetic with ``months``\  is ambiguous","2019-11 (Belfast)","|Complete|","8","`#103870 <https://github.com/llvm/llvm-project/issues/103870>`__",""
-"`LWG3235 <https://wg21.link/LWG3235>`__","``parse``\  manipulator without abbreviation is not callable","2019-11 (Belfast)","","","`#100262 <https://github.com/llvm/llvm-project/issues/100262>`__",""
+"`LWG3235 <https://wg21.link/LWG3235>`__","``parse``\  manipulator without abbreviation is not callable","2019-11 (Belfast)","|Complete|","24","`#100262 <https://github.com/llvm/llvm-project/issues/100262>`__",""
 "`LWG3246 <https://wg21.link/LWG3246>`__","LWG3246: What are the constraints on the template parameter of ``basic_format_arg``?","2019-11 (Belfast)","|Nothing To Do|","","`#100263 <https://github.com/llvm/llvm-project/issues/100263>`__",""
 "`LWG3253 <https://wg21.link/LWG3253>`__","``basic_syncbuf::basic_syncbuf()``\  should not be explicit","2019-11 (Belfast)","|Complete|","20","`#100264 <https://github.com/llvm/llvm-project/issues/100264>`__",""
-"`LWG3245 <https://wg21.link/LWG3245>`__","Unnecessary restriction on ``'%p'``\  parse specifier","2019-11 (Belfast)","","","`#100265 <https://github.com/llvm/llvm-project/issues/100265>`__",""
+"`LWG3245 <https://wg21.link/LWG3245>`__","Unnecessary restriction on ``'%p'``\  parse specifier","2019-11 (Belfast)","|Complete|","24","`#100265 <https://github.com/llvm/llvm-project/issues/100265>`__",""
 "`LWG3244 <https://wg21.link/LWG3244>`__","Constraints for ``Source``\  in |sect|\ [fs.path.req] insufficiently constrainty","2019-11 (Belfast)","","","`#100266 <https://github.com/llvm/llvm-project/issues/100266>`__",""
 "`LWG3241 <https://wg21.link/LWG3241>`__","``chrono-spec``\  grammar ambiguity in |sect|\ [time.format]","2019-11 (Belfast)","|Complete|","16","`#103871 <https://github.com/llvm/llvm-project/issues/103871>`__",""
 "`LWG3257 <https://wg21.link/LWG3257>`__","Missing feature testing macro update from P0858","2019-11 (Belfast)","|Complete|","12","`#103873 <https://github.com/llvm/llvm-project/issues/103873>`__",""
@@ -181,7 +181,7 @@
 "`LWG3273 <https://wg21.link/LWG3273>`__","Specify ``weekday_indexed``\  to range of ``[0, 7]``\ ","2019-11 (Belfast)","|Complete|","16","`#103875 <https://github.com/llvm/llvm-project/issues/103875>`__",""
 "`LWG3070 <https://wg21.link/LWG3070>`__","``path::lexically_relative``\  causes surprising results if a filename can also be a  *root-name*","2019-11 (Belfast)","","","`#100267 <https://github.com/llvm/llvm-project/issues/100267>`__",""
 "`LWG3266 <https://wg21.link/LWG3266>`__","``to_chars(bool)``\  should be deleted","2019-11 (Belfast)","|Complete|","14","`#103876 <https://github.com/llvm/llvm-project/issues/103876>`__",""
-"`LWG3272 <https://wg21.link/LWG3272>`__","``%I%p``\  should parse/format ``duration``\  since midnight","2019-11 (Belfast)","","","`#100268 <https://github.com/llvm/llvm-project/issues/100268>`__",""
+"`LWG3272 <https://wg21.link/LWG3272>`__","``%I%p``\  should parse/format ``duration``\  since midnight","2019-11 (Belfast)","|Complete|","24","`#100268 <https://github.com/llvm/llvm-project/issues/100268>`__",""
 "`LWG3259 <https://wg21.link/LWG3259>`__","The definition of *constexpr iterators* should be adjusted","2019-11 (Belfast)","|Nothing To Do|","","`#103877 <https://github.com/llvm/llvm-project/issues/103877>`__",""
 "`LWG3103 <https://wg21.link/LWG3103>`__","Errors in taking subview of ``span``\  should be ill-formed where possible","2019-11 (Belfast)","|Complete|","11","`#103878 <https://github.com/llvm/llvm-project/issues/103878>`__",""
 "`LWG3274 <https://wg21.link/LWG3274>`__","Missing feature test macro for ``<span>``\ ","2019-11 (Belfast)","|Complete|","11","`#103880 <https://github.com/llvm/llvm-project/issues/103880>`__",""
@@ -209,14 +209,14 @@
 "`LWG3248 <https://wg21.link/LWG3248>`__","``std::format``\  ``#b``\ , ``#B``\ , ``#o``\ , ``#x``\ , and ``#X``\   presentation types misformat negative numbers","2020-02 (Prague)","|Complete|","14","`#103907 <https://github.com/llvm/llvm-project/issues/103907>`__",""
 "`LWG3250 <https://wg21.link/LWG3250>`__","``std::format``\ : ``#``\  (alternate form) for NaN and inf","2020-02 (Prague)","|Complete|","14","`#103908 <https://github.com/llvm/llvm-project/issues/103908>`__",""
 "`LWG3251 <https://wg21.link/LWG3251>`__","Are ``std::format``\  alignment specifiers applied to string arguments?","2020-02 (Prague)","|Complete|","14","`#103909 <https://github.com/llvm/llvm-project/issues/103909>`__",""
-"`LWG3252 <https://wg21.link/LWG3252>`__","Parse locale's aware modifiers for commands are not consistent with POSIX spec","2020-02 (Prague)","","","`#100271 <https://github.com/llvm/llvm-project/issues/100271>`__",""
+"`LWG3252 <https://wg21.link/LWG3252>`__","Parse locale's aware modifiers for commands are not consistent with POSIX spec","2020-02 (Prague)","|Partial|","","`#100271 <https://github.com/llvm/llvm-project/issues/100271>`__","The permitted modifiers are implemented, but parsing locale-specific alternative digits for ``%OI``, ``%OU``, and ``%OW`` is not implemented."
 "`LWG3254 <https://wg21.link/LWG3254>`__","Strike ``stop_token``\ 's ``operator!=``\ ","2020-02 (Prague)","|Complete|","17","`#103910 <https://github.com/llvm/llvm-project/issues/103910>`__",""
 "`LWG3255 <https://wg21.link/LWG3255>`__","``span``\ 's ``array``\  constructor is too strict","2020-02 (Prague)","|Complete|","","`#103911 <https://github.com/llvm/llvm-project/issues/103911>`__",""
 "`LWG3260 <https://wg21.link/LWG3260>`__","``year_month*``\  arithmetic rejects durations convertible to years","2020-02 (Prague)","","","`#100274 <https://github.com/llvm/llvm-project/issues/100274>`__",""
 "`LWG3262 <https://wg21.link/LWG3262>`__","Formatting of negative durations is not specified","2020-02 (Prague)","|Complete|","16","`#103912 <https://github.com/llvm/llvm-project/issues/103912>`__",""
 "`LWG3264 <https://wg21.link/LWG3264>`__","``sized_range``\  and ``ranges::size``\  redundantly use ``disable_sized_range``\ ","2020-02 (Prague)","|Complete|","15","`#103913 <https://github.com/llvm/llvm-project/issues/103913>`__",""
-"`LWG3269 <https://wg21.link/LWG3269>`__","Parse manipulators do not specify the result of the extraction from stream","2020-02 (Prague)","","","`#100275 <https://github.com/llvm/llvm-project/issues/100275>`__",""
-"`LWG3270 <https://wg21.link/LWG3270>`__","Parsing and formatting ``%j``\  with ``duration``\ s","2020-02 (Prague)","|Partial|","","`#100418 <https://github.com/llvm/llvm-project/issues/100418>`__",""
+"`LWG3269 <https://wg21.link/LWG3269>`__","Parse manipulators do not specify the result of the extraction from stream","2020-02 (Prague)","|Complete|","24","`#100275 <https://github.com/llvm/llvm-project/issues/100275>`__",""
+"`LWG3270 <https://wg21.link/LWG3270>`__","Parsing and formatting ``%j``\  with ``duration``\ s","2020-02 (Prague)","|Complete|","24","`#100418 <https://github.com/llvm/llvm-project/issues/100418>`__",""
 "`LWG3280 <https://wg21.link/LWG3280>`__","View converting constructors can cause constraint recursion and are unneeded","2020-02 (Prague)","|Complete|","15","`#103914 <https://github.com/llvm/llvm-project/issues/103914>`__",""
 "`LWG3281 <https://wg21.link/LWG3281>`__","Conversion from ``*pair-like*``\  types to ``subrange``\  is a silent semantic promotion","2020-02 (Prague)","|Complete|","13","`#103915 <https://github.com/llvm/llvm-project/issues/103915>`__",""
 "`LWG3282 <https://wg21.link/LWG3282>`__","``subrange``\  converting constructor should disallow derived to base conversions","2020-02 (Prague)","|Complete|","15","`#103916 <https://github.com/llvm/llvm-project/issues/103916>`__",""
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index 58ea67732f808f..bc3d09ea6c378f 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -82,7 +82,7 @@
 "`LWG3530 <https://wg21.link/LWG3530>`__","``BUILTIN-PTR-MEOW`` should not opt the type out of syntactic checks","2021-06 (Virtual)","","","`#104341 <https://github.com/llvm/llvm-project/issues/104341>`__",""
 "`LWG3532 <https://wg21.link/LWG3532>`__","``split_view<V, P>::inner-iterator<true>::operator++(int)`` should depend on ``Base``","2021-06 (Virtual)","","","`#104342 <https://github.com/llvm/llvm-project/issues/104342>`__",""
 "`LWG3533 <https://wg21.link/LWG3533>`__","Make ``base() const &`` consistent across iterator wrappers that supports ``input_iterators``","2021-06 (Virtual)","|Complete|","14","`#104343 <https://github.com/llvm/llvm-project/issues/104343>`__",""
-"`LWG3536 <https://wg21.link/LWG3536>`__","Should ``chrono::from_stream()`` assign zero to duration for failure?","2021-06 (Virtual)","","","`#104344 <https://github.com/llvm/llvm-project/issues/104344>`__",""
+"`LWG3536 <https://wg21.link/LWG3536>`__","Should ``chrono::from_stream()`` assign zero to duration for failure?","2021-06 (Virtual)","|Complete|","24","`#104344 <https://github.com/llvm/llvm-project/issues/104344>`__",""
 "`LWG3539 <https://wg21.link/LWG3539>`__","``format_to`` must not copy models of ``output_iterator<const charT&>``","2021-06 (Virtual)","|Complete|","14","`#104345 <https://github.com/llvm/llvm-project/issues/104345>`__",""
 "`LWG3540 <https://wg21.link/LWG3540>`__","§[format.arg] There should be no const in ``basic_format_arg(const T* p)``","2021-06 (Virtual)","|Complete|","14","`#104348 <https://github.com/llvm/llvm-project/issues/104348>`__",""
 "`LWG3541 <https://wg21.link/LWG3541>`__","``indirectly_readable_traits`` should be SFINAE-friendly for all types","2021-06 (Virtual)","|Complete|","14","`#104349 <https://github.com/llvm/llvm-project/issues/104349>`__",""
@@ -113,7 +113,7 @@
 "`LWG3480 <https://wg21.link/LWG3480>`__","``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","2021-10 (Virtual)","|Complete|","14","`#104374 <https://github.com/llvm/llvm-project/issues/104374>`__",""
 "`LWG3498 <https://wg21.link/LWG3498>`__","Inconsistent ``noexcept``-specifiers for ``basic_syncbuf``","2021-10 (Virtual)","|Complete|","18","`#104375 <https://github.com/llvm/llvm-project/issues/104375>`__",""
 "`LWG3535 <https://wg21.link/LWG3535>`__","``join_view::iterator::iterator_category`` and ``::iterator_concept`` lie","2021-10 (Virtual)","|Complete|","15","`#104376 <https://github.com/llvm/llvm-project/issues/104376>`__",""
-"`LWG3554 <https://wg21.link/LWG3554>`__","``chrono::parse`` needs ``const charT*`` and ``basic_string_view<charT>`` overloads","2021-10 (Virtual)","","","`#104377 <https://github.com/llvm/llvm-project/issues/104377>`__",""
+"`LWG3554 <https://wg21.link/LWG3554>`__","``chrono::parse`` needs ``const charT*`` and ``basic_string_view<charT>`` overloads","2021-10 (Virtual)","|Complete|","24","`#104377 <https://github.com/llvm/llvm-project/issues/104377>`__",""
 "`LWG3557 <https://wg21.link/LWG3557>`__","The ``static_cast`` expression in ``convertible_to`` has the wrong operand","2021-10 (Virtual)","|Complete|","14","`#104378 <https://github.com/llvm/llvm-project/issues/104378>`__",""
 "`LWG3559 <https://wg21.link/LWG3559>`__","Semantic requirements of ``sized_range`` is circular","2021-10 (Virtual)","|Nothing To Do|","","`#104379 <https://github.com/llvm/llvm-project/issues/104379>`__",""
 "`LWG3560 <https://wg21.link/LWG3560>`__","``ranges::equal`` and ``ranges::is_permutation`` should short-circuit for ``sized_ranges``","2021-10 (Virtual)","","","`#104380 <https://github.com/llvm/llvm-project/issues/104380>`__",""
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 8666436cc81e9d..c362c37124fcdd 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -112,7 +112,7 @@
 "`LWG4170 <https://wg21.link/LWG4170>`__","``contiguous_iterator`` should require ``to_address(I{})``","2024-11 (Wrocław)","","","`#118368 <https://github.com/llvm/llvm-project/issues/118368>`__",""
 "","","","","","",""
 "`LWG3578 <https://wg21.link/LWG3578>`__","Iterator SCARYness in the context of associative container merging","2025-02 (Hagenberg)","","","`#127859 <https://github.com/llvm/llvm-project/issues/127859>`__",""
-"`LWG3956 <https://wg21.link/LWG3956>`__","``chrono::parse`` uses ``from_stream`` as a customization point","2025-02 (Hagenberg)","","","`#127860 <https://github.com/llvm/llvm-project/issues/127860>`__",""
+"`LWG3956 <https://wg21.link/LWG3956>`__","``chrono::parse`` uses ``from_stream`` as a customization point","2025-02 (Hagenberg)","|Complete|","24","`#127860 <https://github.com/llvm/llvm-project/issues/127860>`__",""
 "`LWG4172 <https://wg21.link/LWG4172>`__","``unique_lock`` self-move-assignment is broken","2025-02 (Hagenberg)","|Complete|","22","`#127861 <https://github.com/llvm/llvm-project/issues/127861>`__",""
 "`LWG4175 <https://wg21.link/LWG4175>`__","``get_env()`` specified in terms of ``as_const()`` but this doesn't work with rvalue senders","2025-02 (Hagenberg)","","","`#127862 <https://github.com/llvm/llvm-project/issues/127862>`__",""
 "`LWG4179 <https://wg21.link/LWG4179>`__","Wrong range in ``[alg.search]``","2025-02 (Hagenberg)","","","`#127863 <https://github.com/llvm/llvm-project/issues/127863>`__",""
@@ -267,7 +267,7 @@
 "`LWG3662 <https://wg21.link/LWG3662>`__","``basic_string::append/assign(NTBS, pos, n)`` suboptimal","2026-03 (Croydon)","|Complete|","23","`#189809 <https://github.com/llvm/llvm-project/issues/189809>`__",""
 "`LWG3777 <https://wg21.link/LWG3777>`__","Common ``cartesian_product_view`` produces an invalid range if the first range is input and one of the ranges is empty","2026-03 (Croydon)","","","`#189810 <https://github.com/llvm/llvm-project/issues/189810>`__",""
 "`LWG3797 <https://wg21.link/LWG3797>`__","``elements_view`` insufficiently constrained","2026-03 (Croydon)","","","`#189811 <https://github.com/llvm/llvm-project/issues/189811>`__",""
-"`LWG3831 <https://wg21.link/LWG3831>`__","Two-digit formatting of negative ``year`` is ambiguous","2026-03 (Croydon)","","","`#189812 <https://github.com/llvm/llvm-project/issues/189812>`__",""
+"`LWG3831 <https://wg21.link/LWG3831>`__","Two-digit formatting of negative ``year`` is ambiguous","2026-03 (Croydon)","|Complete|","24","`#189812 <https://github.com/llvm/llvm-project/issues/189812>`__",""
 "`LWG3891 <https://wg21.link/LWG3891>`__","LWG3870 breaks ``std::expected<cv T, E>``","2026-03 (Croydon)","","","`#189813 <https://github.com/llvm/llvm-project/issues/189813>`__",""
 "`LWG4026 <https://wg21.link/LWG4026>`__","Assignment operators of ``std::expected`` should propagate triviality","2026-03 (Croydon)","","","`#189814 <https://github.com/llvm/llvm-project/issues/189814>`__",""
 "`LWG4090 <https://wg21.link/LWG4090>`__","Underspecified use of locale facets for locale-dependent ``std::format``","2026-03 (Croydon)","","","`#189815 <https://github.com/llvm/llvm-project/issues/189815>`__",""
diff --git a/libcxx/include/__chrono/from_stream.h b/libcxx/include/__chrono/from_stream.h
index bb5d5af9d1696b..8e2921b1908125 100644
--- a/libcxx/include/__chrono/from_stream.h
+++ b/libcxx/include/__chrono/from_stream.h
@@ -21,6 +21,7 @@
 #  include <__chrono/file_clock.h>
 #  include <__chrono/gps_clock.h>
 #  include <__chrono/hh_mm_ss.h>
+#  include <__chrono/leap_second.h>
 #  include <__chrono/month.h>
 #  include <__chrono/monthday.h>
 #  include <__chrono/parser_data.h>
@@ -458,6 +459,9 @@ class __from_stream_parser {
   }
 
   // Parses '__fmt' into '__f', setting failbit on a mismatch.
+  // Keep the handling of all format specifiers together in a single switch.
+  // This makes the function longer and increases its cognitive complexity.
+  // NOLINTNEXTLINE(readability-function-size, readability-function-cognitive-complexity)
   _LIBCPP_HIDE_FROM_ABI void __parse(
       const _CharT* __fmt, __fields_storage& __f, basic_string<_CharT, _Traits>& __abbrev, __parse_options __options) {
     const auto& __ctype = std::use_facet<ctype<_CharT> >(__is_.getloc());
diff --git a/libcxx/include/__chrono/parser_data.h b/libcxx/include/__chrono/parser_data.h
index fda046ca3752c6..9af9839614d33e 100644
--- a/libcxx/include/__chrono/parser_data.h
+++ b/libcxx/include/__chrono/parser_data.h
@@ -26,6 +26,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 namespace chrono {
 
+namespace __parser {
+
 // Fields supplied by the parsed format directives.
 enum class __fields_set : uint32_t {
   __none    = 0,
@@ -55,22 +57,26 @@ enum class __fields_set : uint32_t {
   __iso_year_of_century = 1 << 17,
 };
 
-_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set operator|(__fields_set __lhs, __fields_set __rhs) {
+_LIBCPP_HIDE_FROM_ABI constexpr __fields_set operator|(__fields_set __lhs, __fields_set __rhs) {
   return static_cast<__fields_set>(static_cast<uint32_t>(__lhs) | static_cast<uint32_t>(__rhs));
 }
 
-_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set operator&(__fields_set __lhs, __fields_set __rhs) {
+_LIBCPP_HIDE_FROM_ABI constexpr __fields_set operator&(__fields_set __lhs, __fields_set __rhs) {
   return static_cast<__fields_set>(static_cast<uint32_t>(__lhs) & static_cast<uint32_t>(__rhs));
 }
 
-_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set operator~(__fields_set __fields) {
+_LIBCPP_HIDE_FROM_ABI constexpr __fields_set operator~(__fields_set __fields) {
   return static_cast<__fields_set>(~static_cast<uint32_t>(__fields));
 }
 
-_LIBCPP_HIDE_FROM_ABI inline constexpr __fields_set& operator|=(__fields_set& __lhs, __fields_set __rhs) {
+_LIBCPP_HIDE_FROM_ABI constexpr __fields_set& operator|=(__fields_set& __lhs, __fields_set __rhs) {
   return __lhs = __lhs | __rhs;
 }
 
+} // namespace __parser
+
+using __parser::__fields_set;
+
 // Fields collected while parsing. Date/time construction and validation do not
 // modify these values or their presence flags.
 struct __fields_storage {
diff --git a/libcxx/test/libcxx/time/from_stream.pass.cpp b/libcxx/test/libcxx/time/from_stream.pass.cpp
index 6584dce08f10fa..9d7a58046c5a09 100644
--- a/libcxx/test/libcxx/time/from_stream.pass.cpp
+++ b/libcxx/test/libcxx/time/from_stream.pass.cpp
@@ -53,7 +53,7 @@ void test_read_digits() {
     assert(result.__digits_read == c.count);
     assert(result.__overflow == c.overflow);
     assert(state == std::ios_base::goodbit); // Reporting failure is the caller's responsibility.
-    assert(stream.peek() == c.next);
+    assert(stream.peek() == std::char_traits<CharT>::to_int_type(c.next));
   }
 }
 

>From 50f2c4620aadbf19c64d26dc45ff272e48b602a2 Mon Sep 17 00:00:00 2001
From: Emmett <emmettzhang2020 at outlook.com>
Date: Fri, 2 Oct 2026 00:52:50 +0800
Subject: [PATCH 3/6] try to fix CI failure, remove recursive pattern with
 explicit sequential operation

---
 libcxx/include/__chrono/from_stream.h | 46 +++++++++++++++++++--------
 1 file changed, 33 insertions(+), 13 deletions(-)

diff --git a/libcxx/include/__chrono/from_stream.h b/libcxx/include/__chrono/from_stream.h
index 8e2921b1908125..28cf3c6d3f4e0c 100644
--- a/libcxx/include/__chrono/from_stream.h
+++ b/libcxx/include/__chrono/from_stream.h
@@ -25,7 +25,6 @@
 #  include <__chrono/month.h>
 #  include <__chrono/monthday.h>
 #  include <__chrono/parser_data.h>
-#  include <__chrono/statically_widen.h>
 #  include <__chrono/system_clock.h>
 #  include <__chrono/tai_clock.h>
 #  include <__chrono/time_point.h>
@@ -478,9 +477,10 @@ class __from_stream_parser {
       _CharT __c{};
       if (!__peek(__c) || !_Traits::eq(__c, __expected)) {
         __state_ |= ios_base::failbit;
-        return;
+        return false;
       }
       __consume();
+      return !__fail();
     };
 
     // Accept repeated fields only when their values agree.
@@ -623,15 +623,28 @@ class __from_stream_parser {
         break;
 
       case 'D':
-        __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "%m/%d/%y"), __f, __abbrev, __options);
+        __read_unsigned(2, __value);
+        if (__fail() || !__assign(__f.__month_, __value, __fields_set::__month) || !__match(_CharT('/')))
+          break;
+        __read_unsigned(2, __value);
+        if (__fail() || !__assign(__f.__day_, __value, __fields_set::__day) || !__match(_CharT('/')))
+          break;
+        __read_unsigned(2, __value);
+        if (!__fail())
+          __assign(__f.__year_of_century_, __value, __fields_set::__year_of_century);
         break;
 
       case 'F':
         // A width on %F applies only to %Y.
         __read_signed(__has_width ? __width : 4, __value);
-        if (!__fail() && __assign(__f.__year_, __value, __fields_set::__year)) {
-          __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "-%m-%d"), __f, __abbrev, __options);
-        }
+        if (__fail() || !__assign(__f.__year_, __value, __fields_set::__year) || !__match(_CharT('-')))
+          break;
+        __read_unsigned(2, __value);
+        if (__fail() || !__assign(__f.__month_, __value, __fields_set::__month) || !__match(_CharT('-')))
+          break;
+        __read_unsigned(2, __value);
+        if (!__fail())
+          __assign(__f.__day_, __value, __fields_set::__day);
         break;
 
       case 'g':
@@ -710,13 +723,20 @@ class __from_stream_parser {
         break;
       }
 
-      case 'R':
-        __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "%H:%M"), __f, __abbrev, __options);
-        break;
-
-      case 'T':
-        __parse(_LIBCPP_STATICALLY_WIDEN(_CharT, "%H:%M:%S"), __f, __abbrev, __options);
-        break;
+      case 'R': // %H:%M
+      case 'T': // %H:%M:%S
+        __read_unsigned(2, __value);
+        if (__fail() || !__assign(__f.__hours_, __value, __fields_set::__hours) || !__match(_CharT(':')))
+          break;
+        __read_unsigned(2, __value);
+        if (__fail() || !__assign(__f.__minutes_, __value, __fields_set::__minutes))
+          break;
+        if (__spec == 'R')
+          break;
+        if (!__match(_CharT(':')))
+          break;
+        // %T has no width or modifier; parse its seconds as an ordinary %S.
+        [[fallthrough]];
 
       case 'S': {
         // The target type determines whether fractions are allowed; the width only

>From 700303e15bf069204d460aec45c13de4ab172fc2 Mon Sep 17 00:00:00 2001
From: Emmett <emmettzhang2020 at outlook.com>
Date: Fri, 2 Oct 2026 10:00:58 +0800
Subject: [PATCH 4/6] rename __in_range -> __is_in_range to avoid name
 conflicting on Windows

---
 libcxx/include/__chrono/from_stream.h | 45 ++++++++++++++-------------
 1 file changed, 23 insertions(+), 22 deletions(-)

diff --git a/libcxx/include/__chrono/from_stream.h b/libcxx/include/__chrono/from_stream.h
index 28cf3c6d3f4e0c..ddd3ae3280243f 100644
--- a/libcxx/include/__chrono/from_stream.h
+++ b/libcxx/include/__chrono/from_stream.h
@@ -90,7 +90,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __parse_options __get_parse_options() {
 }
 
 // Check an inclusive range without narrowing parsed int or int64_t fields.
-_LIBCPP_HIDE_FROM_ABI constexpr bool __in_range(int64_t __value, int64_t __lo, int64_t __hi) {
+_LIBCPP_HIDE_FROM_ABI constexpr bool __is_in_range(int64_t __value, int64_t __lo, int64_t __hi) {
   return __lo <= __value && __value <= __hi;
 }
 
@@ -650,7 +650,7 @@ class __from_stream_parser {
       case 'g':
         __read_unsigned(__has_width ? __width : 2, __value);
         if (!__fail()) {
-          if (!__in_range(__value, 0, 99))
+          if (!__is_in_range(__value, 0, 99))
             __state_ |= ios_base::failbit;
           else
             __assign(__f.__iso_year_of_century_, __value, __fields_set::__iso_year_of_century);
@@ -754,7 +754,7 @@ class __from_stream_parser {
         int __weekday = 0;
         __read_unsigned(__has_width ? __width : 1, __weekday);
         if (!__fail()) {
-          if (!__in_range(__weekday, 1, 7))
+          if (!__is_in_range(__weekday, 1, 7))
             __state_ |= ios_base::failbit;
           else
             __assign(__f.__weekday_, __weekday % 7, __fields_set::__weekday);
@@ -886,7 +886,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __try_get_year(const __fields_storage& __f, in
   int64_t __year{};
 
   if (__f.__has(__fields_set::__year_of_century)) {
-    if (!__in_range(__f.__year_of_century_, 0, 99))
+    if (!__is_in_range(__f.__year_of_century_, 0, 99))
       return false;
 
     // Use an explicit century or full year before falling back to the default century.
@@ -913,7 +913,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __try_get_year(const __fields_storage& __f, in
     return false;
   }
 
-  if (!__in_range(__year, static_cast<int>((year::min)()), static_cast<int>((year::max)())))
+  if (!__is_in_range(__year, static_cast<int>((year::min)()), static_cast<int>((year::max)())))
     return false;
 
   __result = static_cast<int>(__year);
@@ -925,7 +925,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __try_get_year(const __fields_storage& __f, in
 _LIBCPP_HIDE_FROM_ABI inline bool __iso_week_to_sys_days(int64_t __g, int __v, weekday __wd, sys_days& __result) {
   const int __min_year = static_cast<int>((year::min)());
   const int __max_year = static_cast<int>((year::max)());
-  if (!__in_range(__g, __min_year - 1, __max_year + 1) || !__in_range(__v, 1, 53))
+  if (!__is_in_range(__g, __min_year - 1, __max_year + 1) || !__is_in_range(__v, 1, 53))
     return false;
 
   const days __year_length{__g % 4 == 0 && (__g % 100 != 0 || __g % 400 == 0) ? 366 : 365};
@@ -969,7 +969,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __iso_week_to_sys_days(int64_t __g, int __v, w
 // The caller must supply a valid year.
 _LIBCPP_HIDE_FROM_ABI inline bool
 __week_to_sys_days(int __year, int __week, weekday __first, weekday __wd, sys_days& __result) {
-  if (!__in_range(__week, 0, 53))
+  if (!__is_in_range(__week, 0, 53))
     return false;
 
   // Compute days from 1970-01-01 to __year/__week/__wd in four parts:
@@ -993,7 +993,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __make_date(const __fields_storage& __f, year_
   if (int __year{}; __try_get_year(__f, __year)) {
     // Calendar date: %Y %m %d, also supplied by formats such as %F, %D, or %x.
     if (__f.__has(__fields_set::__month | __fields_set::__day)) {
-      if (!__in_range(__f.__month_, 1, 12) || !__in_range(__f.__day_, 1, 31))
+      if (!__is_in_range(__f.__month_, 1, 12) || !__is_in_range(__f.__day_, 1, 31))
         return false;
 
       const year_month_day __ymd{
@@ -1006,7 +1006,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __make_date(const __fields_storage& __f, year_
 
     // Ordinal date: %Y %j.
     if (__f.__has(__fields_set::__day_of_year)) {
-      if (!__in_range(__f.__day_of_year_, 1, year{__year}.is_leap() ? 366 : 365))
+      if (!__is_in_range(__f.__day_of_year_, 1, year{__year}.is_leap() ? 366 : 365))
         return false;
 
       __result = year_month_day{sys_days{year{__year} / January / 1} + days{__f.__day_of_year_ - 1}};
@@ -1015,7 +1015,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __make_date(const __fields_storage& __f, year_
 
     // Week date: %Y with %U or %W and a weekday (%a/%A/%u/%w).
     if (__f.__has(__fields_set::__weekday) && __f.__has_any(__fields_set::__week_sun | __fields_set::__week_mon)) {
-      if (!__in_range(__f.__weekday_, 0, 6))
+      if (!__is_in_range(__f.__weekday_, 0, 6))
         return false;
       const bool __use_sunday = __f.__has(__fields_set::__week_sun);
       sys_days __date{};
@@ -1050,7 +1050,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __make_date(const __fields_storage& __f, year_
       __iso_year = __f.__iso_year_;
     }
     sys_days __date{};
-    if (!__in_range(__f.__weekday_, 0, 6) ||
+    if (!__is_in_range(__f.__weekday_, 0, 6) ||
         !__iso_week_to_sys_days(__iso_year, __f.__iso_week_, weekday{static_cast<unsigned>(__f.__weekday_)}, __date))
       return false;
 
@@ -1077,7 +1077,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __validate_date(const __fields_storage& __f, c
 
   // Without %C or %Y, %y denotes a year in [1969, 2068], not just matching last digits.
   if (__f.__has(__fields_set::__year_of_century) && !__f.__has_any(__fields_set::__century | __fields_set::__year) &&
-      !__in_range(__year, 1969, 2068))
+      !__is_in_range(__year, 1969, 2068))
     return false;
 
   // Month (%m/%b/%B/%h), day (%d/%e), and weekday (%a/%A/%u/%w).
@@ -1154,7 +1154,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __try_get_hour(const __fields_storage& __f, in
   if (__f.__has(__fields_set::__hours)) {
     // %H determines the hour; check agreement with %I and %p if supplied.
     __hour = __f.__hours_;
-    if (!__in_range(__hour, 0, 23))
+    if (!__is_in_range(__hour, 0, 23))
       return false;
     if (__f.__has(__fields_set::__hour12)) {
       const int __hour12 = static_cast<int>(chrono::make12(hours{__hour}).count());
@@ -1165,7 +1165,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __try_get_hour(const __fields_storage& __f, in
       return false;
   } else if (__f.__has(__fields_set::__hour12)) {
     // Without %H, %I requires %p to distinguish AM from PM.
-    if (!__in_range(__f.__hour12_, 1, 12) || !__f.__has(__fields_set::__am_pm))
+    if (!__is_in_range(__f.__hour12_, 1, 12) || !__f.__has(__fields_set::__am_pm))
       return false;
     __hour = static_cast<int>(chrono::make24(hours{__f.__hour12_}, __f.__is_pm_).count());
   } else {
@@ -1178,11 +1178,12 @@ _LIBCPP_HIDE_FROM_ABI inline bool __try_get_hour(const __fields_storage& __f, in
 }
 
 _LIBCPP_HIDE_FROM_ABI inline bool __validate_minute(const __fields_storage& __f) {
-  return !__f.__has(__fields_set::__minutes) || __in_range(__f.__minutes_, 0, 59);
+  return !__f.__has(__fields_set::__minutes) || __is_in_range(__f.__minutes_, 0, 59);
 }
 
 _LIBCPP_HIDE_FROM_ABI inline bool __validate_second(const __fields_storage& __f, int __max_second) {
-  return (!__f.__has(__fields_set::__seconds) || __in_range(__f.__seconds_, 0, __max_second)) && __f.__subseconds_ >= 0;
+  return (!__f.__has(__fields_set::__seconds) || __is_in_range(__f.__seconds_, 0, __max_second)) &&
+         __f.__subseconds_ >= 0;
 }
 
 // Validate the time-of-day fields and combine their whole seconds only on success.
@@ -1422,7 +1423,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, day
   if (!__f.__has_exactly(__fields_set::__day))
     return false;
 
-  if (!__in_range(__f.__day_, 1, 31))
+  if (!__is_in_range(__f.__day_, 1, 31))
     return false;
 
   __result = day{static_cast<unsigned>(__f.__day_)};
@@ -1433,7 +1434,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, mon
   if (!__f.__has_exactly(__fields_set::__month))
     return false;
 
-  if (!__in_range(__f.__month_, 1, 12))
+  if (!__is_in_range(__f.__month_, 1, 12))
     return false;
 
   __result = month{static_cast<unsigned>(__f.__month_)};
@@ -1457,7 +1458,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, wee
   if (!__f.__has_exactly(__fields_set::__weekday))
     return false;
 
-  if (!__in_range(__f.__weekday_, 0, 6))
+  if (!__is_in_range(__f.__weekday_, 0, 6))
     return false;
 
   __result = weekday{static_cast<unsigned>(__f.__weekday_)};
@@ -1472,7 +1473,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, mon
   int __day{};
   if (__f.__has(__fields_set::__day_of_year)) {
     // Without a year, only days through February 28 are unambiguous.
-    if (!__in_range(__f.__day_of_year_, 1, 59))
+    if (!__is_in_range(__f.__day_of_year_, 1, 59))
       return false;
     __month = __f.__day_of_year_ <= 31 ? 1 : 2;
     __day   = __f.__day_of_year_ <= 31 ? __f.__day_of_year_ : __f.__day_of_year_ - 31;
@@ -1486,7 +1487,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, mon
     __day   = __f.__day_;
   }
 
-  if (!__in_range(__month, 1, 12) || !__in_range(__day, 1, 31))
+  if (!__is_in_range(__month, 1, 12) || !__is_in_range(__day, 1, 31))
     return false;
 
   month_day __md{month{static_cast<unsigned>(__month)}, day{static_cast<unsigned>(__day)}};
@@ -1506,7 +1507,7 @@ _LIBCPP_HIDE_FROM_ABI inline bool __from_fields(const __fields_storage& __f, yea
   if (!__try_get_year(__f, __year))
     return false;
 
-  if (!__in_range(__f.__month_, 1, 12))
+  if (!__is_in_range(__f.__month_, 1, 12))
     return false;
 
   __result = year_month{year{__year}, month{static_cast<unsigned>(__f.__month_)}};

>From 1b38c37472f5b4a595d2f3a04400c4d5fa8107c3 Mon Sep 17 00:00:00 2001
From: Emmett <emmettzhang2020 at outlook.com>
Date: Tue, 20 Oct 2026 11:47:43 +0800
Subject: [PATCH 5/6] Refine test cases

---
 libcxx/test/libcxx/time/from_stream.pass.cpp  | 211 ++++---
 .../std/time/time.parse/from_stream.pass.cpp  | 568 ++++++++++++------
 .../test/std/time/time.parse/parse.pass.cpp   |  63 +-
 3 files changed, 576 insertions(+), 266 deletions(-)

diff --git a/libcxx/test/libcxx/time/from_stream.pass.cpp b/libcxx/test/libcxx/time/from_stream.pass.cpp
index 9d7a58046c5a09..254fa7e0d4153c 100644
--- a/libcxx/test/libcxx/time/from_stream.pass.cpp
+++ b/libcxx/test/libcxx/time/from_stream.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++20
 // UNSUPPORTED: no-localization
 
 #include <cassert>
@@ -24,6 +24,8 @@
 
 template <class CharT>
 void test_read_digits() {
+  using Traits = std::char_traits<CharT>;
+  constexpr auto max_value = std::numeric_limits<std::uint64_t>::max();
   struct TestCase {
     std::basic_string<CharT> input;
     unsigned width;
@@ -31,18 +33,37 @@ void test_read_digits() {
     std::uint64_t value;
     unsigned count;
     bool overflow;
-    CharT next;
+    typename Traits::int_type next;
+    std::ios_base::iostate state = std::ios_base::goodbit;
   };
   const TestCase cases[] = {
-      // Read ordinary digits, stopping at the width or a non-digit.
-      {STR("12345"), 2, 12, 12, 2, false, CharT('3')},
-      {STR("0012X"), 5, 12, 12, 4, false, CharT('X')},
-      // No digits are consumed when the width is zero or the input is not numeric.
+      // No digits consumed.
+      // A zero width consumes nothing.
       {STR("12"), 0, 12, 0, 0, false, CharT('1')},
+      // An initial non-digit consumes nothing.
       {STR("X"), 1, 12, 0, 0, false, CharT('X')},
-      // Stop as soon as the next digit would exceed the limit.
+      // Empty input reports EOF without consuming any digits.
+      {STR(""), 1, 12, 0, 0, false, Traits::eof(), std::ios_base::eofbit},
+
+      // Successful reads.
+      // Stop at the width, leaving '3' unread.
+      {STR("12345"), 2, 12, 12, 2, false, CharT('3')},
+      // Accept leading zeros and stop before the non-digit.
+      {STR("0012X"), 5, 12, 12, 4, false, CharT('X')},
+      // Reaching EOF before the width preserves the parsed value and reports EOF.
+      {STR("12"), 3, 12, 12, 2, false, Traits::eof(), std::ios_base::eofbit},
+
+      // Overflow.
+      // After reaching the limit, consume '3' and report overflow; retain 12.
       {STR("12345"), 5, 12, 12, 3, true, CharT('4')},
+      // Exceed the limit without reaching it first; consume '3' and retain 1.
       {STR("13X"), 3, 12, 1, 2, true, CharT('X')},
+
+      // uint64_t boundaries.
+      // Accept the largest uint64_t value without overflow.
+      {STR("18446744073709551615X"), 21, max_value, max_value, 20, false, CharT('X')},
+      // One above the largest uint64_t value overflows; retain the prefix before the final digit.
+      {STR("18446744073709551616X"), 21, max_value, max_value / 10, 20, true, CharT('X')},
   };
   for (const auto& c : cases) {
     std::basic_istringstream<CharT> stream(c.input);
@@ -52,112 +73,150 @@ void test_read_digits() {
     assert(result.__value == c.value);
     assert(result.__digits_read == c.count);
     assert(result.__overflow == c.overflow);
-    assert(state == std::ios_base::goodbit); // Reporting failure is the caller's responsibility.
-    assert(stream.peek() == std::char_traits<CharT>::to_int_type(c.next));
+    assert(state == c.state);
+    assert(stream.peek() == c.next);
   }
 }
 
+template <class CharT>
 void test_read_signed() {
+  using Traits = std::char_traits<CharT>;
+  constexpr int sentinel = 42;
+  constexpr int min_value = std::numeric_limits<int>::min();
+  constexpr int max_value = std::numeric_limits<int>::max();
+  const auto make_input = [](std::int64_t value) {
+    const auto input = std::to_string(value);
+    return std::basic_string<CharT>(input.begin(), input.end());
+  };
   struct TestCase {
-    std::string input;
+    std::basic_string<CharT> input;
     int expected;
+    bool expected_fail = false;
   };
   const TestCase cases[] = {
-      // Ordinary values, with and without an explicit sign.
-      {"123", 123},
-      {"+123", 123},
-      {"-123", -123},
+      // Ordinary values.
+      // Accept digits without a sign.
+      {STR("123"), 123},
+      // Accept an explicit positive sign.
+      {STR("+123"), 123},
+      // Apply a negative sign.
+      {STR("-123"), -123},
+
+      // Integer boundaries.
+      // Accept the largest positive int.
+      {make_input(max_value), max_value},
       // The negative limit has no positive counterpart in int.
-      {std::to_string(std::numeric_limits<int>::min()), std::numeric_limits<int>::min()},
+      {make_input(min_value), min_value},
+      // Reject a value above INT_MAX and preserve the output.
+      {make_input(static_cast<std::int64_t>(max_value) + 1), sentinel, true},
+      // Reject a value below INT_MIN and preserve the output.
+      {make_input(static_cast<std::int64_t>(min_value) - 1), sentinel, true},
+
+      // Missing digits preserve the output.
+      // A negative sign alone is not an integer.
+      {STR("-"), sentinel, true},
   };
   for (const auto& c : cases) {
-    std::istringstream stream{c.input};
-    int result                   = -1;
+    std::basic_istringstream<CharT> stream{c.input};
+    int result = sentinel;
     std::ios_base::iostate state = std::ios_base::goodbit;
-    std::chrono::__from_stream_parser<char, std::char_traits<char>> parser{stream, state};
-    parser.__read_signed(static_cast<unsigned>(c.input.size()), result);
-    assert(!(state & (std::ios_base::failbit | std::ios_base::badbit)));
+    std::chrono::__from_stream_parser<CharT, Traits> parser{stream, state};
+    parser.__read_signed(std::numeric_limits<unsigned>::max(), result);
+    assert(bool(state & std::ios_base::failbit) == c.expected_fail);
+    assert(!(state & std::ios_base::badbit));
     assert(result == c.expected);
+    assert(stream.peek() == Traits::eof());
   }
 }
 
-void test_field_queries() {
-  using Fields         = std::chrono::__fields_storage;
-  using Parts          = std::chrono::__fields_set;
-  constexpr auto check = [] {
-    Fields fields;
-    assert(!fields.__has(Parts::__day));
-    assert(!fields.__has_any(Parts::__day | Parts::__month));
-    fields.__set(Parts::__utc_offset);
-    assert(fields.__has(Parts::__utc_offset));
-    assert(!fields.__has_exactly(Parts::__day));
-    fields.__set(Parts::__day);
-    // __has_only and __has_exactly ignore the UTC offset field.
-    assert(fields.__has_only(Parts::__day));
-    assert(fields.__has_exactly(Parts::__day));
-    assert(fields.__has(Parts::__day | Parts::__utc_offset));
-    assert(fields.__has_any(Parts::__day | Parts::__month));
-    assert(!fields.__has(Parts::__day | Parts::__month));
-    assert(fields.__has_only(Parts::__day | Parts::__month));
-    assert(fields.__has_exactly(Parts::__day, Parts::__month));
-    fields.__set(Parts::__month);
-    assert(!fields.__has_only(Parts::__day));
-    assert(!fields.__has_exactly(Parts::__day));
-    assert(fields.__has_exactly(Parts::__day, Parts::__month));
-    assert(fields.__has_exactly(Parts::__day | Parts::__month));
-    return true;
-  };
-  static_assert(check());
-  assert(check());
+template <class CharT>
+void test_width_overflow() {
+  std::basic_ostringstream<CharT> format;
+  format.imbue(std::locale::classic());
+  // Append a zero to UINT_MAX to make the format width overflow unsigned.
+  format << CharT('%') << std::numeric_limits<unsigned>::max() << STR("0S");
+
+  // libc++ stores the width in unsigned and rejects overflow before reading input.
+  std::basic_istringstream<CharT> stream{STR("1.25!")};
+  std::chrono::milliseconds result{};
+  std::chrono::from_stream(stream, format.str().c_str(), result);
+  assert(stream.fail());
+  // Clear the failure state and verify that no input was consumed.
+  stream.clear();
+  assert(stream.peek() == CharT('1'));
 }
 
 template <class CharT, class T>
-void check_repeated_field(const std::basic_string<CharT>& format,
-                          const std::basic_string<CharT>& matching,
-                          const std::basic_string<CharT>& conflicting,
-                          T expected) {
-  {
-    std::basic_istringstream<CharT> stream(matching);
-    stream.imbue(std::locale::classic());
-    T result{};
-    std::chrono::from_stream(stream, format.c_str(), result);
-    assert(!stream.fail());
-    assert(result == expected);
-  }
-  {
-    std::basic_istringstream<CharT> stream(conflicting);
-    stream.imbue(std::locale::classic());
-    T result{};
-    std::chrono::from_stream(stream, format.c_str(), result);
-    assert(stream.fail());
-  }
+void check(const std::basic_string<CharT>& input, const std::basic_string<CharT>& format, T expected) {
+  std::basic_istringstream<CharT> stream(input);
+  stream.imbue(std::locale::classic());
+  T result{};
+  std::chrono::from_stream(stream, format.c_str(), result);
+  assert(!stream.fail());
+  assert(result == expected);
+}
+
+template <class T, class CharT>
+void check_failure(const std::basic_string<CharT>& input, const std::basic_string<CharT>& format) {
+  std::basic_istringstream<CharT> stream(input);
+  stream.imbue(std::locale::classic());
+  T result{};
+  std::chrono::from_stream(stream, format.c_str(), result);
+  assert(stream.fail());
+}
+
+template <class CharT>
+void test_whitespace() {
+  // libc++ does not implicitly skip whitespace before %e.
+  check_failure<std::chrono::year_month_day>(STR("2026-07- 7"), STR("%Y-%m-%e"));
 }
 
 template <class CharT>
 void test_repeated_fields() {
   using namespace std::chrono;
   // libc++ accepts equal repetitions and rejects conflicting values.
-  check_repeated_field(STR("%d %d"), STR("01 01"), STR("01 02"), day{1});
+  check(STR("01 01"), STR("%d %d"), day{1});
+  check_failure<day>(STR("01 02"), STR("%d %d"));
 
   // Compound formats and locale formats share the same parsed fields.
-  check_repeated_field(STR("%F %x"), STR("2026-07-20 07/20/26"), STR("2026-07-20 07/21/26"), 2026y / July / 20);
+  check(STR("2026-07-20 07/20/26"), STR("%F %x"), 2026y / July / 20);
+  check_failure<year_month_day>(STR("2026-07-20 07/21/26"), STR("%F %x"));
+
+  // Reject conflicting calendar, ordinal, and ISO week date information.
+  check_failure<year_month_day>(STR("2026-02-15 Mon"), STR("%F %a"));
+  check_failure<year_month_day>(STR("2026 032 03"), STR("%Y %j %m"));
+  check_failure<year_month_day>(STR("2020-W53-5 2020"), STR("%G-W%V-%u %Y"));
+
+  // Different representations of the year or hour must agree.
+  check_failure<year>(STR("2026 25"), STR("%Y %y"));
+  check_failure<minutes>(STR("14 01"), STR("%H %I"));
+
+  // Repeated seconds must agree, including their fractional parts.
+  check(STR("1.25 1.25"), STR("%S %S"), 1250ms);
+  check_failure<milliseconds>(STR("1.25 1.5"), STR("%S %S"));
 
-  // Compare fractional values, not their spelling; locale seconds have no fraction.
-  check_repeated_field(STR("%S %S"), STR("1.25 1.250"), STR("1.25 1.5"), 1250ms);
-  check_repeated_field(STR("%S %X"), STR("1.0 00:00:01"), STR("1.5 00:00:01"), 1000ms);
+  // Locale seconds have no fraction.
+  check(STR("1.0 00:00:01"), STR("%S %X"), 1000ms);
+  check_failure<milliseconds>(STR("1.5 00:00:01"), STR("%S %X"));
 
   // Zone fields are checked even without output pointers.
-  check_repeated_field(STR("%d %z %Ez"), STR("01 +0100 +1:00"), STR("01 +0100 +2:00"), day{1});
-  check_repeated_field(STR("%d %Z %Z"), STR("01 UTC UTC"), STR("01 UTC GMT"), day{1});
+  check(STR("01 +0100 +1:00"), STR("%d %z %Ez"), day{1});
+  check_failure<day>(STR("01 +0100 +2:00"), STR("%d %z %Ez"));
+  check(STR("01 UTC UTC"), STR("%d %Z %Z"), day{1});
+  check_failure<day>(STR("01 UTC GMT"), STR("%d %Z %Z"));
 }
 
 int main(int, char**) {
-  test_read_signed();
-  test_field_queries();
   test_read_digits<char>();
+  test_read_signed<char>();
+  test_width_overflow<char>();
+  test_whitespace<char>();
   test_repeated_fields<char>();
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
   test_read_digits<wchar_t>();
+  test_read_signed<wchar_t>();
+  test_width_overflow<wchar_t>();
+  test_whitespace<wchar_t>();
   test_repeated_fields<wchar_t>();
 #endif
   return 0;
diff --git a/libcxx/test/std/time/time.parse/from_stream.pass.cpp b/libcxx/test/std/time/time.parse/from_stream.pass.cpp
index fa722f7093c7e5..676a37ee55cfb6 100644
--- a/libcxx/test/std/time/time.parse/from_stream.pass.cpp
+++ b/libcxx/test/std/time/time.parse/from_stream.pass.cpp
@@ -6,17 +6,101 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++20
 // UNSUPPORTED: no-localization
 // XFAIL: availability-tzdb-missing && !libcpp-has-no-experimental-tzdb && !no-tzdb && !no-filesystem
 
 // <chrono>
-// from_stream overloads for calendar types, durations, and time points.
+//
+// Tested from_stream overloads (C++20):
+//
+// template<class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 duration<Rep, Period>& d, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Duration, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 sys_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Duration, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 utc_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Duration, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 tai_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Duration, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 gps_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Duration, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 file_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Duration, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 local_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 day& d, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 month& m, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 year& y, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 weekday& wd, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 month_day& md, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 year_month& ym, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
+//
+// template<class charT, class traits, class Alloc = allocator<charT>>
+//   basic_istream<charT, traits>&
+//     from_stream(basic_istream<charT, traits>& is, const charT* fmt,
+//                 year_month_day& ymd, basic_string<charT, traits, Alloc>* abbrev = nullptr,
+//                 minutes* offset = nullptr);
 
 #include <cassert>
 #include <chrono>
 #include <initializer_list>
-#include <limits>
 #include <locale>
 #include <ratio>
 #include <sstream>
@@ -25,6 +109,8 @@
 #include "make_string.h"
 #include "test_macros.h"
 
+using namespace std::chrono;
+
 #define STR(S) MAKE_STRING(CharT, S)
 
 template <class CharT, class T>
@@ -38,201 +124,236 @@ void check(const std::basic_string<CharT>& input, const std::basic_string<CharT>
 }
 
 template <class T, class CharT>
-void check_failure(const std::basic_string<CharT>& input, const std::basic_string<CharT>& format) {
+void check_failure(const std::basic_string<CharT>& input, const std::basic_string<CharT>& format, T initial = T{}) {
   std::basic_istringstream<CharT> stream(input);
   stream.imbue(std::locale::classic());
-  T result{};
+  T result = initial;
   std::chrono::from_stream(stream, format.c_str(), result);
   assert(stream.fail());
+  assert(result == initial);
 }
 
+// Test parsing day, month, year, weekday, month_day, year_month, and year_month_day.
+// Cover numeric and named calendar fields, invalid values, missing fields,
+// and fields that the target type cannot represent.
 template <class CharT>
 void test_calendar_types() {
-  using namespace std::chrono;
+  // Parse a numeric day of the month.
   check(STR("15"), STR("%d"), day{15});
-  check(STR(" 15"), STR("%n%e"), day{15});
-  // Zone fields are consumed even when their output pointers are null.
-  check(STR("15 UTC +0130"), STR("%d %Z %z"), day{15});
+  // Parse the day with %e, which is equivalent to %d.
+  check(STR("15"), STR("%e"), day{15});
+  // A day cannot represent a month field.
   check_failure<day>(STR("02-15"), STR("%m-%d"));
+  // A day cannot represent an hour field, even when its value is zero.
   check_failure<day>(STR("15 00"), STR("%d %H"));
-  check_failure<day>(STR("32"), STR("%d"));
+  // Day 0 is below the valid range.
+  check_failure<day>(STR("0"), STR("%d"));
+  // Day 32 is outside the valid range; preserve the original day on failure.
+  check_failure<day>(STR("32"), STR("%d"), day{7});
 
+  // Parse a numeric month.
   check(STR("02"), STR("%m"), February);
+  // Parse an abbreviated month name in the classic locale.
   check(STR("Feb"), STR("%b"), February);
+  // Parse a full month name.
+  check(STR("July"), STR("%B"), July);
+  // %B also accepts an abbreviated month name, ignoring case.
+  check(STR("jUl"), STR("%B"), July);
+  // %h is equivalent to %b.
+  check(STR("Jul"), STR("%h"), July);
+  // Month 13 is outside the valid range.
   check_failure<month>(STR("13"), STR("%m"));
 
+  // Parse a calendar year.
   check(STR("2026"), STR("%Y"), 2026y);
 
+  // Parse an abbreviated weekday name in the classic locale.
   check(STR("Mon"), STR("%a"), Monday);
+  // %a also accepts a full weekday name, ignoring case.
+  check(STR("mOnDaY"), STR("%a"), Monday);
+  // Parse a full weekday name.
+  check(STR("Monday"), STR("%A"), Monday);
+  // ISO weekday numbering assigns 1 to Monday.
   check(STR("1"), STR("%u"), Monday);
+  // Unlike %u, %w only accepts weekday numbers from 0 to 6.
   check_failure<weekday>(STR("7"), STR("%w"));
 
+  // Parse a month and day without a year.
   check(STR("02-15"), STR("%m-%d"), February / 15);
+  // February 29 is valid for month_day because no year is specified.
   check(STR("02-29"), STR("%m-%d"), February / 29);
-  check(STR("32"), STR("%j"), February / 1);
-  check_failure<month_day>(STR("60"), STR("%j"));
+  // February 30 is invalid in every year.
   check_failure<month_day>(STR("02-30"), STR("%m-%d"));
+  // A month alone does not supply the required day.
   check_failure<month_day>(STR("02"), STR("%m"));
 
+  // Parse a year and month without a day.
   check(STR("2026-02"), STR("%Y-%m"), 2026y / February);
+  // Reject an invalid month in a year_month result.
   check_failure<year_month>(STR("2026-13"), STR("%Y-%m"));
 
-  const year_month_day date = 2026y / February / 15;
-  check(STR("2026-02-15"), STR("%F"), date);
-  check(STR("2026 046"), STR("%Y %j"), date);
-  check(STR("2026-W07-7"), STR("%G-W%V-%u"), date);
-  check(STR("68 69-W01-1"), STR("%y %g-W%V-%u"), 2068y / December / 31);
-  check(STR("-32768-W53-6"), STR("%6G-W%V-%u"), (year::min)() / January / 1);
-  check(STR("2026 07 0"), STR("%Y %U %w"), date);
-  check(STR("2026 06 7"), STR("%Y %W %u"), date);
-  check(STR("2026-02-15 Sun"), STR("%F %a"), date);
-  check_failure<year_month_day>(STR("2026-02-15 Mon"), STR("%F %a"));
+  // Parse a complete calendar date with %F.
+  check(STR("2026-02-15"), STR("%F"), 2026y / February / 15);
+  // %e accepts a single-digit day without padding.
+  check(STR("2026-07-7"), STR("%Y-%m-%e"), 2026y / July / 7);
+  // Reject an invalid day in a complete calendar date.
   check_failure<year_month_day>(STR("2026-02-30"), STR("%F"));
+  // February 29 is valid in a leap year.
+  check(STR("2024-02-29"), STR("%F"), 2024y / February / 29);
+  // February 29 is invalid in a non-leap year.
+  check_failure<year_month_day>(STR("2023-02-29"), STR("%F"));
+  // A year and month do not supply the required day.
   check_failure<year_month_day>(STR("2026-02"), STR("%Y-%m"));
-  check_failure<year_month_day>(STR("2021-W53-5"), STR("%G-W%V-%u"));
 }
 
+// Test compound date/time directives against their component fields.
 template <class CharT>
-void test_format() {
-  using namespace std::chrono;
-  const sys_seconds date      = sys_days{2026y / July / 20};
+void test_compound_specifiers() {
+  const sys_days date         = sys_days{2026y / July / 20};
   const sys_seconds date_time = date + 13h + 45min + 30s;
 
-  // Individual and compound directives.
+  // Parse the explicit fields represented by %F and %T.
   check(STR("2026-07-20 13:45:30"), STR("%Y-%m-%d %H:%M:%S"), date_time);
-  check(STR("2026-07-7"), STR("%Y-%m-%e"), sys_seconds{sys_days{2026y / July / 7}});
+  // %F and %T combine the date and time fields.
   check(STR("2026-07-20 13:45:30"), STR("%F %T"), date_time);
-  check(STR("2026-07-20 13:45"), STR("%F %R"), date + 13h + 45min);
-  check(STR("07/20/26"), STR("%D"), date);
-  check(STR("30"), STR("%S"), 30s);
+  // %R supplies hours and minutes.
+  check(STR("2026-07-20 13:45"), STR("%F %R"), sys_time<minutes>{date} + 13h + 45min);
+  // %T combines hours, minutes, and seconds into a duration.
+  check(STR("01:30:00"), STR("%T"), 5400s);
+  // %D combines the month, day, and two-digit year.
+  check(STR("07/20/26"), STR("%D"), year_month_day{date});
+}
 
-  // Named fields and locale-specific date/time formats in the classic locale.
-  check(STR("Monday"), STR("%A"), Monday);
-  check(STR("July"), STR("%B"), July);
-  check(STR("Jul"), STR("%h"), July);
+// Test the classic locale's date, time, and date-and-time representations.
+template <class CharT>
+void test_locale_formats() {
+  const year_month_day date   = 2026y / July / 20;
+  const sys_seconds date_time = sys_days{date} + 13h + 45min + 30s;
+
+  // Locale-specific date/time formats in the classic locale.
   check(STR("Mon Jul 20 13:45:30 2026"), STR("%c"), date_time);
-  check_failure<sys_seconds>(STR("Tue Jul 20 13:45:30 2026"), STR("%c"));
+  // %x parses the classic locale's month/day/two-digit-year representation.
   check(STR("07/20/26"), STR("%x"), date);
+  // %X parses the classic locale's hours, minutes, and seconds.
+  check(STR("01:30:00"), STR("%X"), 5400s);
+  // Parse the classic locale's twelve-hour time with an AM designator.
+  check(STR("01:30:00 AM"), STR("%r"), 5400s);
+}
 
-  // A width on %F applies only to %Y.
-  check(STR("002026-07-20"), STR("%6F"), date);
-  check(STR("26-W30-1"), STR("%g-W%V-%u"), date);
+// Test literal matching and whitespace consumption in the input.
+template <class CharT>
+void test_literals_and_whitespace() {
+  const year_month_day date = 2026y / July / 20;
 
-  // Literals and whitespace, including a match of zero whitespace characters.
+  // %% matches a literal percent sign.
   check(STR("2026-07-20%"), STR("%F%%"), date);
+  // %t matches a tab between numeric fields.
   check(STR("2026\t07\t20"), STR("%Y%t%m%t%d"), date);
+  // %t can match no whitespace before a literal.
+  check(STR("X15"), STR("%tX%d"), day{15});
+  // A format space matches multiple input spaces.
   check(STR("   2026-07-20"), STR(" %F"), date);
+  // A format space can also match no whitespace.
   check(STR("2026-07-20"), STR(" %Y-%m-%d"), date);
+  // %n consumes one whitespace character before the day.
+  check(STR(" 15"), STR("%n%e"), day{15});
+  // %n fails when no whitespace precedes the literal.
+  check_failure<day>(STR("X15"), STR("%nX%d"));
 
-  check_failure<sys_seconds>(STR("2026/07/20"), STR("%Y-%m-%d"));
-  check_failure<sys_seconds>(STR("13:45:30"), STR("%H:%M:%S"));
-  check_failure<sys_seconds>(STR("2026-07-xx"), STR("%Y-%m-%d"));
-  check_failure<sys_seconds>(STR("2026-07- 7"), STR("%Y-%m-%e"));
-}
-
-template <class CharT>
-void test_width_overflow() {
-  using namespace std::chrono;
-  std::basic_ostringstream<CharT> format;
-  format << CharT('%') << std::numeric_limits<unsigned>::max() << STR("0S");
-
-  // Reject an overflowing format width before reading the input.
-  std::basic_istringstream<CharT> stream{STR("1.25!")};
-  milliseconds result{};
-  from_stream(stream, format.str().c_str(), result);
-  assert(stream.fail());
-  stream.clear();
-  assert(stream.peek() == CharT('1'));
+  // Literal separators must match.
+  check_failure<year_month_day>(STR("2026/07/20"), STR("%Y-%m-%d"));
 }
 
+// Test day-of-year and week-based dates, year boundaries, and matching date fields.
 template <class CharT>
-void test_date_consistency() {
-  using namespace std::chrono;
+void test_date_resolution() {
+  const year_month_day date = 2026y / February / 15;
   const year_month_day feb1 = 2026y / February / 1;
   const year_month_day jan1 = 2021y / January / 1;
 
-  // An ordinal date must agree with the supplied month.
+  // Day-of-year 32 is February 1 in both leap and non-leap years.
+  check(STR("32"), STR("%j"), February / 1);
+  // Day-of-year 60 needs a year to distinguish February 29 from March 1.
+  check_failure<month_day>(STR("60"), STR("%j"));
+  // Convert a year and day-of-year to a calendar date.
+  check(STR("2026 046"), STR("%Y %j"), date);
+  // Parse an ordinal date with a matching month.
   check(STR("2026 032 02"), STR("%Y %j %m"), feb1);
-  check_failure<year_month_day>(STR("2026 032 03"), STR("%Y %j %m"));
 
-  // An ISO week date must agree with the calendar year, even across a year boundary.
+  // Convert an ISO week year, week number, and weekday to a calendar date.
+  check(STR("2026-W07-7"), STR("%G-W%V-%u"), date);
+  // A calendar year supplies context for a two-digit ISO week year.
+  check(STR("2026 26-W30-1"), STR("%Y %g-W%V-%u"), 2026y / July / 20);
+  // Calendar year 2068 ends in ISO week year 2069, despite %y's century cutoff at 69.
+  check(STR("68 69-W01-1"), STR("%y %g-W%V-%u"), 2068y / December / 31);
+  // The earliest supported calendar year begins in the preceding ISO week year.
+  check(STR("-32768-W53-6"), STR("%6G-W%V-%u"), (year::min)() / January / 1);
+  // ISO week years and calendar years can differ across a year boundary.
   check(STR("2020-W53-5 2021"), STR("%G-W%V-%u %Y"), jan1);
-  check_failure<year_month_day>(STR("2020-W53-5 2020"), STR("%G-W%V-%u %Y"));
+  // Match a full ISO week year with its last two digits.
   check(STR("1926-W01-1 26"), STR("%G-W%V-%u %g"), 1926y / January / 4);
+  // ISO week year 2021 has no week 53.
+  check_failure<year_month_day>(STR("2021-W53-5"), STR("%G-W%V-%u"));
+
+  // Parse a Sunday-based week number with Sunday numbered 0.
+  check(STR("2026 07 0"), STR("%Y %U %w"), date);
+  // Parse a Monday-based week number with ISO Sunday numbered 7.
+  check(STR("2026 06 7"), STR("%Y %W %u"), date);
+  // Accept a date accompanied by its matching weekday.
+  check(STR("2026-02-15 Sun"), STR("%F %a"), date);
 }
 
+// Test E-modified fields in the classic locale, including UTC offsets.
 template <class CharT>
 void test_modifier_E() {
-  using namespace std::chrono;
-  const sys_seconds date = sys_days{2026y / July / 20};
+  const year_month_day date   = 2026y / July / 20;
+  const sys_seconds date_time = sys_days{date} + 13h + 45min + 30s;
 
-  check(STR("Mon Jul 20 13:45:30 2026"), STR("%Ec"), date + 13h + 45min + 30s);
+  // %Ec parses the same date-and-time representation as %c in the classic locale.
+  check(STR("Mon Jul 20 13:45:30 2026"), STR("%Ec"), date_time);
+  // %Ex parses the same date representation as %x in the classic locale.
   check(STR("07/20/26"), STR("%Ex"), date);
+  // %EX parses the same time representation as %X in the classic locale.
+  check(STR("01:30:00"), STR("%EX"), 5400s);
 
   // Numeric years in the classic locale.
-  for (const auto& format : {STR("%EC %Ey-%m-%d"), STR("%EC %EY-%m-%d")}) {
-    std::basic_istringstream<CharT> stream(format == STR("%EC %Ey-%m-%d") ? STR("20 26-07-20") : STR("20 2026-07-20"));
-    stream.imbue(std::locale::classic());
-    sys_seconds result{};
-    from_stream(stream, format.c_str(), result);
-    assert(!stream.fail());
-    assert(result == date);
-  }
+  check(STR("20 26-07-20"), STR("%EC %Ey-%m-%d"), date);
+  // Match a century with a full year using E-modified fields.
+  check(STR("20 2026-07-20"), STR("%EC %EY-%m-%d"), date);
 
   // Parse a century and a UTC offset.
-  {
-    std::basic_istringstream<CharT> stream(STR("20 26-07-20 +4:30"));
-    stream.imbue(std::locale::classic());
-    sys_seconds result{};
-    from_stream(stream, STR("%EC %y-%m-%d %Ez").c_str(), result);
-    assert(!stream.fail());
-    assert(result == date - 4h - 30min);
-  }
+  check(STR("20 26-07-20 13:45:30 +4:30"), STR("%EC %y-%m-%d %T %Ez"), date_time - 4h - 30min);
 }
 
+// Test O-modified numeric fields in the classic locale.
 template <class CharT>
 void test_modifier_O() {
-  using namespace std::chrono;
-  const sys_seconds date = sys_days{2026y / July / 20};
+  const sys_days date = sys_days{2026y / July / 20};
 
-  check(STR("2026-07-20"), STR("%Y-%m-%Oe"), date);
+  // %Oe accepts ordinary decimal day digits in the classic locale.
+  check(STR("2026-07-20"), STR("%Y-%m-%Oe"), year_month_day{date});
 
-  // Parse numeric fields, including twelve o'clock with PM.
+  // Parse numeric fields and leave the trailing character unread.
   {
     std::basic_istringstream<CharT> stream(STR("26-07-20 13:45 1!"));
     stream.imbue(std::locale::classic());
-    sys_seconds result{};
+    sys_time<minutes> result{};
     from_stream(stream, STR("%Oy-%Om-%Od %OH:%OM %Ow").c_str(), result);
     assert(!stream.fail());
     assert(result == date + 13h + 45min);
     assert(stream.peek() == CharT('!'));
   }
-  {
-    std::basic_istringstream<CharT> stream(STR("2026-07-20 12 PM"));
-    stream.imbue(std::locale::classic());
-    sys_seconds result{};
-    from_stream(stream, STR("%F %OI %p").c_str(), result);
-    assert(!stream.fail());
-    assert(result == date + 12h);
-  }
+  // Twelve o'clock with PM denotes noon.
+  check(STR("2026-07-20 12 PM"), STR("%F %OI %p"), sys_time<hours>{date} + 12h);
 
-  // %OS, %OU and %OW parse numerically; %Oz uses the offset parser.
-  {
-    std::basic_istringstream<CharT> stream(STR("2026-07-20 13:45:30.125 +4:30"));
-    stream.imbue(std::locale::classic());
-    sys_time<milliseconds> result{};
-    from_stream(stream, STR("%F %H:%M:%OS %Oz").c_str(), result);
-    assert(!stream.fail());
-    assert(result == date + 13h + 45min + 30s + 125ms - 4h - 30min);
-  }
-  for (const auto& format : {STR("%Y %OU %w"), STR("%Y %OW %w")}) {
-    std::basic_istringstream<CharT> stream(STR("2026 29 1"));
-    stream.imbue(std::locale::classic());
-    sys_seconds result{};
-    from_stream(stream, format.c_str(), result);
-    assert(!stream.fail());
-    assert(result == date);
-  }
+  // Parse fractional seconds with a colon-separated UTC offset.
+  check(STR("2026-07-20 13:45:30.125 +4:30"),
+        STR("%F %H:%M:%OS %Oz"),
+        date + 13h + 45min + 30s + 125ms - 4h - 30min);
+
+  // This date has week number 29 with either Sunday or Monday as the first day.
+  for (const auto& format : {STR("%Y %OU %w"), STR("%Y %OW %w")})
+    check(STR("2026 29 1"), format, year_month_day{date});
 }
 
 template <class CharT>
@@ -240,28 +361,29 @@ struct comma_numpunct : std::numpunct<CharT> {
   CharT do_decimal_point() const override { return CharT(','); }
 };
 
+// Test fractional-second syntax, decimal punctuation, and target precision.
 template <class CharT>
 void test_fractional_seconds() {
-  using namespace std::chrono;
+  // Convert fractional seconds to an integral millisecond count.
   check(STR("1.25"), STR("%S"), 1250ms);
+  // Accept a fraction without digits before the decimal point.
   check(STR(".5"), STR("%S"), 500ms);
+  // Accept a decimal point without following fractional digits.
   check(STR("1."), STR("%S"), 1000ms);
-  check(STR(".5!"), STR("%2S!"), 500ms);
   // Floating-point representations allow fractions even with a whole-second period.
   check(STR("12.125s"), STR("%Ss"), duration<double>{12.125});
-  // An explicit width controls consumption independently of the target precision.
-  check(STR("1.2345!"), STR("%6S!"), 1234ms);
 
-  // An integer seconds target leaves the decimal point unread, regardless of width.
-  for (const auto& format : {STR("%S"), STR("%6S")}) {
+  // With the default width, an integer seconds target leaves the decimal point unread.
+  {
     std::basic_istringstream<CharT> stream(STR("1.25"));
     stream.imbue(std::locale::classic());
     duration<int> result{};
-    from_stream(stream, format.c_str(), result);
+    from_stream(stream, STR("%S").c_str(), result);
     assert(!stream.fail());
     assert(result == 1s);
     assert(stream.peek() == CharT('.'));
   }
+  // Use the locale's comma decimal point and leave the trailing character unread.
   {
     std::basic_istringstream<CharT> stream(STR("1,25!"));
     stream.imbue(std::locale(std::locale::classic(), new comma_numpunct<CharT>));
@@ -271,6 +393,31 @@ void test_fractional_seconds() {
     assert(result == 1250ms);
     assert(stream.peek() == CharT('!'));
   }
+}
+
+// Test field widths, including signs, decimal points, and unread input.
+template <class CharT>
+void test_field_widths() {
+  // A width on %F applies only to %Y.
+  check(STR("002026-07-20"), STR("%6F"), 2026y / July / 20);
+
+  // A sign consumes one character of the field's width.
+  for (bool negative : {false, true}) {
+    std::basic_istringstream<CharT> stream(negative ? STR("-123") : STR("+123"));
+    stream.imbue(std::locale::classic());
+    year result{};
+    from_stream(stream, STR("%3Y").c_str(), result);
+    assert(!stream.fail());
+    assert(result == year{negative ? -12 : 12});
+    assert(stream.peek() == CharT('3'));
+  }
+
+  // A width consumed entirely by the sign leaves no year digits.
+  check_failure<year>(STR("+1"), STR("%1Y"));
+
+  // Consume six characters and match the trailing literal without losing precision.
+  check(STR("1.2345!"), STR("%6S!"), 1234500us);
+
   {
     // The width includes the decimal point and limits the fractional digits.
     std::basic_istringstream<CharT> stream(STR("1.234"));
@@ -283,20 +430,49 @@ void test_fractional_seconds() {
   }
 }
 
-template <class CharT>
+// Test system, local, and file clock targets and their required date/time fields.
+template <class CharT, class FileClock = file_clock>
 void test_time_points() {
-  using namespace std::chrono;
   const sys_seconds expected = sys_days{2026y / July / 20} + 13h + 45min + 30s;
   auto test = [&](auto value) { check(STR("20 26-07-20 01:45:30 PM"), STR("%C %y-%m-%d %I:%M:%S %p"), value); };
+  // Combine century, year, and twelve-hour time into a system-clock time point.
   test(expected);
+  // Parse the same calendar and time fields into a local time point.
   test(local_seconds{expected.time_since_epoch()});
-  test(file_clock::from_sys(expected));
+  // Convert the parsed date and time to the file clock's epoch.
+  if constexpr (requires { FileClock::from_sys(expected); }) {
+    test(FileClock::from_sys(expected));
+  }
+#if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&                             \
+    !defined(TEST_HAS_NO_FILESYSTEM)
+  else {
+    // Implementations may provide UTC conversions instead of system-clock conversions.
+    test(FileClock::from_utc(utc_clock::from_sys(expected)));
+  }
+
+  // The GPS epoch is 1980-01-06 00:00:00.
+  check(STR("1980-01-06 00:00:00"), STR("%F %T"), gps_seconds{0s});
+#endif
 
+  // A time of day alone cannot determine a time point.
+  check_failure<sys_seconds>(STR("13:45:30"), STR("%H:%M:%S"));
+  // Reject a nonnumeric day and preserve the original time point.
+  check_failure<sys_seconds>(STR("2026-07-xx"), STR("%Y-%m-%d"), expected);
+
+  // Parse a date into a system-clock time point with day precision.
   check(STR("2026-07-20"), STR("%F"), sys_days{2026y / July / 20});
   // A days target rejects time-of-day fields even when the UTC offset would cancel them.
   check_failure<sys_days>(STR("2026-07-20 04:00 +0400"), STR("%F %R %z"));
+}
+
+// Test time-point precision, representation, and conversion relative to the clock epoch.
+template <class CharT>
+void test_time_point_conversion() {
+  // Preserve fractional seconds for a time point just before the Unix epoch.
   check(STR("1969-12-31 23:59:59.5"), STR("%F %T"), sys_time<milliseconds>{-500ms});
+  // Preserve fractional seconds in a floating-point time point and match the trailing literal.
   check(STR("1970-01-01 00:00:12.125!"), STR("%F %T!"), sys_time<duration<double>>{duration<double>{12.125}});
+  // Convert one second after the Unix epoch to an attosecond count.
   check(STR("1970-01-01 00:00:01"), STR("%F %T"), sys_time<duration<long long, std::atto>>{1s});
 
 #if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&                             \
@@ -309,118 +485,145 @@ void test_time_points() {
 
 #if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&                             \
     !defined(TEST_HAS_NO_FILESYSTEM)
+// Test valid and invalid UTC leap seconds, including fractions and offsets.
 template <class CharT>
 void test_utc_leap_seconds() {
-  using namespace std::chrono;
   const utc_seconds leap = utc_clock::from_sys(sys_days{2017y / January / 1}) - 1s;
+  // Accept the leap second at the end of 2016.
   check(STR("2016-12-31 23:59:60"), STR("%F %T"), leap);
+  // Apply the UTC offset and preserve the fraction within a leap second.
   check(STR("2017-01-01 00:59:60.5 +0100"), STR("%F %T %z"), leap + 500ms);
+  // Reject second 60 at a time when no leap second occurs.
   check_failure<utc_seconds>(STR("2026-07-20 12:00:60"), STR("%F %T"));
 }
 #endif
 
+// Test signed years, century selection, and agreement between year fields.
 template <class CharT>
-void test_year_fields() {
-  using namespace std::chrono;
+void test_year_resolution() {
+  // Accept an explicit positive sign within the year field's width.
   check(STR("+123"), STR("%4Y"), year{123});
+  // Accept a negative year with room for its sign and three digits.
   check(STR("-123"), STR("%4Y"), year{-123});
+  // Year zero is a valid calendar year.
   check(STR("0"), STR("%Y"), year{0});
 
   // Two-digit years use a default century unless %C or %Y supplies one.
   check(STR("68"), STR("%y"), year{2068});
+  // The default century changes from 2000 to 1900 at two-digit year 69.
   check(STR("69"), STR("%y"), year{1969});
+  // Combine an explicit century with a two-digit year.
   check(STR("20 26"), STR("%C %y"), 2026y);
+  // Combine a negative century with a two-digit year.
   check(STR("-20 76"), STR("%3C %y"), year{-1976});
+  // Accept a full year followed by its matching century.
   check(STR("2026 20"), STR("%Y %C"), 2026y);
+  // A full year supplies the century for a matching two-digit year.
   check(STR("1926 26"), STR("%Y %y"), 1926y);
+  // The year in %F supplies the century for a following two-digit year.
   check(STR("1926-07-20 26"), STR("%F %y"), 1926y / July / 20);
 
-  // A sign consumes one character of the field's width.
-  {
-    std::basic_istringstream<CharT> stream(STR("+123"));
-    stream.imbue(std::locale::classic());
-    year result{};
-    from_stream(stream, STR("%3Y").c_str(), result);
-    assert(!stream.fail());
-    assert(result == year{12});
-    assert(stream.peek() == CharT('3'));
-  }
-
+  // Increasing the width does not make 100 a valid two-digit year.
   check_failure<year>(STR("100"), STR("%3y"));
-  check_failure<year>(STR("+1"), STR("%1Y"));
-  check_failure<year>(STR("2026 25"), STR("%Y %y"));
+  // A century alone cannot determine a complete year.
   check_failure<year>(STR("20"), STR("%C"));
 }
 
+// Test duration components, their ranges, and rejection of calendar fields.
+// Parse time-of-day and day-count components.
 template <class CharT>
 void test_duration() {
-  using namespace std::chrono;
-  // Parse time-of-day and day-count components.
-  for (const auto& format : {STR("%T"), STR("%X"), STR("%EX")})
-    check(STR("01:30:00"), format, 5400s);
-  check(STR("01:30:00 AM"), STR("%r"), 5400s);
-  check(STR("PM 01:30"), STR("%p %I:%M"), 810min);
+  // Parse a standalone seconds field into a duration.
+  check(STR("30"), STR("%S"), 30s);
+
+  // Interpret %j as a day count when parsing a duration.
   check(STR("2"), STR("%j"), days{2});
+  // Add hours and minutes to a multi-day duration.
   check(STR("2 01:30"), STR("%j %R"), 48h + 90min);
+  // Accept the largest ordinary hour, minute, and second fields.
   check(STR("23:59:59"), STR("%T"), 23h + 59min + 59s);
 
-  check_failure<seconds>(STR("15 01"), STR("%d %H"));
-  check_failure<hours>(STR("01:30"), STR("%R"));
-  check_failure<minutes>(STR("PM"), STR("%p"));
-  check_failure<minutes>(STR("60"), STR("%M"));
-  check_failure<seconds>(STR("60"), STR("%S"));
+  // Reject a calendar day-of-month field and preserve the original duration.
+  check_failure<seconds>(STR("15 01"), STR("%d %H"), 42s);
 }
 
+// Test twelve-hour and twenty-four-hour fields, AM/PM, and hour ranges.
 template <class CharT>
-void test_hours() {
-  using namespace std::chrono;
-  // %H can disambiguate %I without %p, in either input order.
+void test_hour_fields() {
+  // Twelve o'clock with AM denotes midnight without a twenty-four-hour field.
+  check(STR("12 AM"), STR("%I %p"), 0h);
+  // Apply a PM designator that precedes the twelve-hour time.
+  check(STR("PM 01:30"), STR("%p %I:%M"), 810min);
+
+  // Accept matching twenty-four-hour, twelve-hour, and PM fields.
   check(STR("13 01 PM"), STR("%H %I %p"), 13h);
+  // A preceding twenty-four-hour field resolves the twelve-hour field as PM.
   check(STR("13 01"), STR("%H %I"), 13h);
+  // A following twenty-four-hour field also resolves the twelve-hour field as PM.
   check(STR("01 13"), STR("%I %H"), 13h);
+  // Hour 00 resolves twelve o'clock as midnight.
   check(STR("00 12"), STR("%H %I"), 0h);
+  // Hour 12 resolves twelve o'clock as noon.
   check(STR("12 12"), STR("%H %I"), 12h);
 
-  check_failure<minutes>(STR("14 01"), STR("%H %I"));
-  check_failure<minutes>(STR("13 AM"), STR("%H %p"));
-  check_failure<hours>(STR("24"), STR("%H"));
+  // An AM/PM designator alone cannot determine a duration.
+  check_failure<minutes>(STR("PM"), STR("%p"));
+  // Hour 13 is outside the twelve-hour range even with a PM designator.
   check_failure<minutes>(STR("13 PM"), STR("%I %p"));
 }
 
+// Test duration representations and whether the target period can represent the parsed value.
 template <class CharT>
 void test_duration_conversion() {
-  using namespace std::chrono;
-
+  // Store a positive seconds count in an unsigned duration representation.
   check(STR("42"), STR("%S"), duration<unsigned>{42});
+  // Scale fractional seconds to a floating-point millisecond count.
   check(STR("1.25"), STR("%S"), duration<double, std::milli>{1250});
-  // A 1.5-second integer tick is coarser than the seconds field.
-  check_failure<duration<int, std::ratio<3, 2>>>(STR("1.5"), STR("%S"));
+  // An integral hours target cannot represent the additional thirty minutes.
+  check_failure<hours>(STR("01:30"), STR("%R"));
 }
 
+// Test UTC offset syntax and its effect on the parsed time point.
 template <class CharT>
 void test_offsets() {
-  using namespace std::chrono;
-  const sys_seconds date = sys_days{2026y / July / 20};
-  check(STR("2026-07-20 04"), STR("%F %z"), date - 4h);
-  check(STR("2026-07-20 0430"), STR("%F %z"), date - 4h - 30min);
-  check(STR("2026-07-20 -0130"), STR("%F %z"), date + 90min);
-  // Offset minutes are not clock-minute fields restricted to 0-59.
-  check(STR("2026-07-20 +0160"), STR("%F %z"), date - 120min);
+  // Consume the offset without storing it when the output pointer is null.
+  check(STR("15 +0130"), STR("%d %z"), day{15});
 
-  check(STR("2026-07-20 4"), STR("%F %Ez"), date - 4h);
-  check(STR("2026-07-20 +4:30"), STR("%F %Ez"), date - 4h - 30min);
-  check(STR("2026-07-20 +4:30"), STR("%F %Oz"), date - 4h - 30min);
-  check(STR("2026-07-20 -4:30"), STR("%F %Ez"), date + 4h + 30min);
+  const sys_seconds date = sys_days{2026y / July / 20};
+  // An unsigned two-digit offset supplies positive hours without minutes.
+  check(STR("2026-07-20 00:00:00 04"), STR("%F %T %z"), date - 4h);
+  // A four-digit offset supplies positive hours and minutes.
+  check(STR("2026-07-20 00:00:00 0430"), STR("%F %T %z"), date - 4h - 30min);
+  // Subtracting a negative UTC offset moves the result forward.
+  check(STR("2026-07-20 00:00:00 -0130"), STR("%F %T %z"), date + 90min);
+
+  // %Ez accepts a single-digit hour without minutes.
+  check(STR("2026-07-20 00:00:00 4"), STR("%F %T %Ez"), date - 4h);
+  // %Ez accepts an explicit positive sign and colon-separated minutes.
+  check(STR("2026-07-20 00:00:00 +4:30"), STR("%F %T %Ez"), date - 4h - 30min);
+  // %Oz accepts the same colon-separated offset syntax as %Ez.
+  check(STR("2026-07-20 00:00:00 +4:30"), STR("%F %T %Oz"), date - 4h - 30min);
+  // %Ez also accepts a negative colon-separated offset.
+  check(STR("2026-07-20 00:00:00 -4:30"), STR("%F %T %Ez"), date + 4h + 30min);
+
+  // A parsed UTC offset does not shift a local time point.
+  check(STR("2026-07-20 00:00:00 +0130"), STR("%F %T %z"), local_seconds{date.time_since_epoch()});
 
   // Basic hours and any supplied minutes require two digits.
-  check_failure<sys_seconds>(STR("2026-07-20 019"), STR("%F %z"));
-  check_failure<sys_seconds>(STR("2026-07-20 4:9"), STR("%F %Ez"));
-  check_failure<sys_seconds>(STR("2026-07-20 4"), STR("%F %z"));
+  check_failure<sys_seconds>(STR("2026-07-20 00:00:00 019!"), STR("%F %T %z!"));
+  // Modified offsets still require two minute digits after the colon.
+  check_failure<sys_seconds>(STR("2026-07-20 00:00:00 4:9!"), STR("%F %T %Ez!"));
+  // An unmodified offset requires two hour digits.
+  check_failure<sys_seconds>(STR("2026-07-20 00:00:00 4"), STR("%F %T %z"));
 }
 
+// Test consuming and storing time-zone abbreviations.
 template <class CharT>
 void test_abbrev() {
-  using namespace std::chrono;
+  // Consume the abbreviation without storing it when the output pointer is null.
+  check(STR("15 UTC"), STR("%d %Z"), day{15});
+
+  // Store letters, digits, and permitted punctuation in the abbreviation, stopping before '!'.
   std::basic_istringstream<CharT> stream(STR("2026-07-20 a_1/+B-2!"));
   stream.imbue(std::locale::classic());
   sys_days result{};
@@ -435,17 +638,20 @@ void test_abbrev() {
 template <class CharT>
 void test() {
   test_calendar_types<CharT>();
-  test_format<CharT>();
-  test_width_overflow<CharT>();
-  test_date_consistency<CharT>();
+  test_compound_specifiers<CharT>();
+  test_locale_formats<CharT>();
+  test_literals_and_whitespace<CharT>();
+  test_date_resolution<CharT>();
   test_modifier_E<CharT>();
   test_modifier_O<CharT>();
   test_fractional_seconds<CharT>();
-  test_year_fields<CharT>();
+  test_field_widths<CharT>();
+  test_year_resolution<CharT>();
   test_duration<CharT>();
-  test_hours<CharT>();
+  test_hour_fields<CharT>();
   test_duration_conversion<CharT>();
   test_time_points<CharT>();
+  test_time_point_conversion<CharT>();
 #if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) &&                             \
     !defined(TEST_HAS_NO_FILESYSTEM)
   test_utc_leap_seconds<CharT>();
diff --git a/libcxx/test/std/time/time.parse/parse.pass.cpp b/libcxx/test/std/time/time.parse/parse.pass.cpp
index e1f894f3184149..33ba6931273d04 100644
--- a/libcxx/test/std/time/time.parse/parse.pass.cpp
+++ b/libcxx/test/std/time/time.parse/parse.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++20
 // UNSUPPORTED: no-localization
 
 // <chrono>
@@ -31,13 +31,15 @@ concept CanParse = requires(Args&&... args) { std::chrono::parse(std::forward<Ar
 namespace custom {
 template <int Arity>
 struct value {
-  int count = 0;
+  int count            = 0;
+  bool abbrev_was_null = false;
 };
 
+// parse must return the input stream even when the ADL function returns void.
 template <class CharT, class Traits>
-std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, value<3>& out) {
+void from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, value<3>& out) {
   assert(fmt[0] == CharT('#'));
-  return is >> out.count;
+  is >> out.count;
 }
 
 template <class CharT, class Traits, class Alloc>
@@ -61,6 +63,7 @@ from_stream(std::basic_istream<CharT, Traits>& is,
             std::chrono::minutes* offset) {
   assert(fmt[0] == CharT('#'));
   assert(offset != nullptr);
+  out.abbrev_was_null = abbrev == nullptr;
   if (abbrev)
     *abbrev = STR("custom");
   *offset = std::chrono::minutes{90};
@@ -75,57 +78,98 @@ void check_constraints() {
   using String  = std::basic_string<CharT>;
   using Value   = custom::value<Arity>;
   using Minutes = std::chrono::minutes;
+  // Without optional outputs, parse calls a three-argument from_stream.
   static_assert(CanParse<const Format&, Value&> == (Arity == 3));
+  // An abbreviation output requires a four-argument from_stream.
   static_assert(CanParse<const Format&, Value&, String&> == (Arity == 4));
+  // An offset output requires five arguments, including a null abbreviation pointer.
   static_assert(CanParse<const Format&, Value&, Minutes&> == (Arity == 5));
+  // Both optional outputs require a five-argument from_stream.
   static_assert(CanParse<const Format&, Value&, String&, Minutes&> == (Arity == 5));
 }
 
+// Test overload participation for each ADL signature and invalid result arguments.
 template <class CharT, class Format>
 void test_constraints() {
   check_constraints<CharT, Format, 3>();
   check_constraints<CharT, Format, 4>();
   check_constraints<CharT, Format, 5>();
+  // Reject a type without a suitable from_stream.
   static_assert(!CanParse<const Format&, custom::not_parsable&>);
+  // This custom parser requires a mutable result.
   static_assert(!CanParse<const Format&, const custom::value<3>&>);
+  // The result must be an lvalue.
   static_assert(!CanParse<const Format&, custom::value<3>>);
 }
 
+// Test ADL dispatch and output forwarding for all four parse argument lists.
 template <class CharT, class Format>
 void test_adl() {
   using String              = std::basic_string<CharT>;
   const auto format_storage = STR("#");
   const Format fmt{format_storage.c_str()};
+  // Call the void-returning ADL parser and return the original input stream.
   {
     std::basic_istringstream<CharT> is(STR("7"));
     custom::value<3> result{};
     auto& returned = is >> std::chrono::parse(fmt, result);
+    static_assert(std::same_as<decltype(returned), std::basic_istream<CharT>&>);
+    assert(&returned == &is);
+    assert(!is.fail());
+    assert(result.count == 7);
+  }
+  // Forward only the abbreviation output to the four-argument ADL parser.
+  {
+    std::basic_istringstream<CharT> is(STR("7"));
+    custom::value<4> result{};
+    String abbrev;
+    auto& returned = is >> std::chrono::parse(fmt, result, abbrev);
+    static_assert(std::same_as<decltype(returned), std::basic_istream<CharT>&>);
     assert(&returned == &is);
     assert(!is.fail());
     assert(result.count == 7);
+    assert(abbrev == STR("custom"));
   }
+  // Forward the offset output with a null abbreviation pointer.
+  {
+    std::basic_istringstream<CharT> is(STR("7"));
+    custom::value<5> result{};
+    std::chrono::minutes offset{};
+    auto& returned = is >> std::chrono::parse(fmt, result, offset);
+    static_assert(std::same_as<decltype(returned), std::basic_istream<CharT>&>);
+    assert(&returned == &is);
+    assert(!is.fail());
+    assert(result.count == 7);
+    assert(result.abbrev_was_null);
+    assert(offset == std::chrono::minutes{90});
+  }
+  // Forward both optional outputs to the five-argument ADL parser.
   {
     std::basic_istringstream<CharT> is(STR("7"));
     custom::value<5> result{};
     String abbrev;
     std::chrono::minutes offset{};
-    is >> std::chrono::parse(fmt, result, abbrev, offset);
+    auto& returned = is >> std::chrono::parse(fmt, result, abbrev, offset);
+    static_assert(std::same_as<decltype(returned), std::basic_istream<CharT>&>);
+    assert(&returned == &is);
     assert(!is.fail());
     assert(result.count == 7);
+    assert(!result.abbrev_was_null);
     assert(abbrev == STR("custom"));
     assert(offset == std::chrono::minutes{90});
   }
 }
 
+// Test delegation to chrono parsing, optional outputs, and failure propagation.
 template <class CharT, class Format>
 void test_chrono_overloads() {
   using namespace std::chrono;
   const sys_seconds date    = sys_days{2026y / July / 20};
-  const auto format_storage = STR("%F %Z %z");
+  const auto format_storage = STR("%F %T %Z %z");
   const Format fmt{format_storage.c_str()};
-  // Test both format types, with and without optional outputs.
+  // Apply the parsed UTC offset without requesting the optional outputs.
   {
-    std::basic_istringstream<CharT> is(STR("2026-07-20 UTC +0130!"));
+    std::basic_istringstream<CharT> is(STR("2026-07-20 00:00:00 UTC +0130!"));
     is.imbue(std::locale::classic());
     sys_seconds result{};
     static_assert(std::same_as<decltype(is >> parse(fmt, result)), std::basic_istream<CharT>&>);
@@ -135,8 +179,9 @@ void test_chrono_overloads() {
     assert(result == date - 90min);
     assert(is.peek() == CharT('!'));
   }
+  // Store both optional outputs and leave the trailing character unread.
   {
-    std::basic_istringstream<CharT> is(STR("2026-07-20 UTC +0130!"));
+    std::basic_istringstream<CharT> is(STR("2026-07-20 00:00:00 UTC +0130!"));
     is.imbue(std::locale::classic());
     sys_seconds result{};
     std::basic_string<CharT> abbrev;

>From 6f37bcda7617687553d280c6a0390f63dd6355ca Mon Sep 17 00:00:00 2001
From: Emmett <emmettzhang2020 at outlook.com>
Date: Tue, 20 Oct 2026 16:31:33 +0800
Subject: [PATCH 6/6] [libc++] Fix chrono parsing test formatting

---
 libcxx/test/libcxx/time/from_stream.pass.cpp         | 10 +++++-----
 libcxx/test/std/time/time.parse/from_stream.pass.cpp |  4 +---
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/libcxx/test/libcxx/time/from_stream.pass.cpp b/libcxx/test/libcxx/time/from_stream.pass.cpp
index 254fa7e0d4153c..124580bd4a9e84 100644
--- a/libcxx/test/libcxx/time/from_stream.pass.cpp
+++ b/libcxx/test/libcxx/time/from_stream.pass.cpp
@@ -24,7 +24,7 @@
 
 template <class CharT>
 void test_read_digits() {
-  using Traits = std::char_traits<CharT>;
+  using Traits             = std::char_traits<CharT>;
   constexpr auto max_value = std::numeric_limits<std::uint64_t>::max();
   struct TestCase {
     std::basic_string<CharT> input;
@@ -80,11 +80,11 @@ void test_read_digits() {
 
 template <class CharT>
 void test_read_signed() {
-  using Traits = std::char_traits<CharT>;
-  constexpr int sentinel = 42;
+  using Traits            = std::char_traits<CharT>;
+  constexpr int sentinel  = 42;
   constexpr int min_value = std::numeric_limits<int>::min();
   constexpr int max_value = std::numeric_limits<int>::max();
-  const auto make_input = [](std::int64_t value) {
+  const auto make_input   = [](std::int64_t value) {
     const auto input = std::to_string(value);
     return std::basic_string<CharT>(input.begin(), input.end());
   };
@@ -118,7 +118,7 @@ void test_read_signed() {
   };
   for (const auto& c : cases) {
     std::basic_istringstream<CharT> stream{c.input};
-    int result = sentinel;
+    int result                   = sentinel;
     std::ios_base::iostate state = std::ios_base::goodbit;
     std::chrono::__from_stream_parser<CharT, Traits> parser{stream, state};
     parser.__read_signed(std::numeric_limits<unsigned>::max(), result);
diff --git a/libcxx/test/std/time/time.parse/from_stream.pass.cpp b/libcxx/test/std/time/time.parse/from_stream.pass.cpp
index 676a37ee55cfb6..b16da01f9c5a2d 100644
--- a/libcxx/test/std/time/time.parse/from_stream.pass.cpp
+++ b/libcxx/test/std/time/time.parse/from_stream.pass.cpp
@@ -347,9 +347,7 @@ void test_modifier_O() {
   check(STR("2026-07-20 12 PM"), STR("%F %OI %p"), sys_time<hours>{date} + 12h);
 
   // Parse fractional seconds with a colon-separated UTC offset.
-  check(STR("2026-07-20 13:45:30.125 +4:30"),
-        STR("%F %H:%M:%OS %Oz"),
-        date + 13h + 45min + 30s + 125ms - 4h - 30min);
+  check(STR("2026-07-20 13:45:30.125 +4:30"), STR("%F %H:%M:%OS %Oz"), date + 13h + 45min + 30s + 125ms - 4h - 30min);
 
   // This date has week number 29 with either Sunday or Monday as the first day.
   for (const auto& format : {STR("%Y %OU %w"), STR("%Y %OW %w")})



More information about the libcxx-commits mailing list