[libcxx] r350929 - Implement the 'sys_time' portions of the C++20 calendaring stuff. Reviewed as D56494

Marshall Clow mclow.lists at gmail.com
Fri Jan 11 07:12:04 PST 2019


Author: marshall
Date: Fri Jan 11 07:12:04 2019
New Revision: 350929

URL: http://llvm.org/viewvc/llvm-project?rev=350929&view=rev
Log:
Implement the 'sys_time' portions of the C++20 calendaring stuff. Reviewed as D56494

Added:
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.local_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.sys_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.local_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.sys_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.local_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.sys_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/local_time.types.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/sys.time.types.pass.cpp
Removed:
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.year_month_day_last.pass.cpp
Modified:
    libcxx/trunk/include/chrono
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.local_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.sys_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.year_month_day_last.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ok.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/day.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_local_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_sys_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.local_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.sys_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_local_days.pass.cpp
    libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_sys_days.pass.cpp

Modified: libcxx/trunk/include/chrono
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/chrono?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/include/chrono (original)
+++ libcxx/trunk/include/chrono Fri Jan 11 07:12:04 2019
@@ -1592,6 +1592,19 @@ using file_clock = _VSTD_FS::_Filesystem
 template<class _Duration>
 using file_time = time_point<file_clock, _Duration>;
 
+
+template <class _Duration>
+using sys_time    = time_point<system_clock, _Duration>;
+using sys_seconds = sys_time<seconds>;
+using sys_days    = sys_time<days>;
+
+struct local_t {};
+template<class Duration>
+using local_time  = time_point<local_t, Duration>;
+using local_seconds = local_time<seconds>;
+using local_days    = local_time<days>;
+
+
 struct _LIBCPP_TYPE_VIS last_spec { explicit last_spec() = default; };
 
 class _LIBCPP_TYPE_VIS day {
@@ -1812,21 +1825,36 @@ private:
     unsigned char __wd;
 public:
   weekday() = default;
-  explicit inline constexpr weekday(unsigned __val) noexcept: __wd(static_cast<unsigned char>(__val)) {}
-//   inline constexpr weekday(const sys_days& dp) noexcept;
-//   explicit constexpr weekday(const local_days& dp) noexcept;
+  inline explicit constexpr weekday(unsigned __val) noexcept : __wd(static_cast<unsigned char>(__val)) {}
+  inline constexpr          weekday(const sys_days& __sysd) noexcept
+          : __wd(__weekday_from_days(__sysd.time_since_epoch().count())) {}
+  inline explicit constexpr weekday(const local_days& __locd) noexcept
+          : __wd(__weekday_from_days(__locd.time_since_epoch().count())) {}
+
   inline constexpr weekday& operator++()    noexcept { __wd = (__wd == 6 ? 0 : __wd + 1); return *this; }
   inline constexpr weekday  operator++(int) noexcept { weekday __tmp = *this; ++(*this); return __tmp; }
   inline constexpr weekday& operator--()    noexcept { __wd = (__wd == 0 ? 6 : __wd - 1); return *this; }
   inline constexpr weekday  operator--(int) noexcept { weekday __tmp = *this; --(*this); return __tmp; }
          constexpr weekday& operator+=(const days& __dd) noexcept;
          constexpr weekday& operator-=(const days& __dd) noexcept;
-  explicit inline constexpr operator unsigned() const noexcept { return __wd; }
+  inline explicit constexpr operator unsigned() const noexcept { return __wd; }
   inline constexpr bool ok() const noexcept { return __wd <= 6; }
-  constexpr weekday_indexed operator[](unsigned __index) const noexcept;
-  constexpr weekday_last    operator[](last_spec) const noexcept;
+         constexpr weekday_indexed operator[](unsigned __index) const noexcept;
+         constexpr weekday_last    operator[](last_spec) const noexcept;
+
+  static constexpr unsigned char __weekday_from_days(int __days) noexcept;
 };
 
+
+// https://howardhinnant.github.io/date_algorithms.html#weekday_from_days
+inline constexpr
+unsigned char weekday::__weekday_from_days(int __days) noexcept
+{
+    return static_cast<unsigned char>(
+              static_cast<unsigned>(__days >= -4 ? (__days+4) % 7 : (__days+5) % 7 + 6)
+           );
+}
+
 inline constexpr
 bool operator==(const weekday& __lhs, const weekday& __rhs) noexcept
 { return static_cast<unsigned>(__lhs) == static_cast<unsigned>(__rhs); }
@@ -2221,6 +2249,7 @@ constexpr year_month operator-(const yea
 constexpr year_month operator-(const year_month& __lhs, const years& __rhs) noexcept
 { return __lhs + -__rhs; }
 
+class year_month_day_last;
 
 class _LIBCPP_TYPE_VIS year_month_day {
 private:
@@ -2232,24 +2261,66 @@ public:
      inline constexpr year_month_day(
             const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept
             : __y{__yval}, __m{__mval}, __d{__dval} {}  
-//   inline constexpr year_month_day(const year_month_day_last& __ymdl) noexcept;
-//   inline constexpr year_month_day(const sys_days& dp) noexcept;
-//   inline explicit constexpr year_month_day(const local_days& dp) noexcept;
+            constexpr year_month_day(const year_month_day_last& __ymdl) noexcept;
+     inline constexpr year_month_day(const sys_days& __sysd) noexcept
+            : year_month_day(__from_days(__sysd.time_since_epoch())) {}
+     inline explicit constexpr year_month_day(const local_days& __locd) noexcept
+            : year_month_day(__from_days(__locd.time_since_epoch())) {}
+
             constexpr year_month_day& operator+=(const months& __dm) noexcept;
             constexpr year_month_day& operator-=(const months& __dm) noexcept;
             constexpr year_month_day& operator+=(const years& __dy)  noexcept;
             constexpr year_month_day& operator-=(const years& __dy)  noexcept;
-     inline constexpr chrono::year  year()  const noexcept { return __y; }
+
+     inline constexpr chrono::year   year() const noexcept { return __y; }
      inline constexpr chrono::month month() const noexcept { return __m; }
-     inline constexpr chrono::day   day()   const noexcept  { return __d; }
-//   inline constexpr operator            sys_days() const noexcept;
-//   inline explicit constexpr operator local_days() const noexcept;
-
-//   TODO: This is not quite correct; requires the calendar bits to do right
-//   d_ is in the range [1d, (y_/m_/last).day()],
-     inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok() && __d.ok(); }
+     inline constexpr chrono::day     day() const noexcept { return __d; }
+     inline constexpr operator   sys_days() const noexcept          { return   sys_days{__to_days()}; }
+     inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; }
+
+            constexpr bool             ok() const noexcept;
+
+     static constexpr year_month_day __from_days(days __d) noexcept;
+     constexpr days __to_days() const noexcept;
 };
 
+
+// https://howardhinnant.github.io/date_algorithms.html#civil_from_days
+inline constexpr
+year_month_day
+year_month_day::__from_days(days __d) noexcept
+{
+    static_assert(std::numeric_limits<unsigned>::digits >= 18, "");
+    static_assert(std::numeric_limits<int>::digits >= 20     , "");
+    const int      __z = __d.count() + 719468;
+    const int      __era = (__z >= 0 ? __z : __z - 146096) / 146097;
+    const unsigned __doe = static_cast<unsigned>(__z - __era * 146097);              // [0, 146096]
+    const unsigned __yoe = (__doe - __doe/1460 + __doe/36524 - __doe/146096) / 365;  // [0, 399]
+    const int      __yr = static_cast<int>(__yoe) + __era * 400;
+    const unsigned __doy = __doe - (365 * __yoe + __yoe/4 - __yoe/100);              // [0, 365]
+    const unsigned __mp = (5 * __doy + 2)/153;                                       // [0, 11]
+    const unsigned __dy = __doy - (153 * __mp + 2)/5 + 1;                            // [1, 31]
+    const unsigned __mth = __mp + (__mp < 10 ? 3 : -9);                              // [1, 12]
+    return year_month_day{chrono::year{__yr + (__mth <= 2)}, chrono::month{__mth}, chrono::day{__dy}};
+}
+
+// https://howardhinnant.github.io/date_algorithms.html#days_from_civil
+inline constexpr days year_month_day::__to_days() const noexcept
+{
+    static_assert(std::numeric_limits<unsigned>::digits >= 18, "");
+    static_assert(std::numeric_limits<int>::digits >= 20     , "");
+
+    const int      __yr  = static_cast<int>(__y) - (__m <= February);
+    const unsigned __mth = static_cast<unsigned>(__m);
+    const unsigned __dy  = static_cast<unsigned>(__d);
+
+    const int      __era = (__yr >= 0 ? __yr : __yr - 399) / 400;
+    const unsigned __yoe = static_cast<unsigned>(__yr - __era * 400);                // [0, 399]
+    const unsigned __doy = (153 * (__mth + (__mth > 2 ? -3 : 9)) + 2) / 5 + __dy-1;  // [0, 365]
+    const unsigned __doe = __yoe * 365 + __yoe/4 - __yoe/100 + __doy;                // [0, 146096]
+    return days{__era * 146097 + static_cast<int>(__doe) - 719468};
+}
+
 inline constexpr
 bool operator==(const year_month_day& __lhs, const year_month_day& __rhs) noexcept
 { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); }
@@ -2347,16 +2418,30 @@ public:
      constexpr year_month_day_last& operator+=(const years& __y)  noexcept;
      constexpr year_month_day_last& operator-=(const years& __y)  noexcept;
 
-     constexpr chrono::year           year()           const noexcept { return __y; }
-     constexpr chrono::month          month()          const noexcept { return __mdl.month(); }
-     constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl; }
-//   constexpr chrono::day            day()            const noexcept;
-//   constexpr          operator sys_days()   const noexcept;
-//   explicit constexpr operator local_days() const noexcept;
-     constexpr bool ok() const noexcept { return __y.ok() && __mdl.ok(); }
+     inline constexpr chrono::year                     year() const noexcept { return __y; }
+     inline constexpr chrono::month                   month() const noexcept { return __mdl.month(); }
+     inline constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl; }
+            constexpr chrono::day                       day() const noexcept;
+     inline constexpr operator                     sys_days() const noexcept { return   sys_days{year()/month()/day()}; }
+     inline explicit constexpr operator          local_days() const noexcept { return local_days{year()/month()/day()}; }
+     inline constexpr bool                               ok() const noexcept { return __y.ok() && __mdl.ok(); }
 };
 
 inline constexpr
+chrono::day year_month_day_last::day() const noexcept
+{
+    constexpr chrono::day __d[] =
+    {
+        chrono::day(31), chrono::day(28), chrono::day(31),
+        chrono::day(30), chrono::day(31), chrono::day(30),
+        chrono::day(31), chrono::day(31), chrono::day(30),
+        chrono::day(31), chrono::day(30), chrono::day(31)
+    };
+    return month() != February || !__y.is_leap() ?
+        __d[static_cast<unsigned>(month()) - 1] : chrono::day{29};
+}
+
+inline constexpr
 bool operator==(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept
 { return __lhs.year() == __rhs.year() && __lhs.month_day_last() == __rhs.month_day_last(); }
 
@@ -2429,6 +2514,15 @@ inline constexpr year_month_day_last& ye
 inline constexpr year_month_day_last& year_month_day_last::operator+=(const years& __dy)  noexcept { *this = *this + __dy; return *this; }
 inline constexpr year_month_day_last& year_month_day_last::operator-=(const years& __dy)  noexcept { *this = *this - __dy; return *this; }
 
+inline constexpr year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept
+    : __y{__ymdl.year()}, __m{__ymdl.month()}, __d{__ymdl.day()} {}  
+
+inline constexpr bool year_month_day::ok() const noexcept
+{
+    if (!__y.ok() || !__m.ok()) return false;
+    return chrono::day{1} <= __d && __d <= (__y / __m / last).day();
+}
+
 class _LIBCPP_TYPE_VIS year_month_weekday {
     chrono::year            __y;
     chrono::month           __m;
@@ -2438,8 +2532,10 @@ public:
     constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval,
                                const chrono::weekday_indexed& __wdival) noexcept
         : __y{__yval}, __m{__mval}, __wdi{__wdival} {}
-//  constexpr year_month_weekday(const sys_days& dp) noexcept;
-//  explicit constexpr year_month_weekday(const local_days& dp) noexcept;
+    constexpr year_month_weekday(const sys_days& __sysd) noexcept
+            : year_month_weekday(__from_days(__sysd.time_since_epoch())) {}
+    inline explicit constexpr year_month_weekday(const local_days& __locd) noexcept
+            : year_month_weekday(__from_days(__locd.time_since_epoch())) {}
     constexpr year_month_weekday& operator+=(const months& m) noexcept;
     constexpr year_month_weekday& operator-=(const months& m) noexcept;
     constexpr year_month_weekday& operator+=(const years& y)  noexcept;
@@ -2451,17 +2547,38 @@ public:
     inline constexpr unsigned                          index() const noexcept { return __wdi.index(); }
     inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; }
 
-//  constexpr          operator sys_days()   const noexcept;
-//  explicit constexpr operator local_days() const noexcept;
+    inline constexpr                       operator sys_days() const noexcept { return   sys_days{__to_days()}; }
+    inline explicit constexpr operator            local_days() const noexcept { return local_days{__to_days()}; }
     inline constexpr bool ok() const noexcept
     {
         if (!__y.ok() || !__m.ok() || !__wdi.ok()) return false;
     //  TODO: make sure it's a valid date
         return true;
     }
+
+    static constexpr year_month_weekday __from_days(days __d) noexcept;
+    constexpr days __to_days() const noexcept;
 };
 
 inline constexpr
+year_month_weekday year_month_weekday::__from_days(days __d) noexcept
+{
+    const sys_days      __sysd{__d};
+    const chrono::weekday __wd = chrono::weekday(__sysd);
+    const year_month_day __ymd = year_month_day(__sysd);
+    return year_month_weekday{__ymd.year(), __ymd.month(), 
+                              __wd[(static_cast<unsigned>(__ymd.day())-1)/7+1]};
+}
+
+inline constexpr
+days year_month_weekday::__to_days() const noexcept
+{
+    const sys_days __sysd = sys_days(__y/__m/1);
+    return (__sysd + (__wdi.weekday() - chrono::weekday(__sysd) + days{(__wdi.index()-1)*7}))
+                .time_since_epoch();
+}
+
+inline constexpr
 bool operator==(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept
 { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); }
 
@@ -2538,12 +2655,23 @@ public:
     inline constexpr chrono::month               month() const noexcept { return __m; }
     inline constexpr chrono::weekday           weekday() const noexcept { return __wdl.weekday(); }
     inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; }
-//  constexpr          operator sys_days()   const noexcept;
-//  explicit constexpr operator local_days() const noexcept;
+    inline constexpr operator                 sys_days() const noexcept { return   sys_days{__to_days()}; }
+    inline explicit constexpr operator      local_days() const noexcept { return local_days{__to_days()}; }
     inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok() && __wdl.ok(); }
+    
+    constexpr days __to_days() const noexcept;
+    
 };
 
 inline constexpr
+days year_month_weekday_last::__to_days() const noexcept
+{
+    const sys_days __last = sys_days{__y/__m/last};
+    return (__last - (chrono::weekday{__last} - __wdl.weekday())).time_since_epoch();
+
+}
+
+inline constexpr
 bool operator==(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept
 { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); }
 

Added: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.local_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.local_days.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.local_days.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.local_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+// class weekday;
+
+//  constexpr weekday(const local_days& dp) noexcept;
+//
+//  Effects:  Constructs an object of type weekday by computing what day
+//              of the week  corresponds to the local_days dp, and representing
+//              that day of the week in wd_ 
+//
+//  Remarks: For any value ymd of type year_month_day for which ymd.ok() is true,
+//                ymd == year_month_day{sys_days{ymd}} is true.
+// 
+// [Example: 
+//  If dp represents 1970-01-01, the constructed weekday represents Thursday by storing 4 in wd_.
+// —end example]
+
+#include <chrono>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+    using local_days = std::chrono::local_days;
+    using days       = std::chrono::days;
+    using weekday    = std::chrono::weekday;
+
+    ASSERT_NOEXCEPT(weekday{std::declval<local_days>()});
+
+    {
+    constexpr local_days sd{}; // 1-Jan-1970 was a Thursday
+    constexpr weekday wd{sd};
+
+    static_assert( wd.ok(), "");
+    static_assert(static_cast<unsigned>(wd) == 4, "");
+    }
+
+    {
+    constexpr local_days sd{days{10957+32}}; // 2-Feb-2000 was a Wednesday
+    constexpr weekday wd{sd};
+
+    static_assert( wd.ok(), "");
+    static_assert(static_cast<unsigned>(wd) == 3, "");
+    }
+
+
+    {
+    constexpr local_days sd{days{-10957}}; // 2-Jan-1940 was a Tuesday
+    constexpr weekday wd{sd};
+
+    static_assert( wd.ok(), "");
+    static_assert(static_cast<unsigned>(wd) == 2, "");
+    }
+
+    {
+    local_days sd{days{-(10957+34)}}; // 29-Nov-1939 was a Wednesday
+    weekday wd{sd};
+
+    assert( wd.ok());
+    assert(static_cast<unsigned>(wd) == 3);
+    }
+}

Added: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.sys_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.sys_days.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.sys_days.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.weekday/time.cal.weekday.members/ctor.sys_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+// class weekday;
+
+//  constexpr weekday(const sys_days& dp) noexcept;
+//
+//  Effects:  Constructs an object of type weekday by computing what day
+//              of the week  corresponds to the sys_days dp, and representing
+//              that day of the week in wd_ 
+//
+//  Remarks: For any value ymd of type year_month_day for which ymd.ok() is true,
+//                ymd == year_month_day{sys_days{ymd}} is true.
+// 
+// [Example: 
+//  If dp represents 1970-01-01, the constructed weekday represents Thursday by storing 4 in wd_.
+// —end example]
+
+#include <chrono>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+    using sys_days  = std::chrono::sys_days;
+    using days      = std::chrono::days;
+    using weekday   = std::chrono::weekday;
+
+    ASSERT_NOEXCEPT(weekday{std::declval<sys_days>()});
+
+    {
+    constexpr sys_days sd{}; // 1-Jan-1970 was a Thursday
+    constexpr weekday wd{sd};
+
+    static_assert( wd.ok(), "");
+    static_assert(static_cast<unsigned>(wd) == 4, "");
+    }
+
+    {
+    constexpr sys_days sd{days{10957+32}}; // 2-Feb-2000 was a Wednesday
+    constexpr weekday wd{sd};
+
+    static_assert( wd.ok(), "");
+    static_assert(static_cast<unsigned>(wd) == 3, "");
+    }
+
+
+    {
+    constexpr sys_days sd{days{-10957}}; // 2-Jan-1940 was a Tuesday
+    constexpr weekday wd{sd};
+
+    static_assert( wd.ok(), "");
+    static_assert(static_cast<unsigned>(wd) == 2, "");
+    }
+
+    {
+    sys_days sd{days{-(10957+34)}}; // 29-Nov-1939 was a Wednesday
+    weekday wd{sd};
+
+    assert( wd.ok());
+    assert(static_cast<unsigned>(wd) == 3);
+    }
+}

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.local_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.local_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.local_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.local_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_day;
@@ -34,11 +33,53 @@
 int main()
 {
     using year           = std::chrono::year;
-    using month          = std::chrono::month;
     using day            = std::chrono::day;
-//  using local_days     = std::chrono::local_days;
+    using local_days     = std::chrono::local_days;
+    using days           = std::chrono::days;
     using year_month_day = std::chrono::year_month_day;
 
-//  ASSERT_NOEXCEPT(year_month_day{std::declval<const local_days>()});
-    assert(false);
+    ASSERT_NOEXCEPT(year_month_day{std::declval<local_days>()});
+
+    {
+    constexpr local_days sd{};
+    constexpr year_month_day ymd{sd};
+
+    static_assert( ymd.ok(),                            "");
+    static_assert( ymd.year()  == year{1970},           "");
+    static_assert( ymd.month() == std::chrono::January, "");
+    static_assert( ymd.day()   == day{1},               "");
+    }
+
+    {
+    constexpr local_days sd{days{10957+32}};
+    constexpr year_month_day ymd{sd};
+
+    static_assert( ymd.ok(),                             "");
+    static_assert( ymd.year()  == year{2000},            "");
+    static_assert( ymd.month() == std::chrono::February, "");
+    static_assert( ymd.day()   == day{2},                "");
+    }
+
+
+//  There's one more leap day between 1/1/40 and 1/1/70
+//  when compared to 1/1/70 -> 1/1/2000
+    {
+    constexpr local_days sd{days{-10957}};
+    constexpr year_month_day ymd{sd};
+
+    static_assert( ymd.ok(),                            "");
+    static_assert( ymd.year()  == year{1940},           "");
+    static_assert( ymd.month() == std::chrono::January, "");
+    static_assert( ymd.day()   == day{2},               "");
+    }
+
+    {
+    local_days sd{days{-(10957+34)}};
+    year_month_day ymd{sd};
+
+    assert( ymd.ok());
+    assert( ymd.year()  == year{1939});
+    assert( ymd.month() == std::chrono::November);
+    assert( ymd.day()   == day{29});
+    }
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.sys_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.sys_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.sys_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.sys_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,15 +7,14 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_day;
 
 //  constexpr year_month_day(const sys_days& dp) noexcept;
 //
-//  Effects:  Constructs an object of type year_month_day that corresponds
-//                to the date represented by dp
+//  Effects:  Constructs an object of type year_month_day that corresponds 
+//                to the date represented by dp.
 //
 //  Remarks: For any value ymd of type year_month_day for which ymd.ok() is true,
 //                ymd == year_month_day{sys_days{ymd}} is true.
@@ -33,12 +32,53 @@
 int main()
 {
     using year           = std::chrono::year;
-    using month          = std::chrono::month;
     using day            = std::chrono::day;
-//  using sys_days     = std::chrono::sys_days;
+    using sys_days       = std::chrono::sys_days;
+    using days           = std::chrono::days;
     using year_month_day = std::chrono::year_month_day;
 
-//  ASSERT_NOEXCEPT(year_month_day{std::declval<const sys_days>()});
-    assert(false);
+    ASSERT_NOEXCEPT(year_month_day{std::declval<sys_days>()});
 
+    {
+    constexpr sys_days sd{};
+    constexpr year_month_day ymd{sd};
+
+    static_assert( ymd.ok(),                            "");
+    static_assert( ymd.year()  == year{1970},           "");
+    static_assert( ymd.month() == std::chrono::January, "");
+    static_assert( ymd.day()   == day{1},               "");
+    }
+
+    {
+    constexpr sys_days sd{days{10957+32}};
+    constexpr year_month_day ymd{sd};
+
+    static_assert( ymd.ok(),                             "");
+    static_assert( ymd.year()  == year{2000},            "");
+    static_assert( ymd.month() == std::chrono::February, "");
+    static_assert( ymd.day()   == day{2},                "");
+    }
+
+
+//  There's one more leap day between 1/1/40 and 1/1/70
+//  when compared to 1/1/70 -> 1/1/2000
+    {
+    constexpr sys_days sd{days{-10957}};
+    constexpr year_month_day ymd{sd};
+
+    static_assert( ymd.ok(),                            "");
+    static_assert( ymd.year()  == year{1940},           "");
+    static_assert( ymd.month() == std::chrono::January, "");
+    static_assert( ymd.day()   == day{2},               "");
+    }
+
+    {
+    sys_days sd{days{-(10957+34)}};
+    year_month_day ymd{sd};
+
+    assert( ymd.ok());
+    assert( ymd.year()  == year{1939});
+    assert( ymd.month() == std::chrono::November);
+    assert( ymd.day()   == day{29});
+    }
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.year_month_day_last.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.year_month_day_last.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.year_month_day_last.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ctor.year_month_day_last.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_day;
@@ -33,10 +32,49 @@ int main()
     using year                = std::chrono::year;
     using month               = std::chrono::month;
     using day                 = std::chrono::day;
-//  using year_month_day_last = std::chrono::year_month_day_last;
+    using month_day_last = std::chrono::month_day_last;
+    using year_month_day_last = std::chrono::year_month_day_last;
     using year_month_day      = std::chrono::year_month_day;
 
-//  ASSERT_NOEXCEPT(year_month_day{std::declval<const year_month_day_last>()});
-    assert(false);
+    ASSERT_NOEXCEPT(year_month_day{std::declval<const year_month_day_last>()});
 
+    {
+    constexpr year_month_day_last ymdl{year{2019}, month_day_last{month{1}}};
+    constexpr year_month_day ymd{ymdl};
+
+    static_assert( ymd.year()  == year{2019}, "");
+    static_assert( ymd.month() == month{1},   "");
+    static_assert( ymd.day()   == day{31},    "");
+    static_assert( ymd.ok(),                  "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{1970}, month_day_last{month{4}}};
+    constexpr year_month_day ymd{ymdl};
+
+    static_assert( ymd.year()  == year{1970}, "");
+    static_assert( ymd.month() == month{4},   "");
+    static_assert( ymd.day()   == day{30},    "");
+    static_assert( ymd.ok(),                  "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{2000}, month_day_last{month{2}}};
+    constexpr year_month_day ymd{ymdl};
+
+    static_assert( ymd.year()  == year{2000}, "");
+    static_assert( ymd.month() == month{2},   "");
+    static_assert( ymd.day()   == day{29},    "");
+    static_assert( ymd.ok(),                  "");
+    }
+
+    { // Feb 1900 was NOT a leap year.
+    year_month_day_last ymdl{year{1900}, month_day_last{month{2}}};
+    year_month_day ymd{ymdl};
+
+    assert( ymd.year()  == year{1900});
+    assert( ymd.month() == month{2});
+    assert( ymd.day()   == day{28});
+    assert( ymd.ok());
+    }
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ok.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ok.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ok.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/ok.pass.cpp Fri Jan 11 07:12:04 2019
@@ -44,6 +44,37 @@ int main()
 
     static_assert( year_month_day{year{2019},   January, day{1}}.ok(), ""); // All OK
 
+//  Some months have a 31st
+    static_assert( year_month_day{year{2020},   month{ 1}, day{31}}.ok(), "");
+    static_assert(!year_month_day{year{2020},   month{ 2}, day{31}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 3}, day{31}}.ok(), "");
+    static_assert(!year_month_day{year{2020},   month{ 4}, day{31}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 5}, day{31}}.ok(), "");
+    static_assert(!year_month_day{year{2020},   month{ 6}, day{31}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 7}, day{31}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 8}, day{31}}.ok(), "");
+    static_assert(!year_month_day{year{2020},   month{ 9}, day{31}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{10}, day{31}}.ok(), "");
+    static_assert(!year_month_day{year{2020},   month{11}, day{31}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{12}, day{31}}.ok(), "");
+
+//  Everyone except FEB has a 30th
+    static_assert( year_month_day{year{2020},   month{ 1}, day{30}}.ok(), "");
+    static_assert(!year_month_day{year{2020},   month{ 2}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 3}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 4}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 5}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 6}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 7}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 8}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{ 9}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{10}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{11}, day{30}}.ok(), "");
+    static_assert( year_month_day{year{2020},   month{12}, day{30}}.ok(), "");
+
+    static_assert(!year_month_day{year{2019},   std::chrono::February, day{29}}.ok(), ""); // Not a leap year
+    static_assert( year_month_day{year{2020},   std::chrono::February, day{29}}.ok(), ""); // Ok; 2020 is a leap year
+
     for (unsigned i = 0; i <= 50; ++i)
     {
         year_month_day ym{year{2019}, January, day{i}};

Added: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.local_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.local_days.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.local_days.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.local_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+// class year_month_day;
+
+// constexpr operator local_days() const noexcept;
+//
+// Returns: If ok(), returns a local_days holding a count of days from the
+//   local_days epoch to *this (a negative value if *this represents a date
+//   prior to the sys_days epoch). Otherwise, if y_.ok() && m_.ok() is true,
+//   returns a sys_days which is offset from sys_days{y_/m_/last} by the
+//   number of days d_ is offset from sys_days{y_/m_/last}.day(). Otherwise
+//   the value returned is unspecified.
+//
+// Remarks: A local_days in the range [days{-12687428}, days{11248737}] which
+//   is converted to a year_month_day shall have the same value when
+//   converted back to a sys_days.
+//
+// [Example:
+//   static_assert(year_month_day{local_days{2017y/January/0}}  == 2016y/December/31);
+//   static_assert(year_month_day{local_days{2017y/January/31}} == 2017y/January/31);
+//   static_assert(year_month_day{local_days{2017y/January/32}} == 2017y/February/1);
+// —end example]
+
+#include <chrono>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+void RunTheExample()
+{
+    using namespace std::chrono;
+
+    static_assert(year_month_day{local_days{2017y/January/0}}  == 2016y/December/31);
+    static_assert(year_month_day{local_days{2017y/January/31}} == 2017y/January/31);
+    static_assert(year_month_day{local_days{2017y/January/32}} == 2017y/February/1);  
+}
+
+int main()
+{
+    using year           = std::chrono::year;
+    using month          = std::chrono::month;
+    using day            = std::chrono::day;
+    using local_days       = std::chrono::local_days;
+    using days           = std::chrono::days;
+    using year_month_day = std::chrono::year_month_day;
+
+    ASSERT_NOEXCEPT(local_days(std::declval<year_month_day>()));
+    RunTheExample();
+
+    {
+    constexpr year_month_day ymd{year{1970}, month{1}, day{1}};
+    constexpr local_days sd{ymd};
+
+    static_assert( sd.time_since_epoch() == days{0}, "");
+    static_assert( year_month_day{sd} == ymd, ""); // and back
+    }
+
+    {
+    constexpr year_month_day ymd{year{2000}, month{2}, day{2}};
+    constexpr local_days sd{ymd};
+
+    static_assert( sd.time_since_epoch() == days{10957+32}, "");
+    static_assert( year_month_day{sd} == ymd, ""); // and back
+    }
+
+//  There's one more leap day between 1/1/40 and 1/1/70
+//  when compared to 1/1/70 -> 1/1/2000
+    {
+    constexpr year_month_day ymd{year{1940}, month{1}, day{2}};
+    constexpr local_days sd{ymd};
+
+    static_assert( sd.time_since_epoch() == days{-10957}, "");
+    static_assert( year_month_day{sd} == ymd, ""); // and back
+    }
+
+    {
+    year_month_day ymd{year{1939}, month{11}, day{29}};
+    local_days sd{ymd};
+
+    assert( sd.time_since_epoch() == days{-(10957+34)});
+    assert( year_month_day{sd} == ymd); // and back
+    }
+
+}

Added: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.sys_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.sys_days.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.sys_days.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymd/time.cal.ymd.members/op.sys_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+// class year_month_day;
+
+// constexpr operator sys_days() const noexcept;
+//
+// Returns: If ok(), returns a sys_days holding a count of days from the
+//   sys_days epoch to *this (a negative value if *this represents a date
+//   prior to the sys_days epoch). Otherwise, if y_.ok() && m_.ok() is true,
+//   returns a sys_days which is offset from sys_days{y_/m_/last} by the
+//   number of days d_ is offset from sys_days{y_/m_/last}.day(). Otherwise
+//   the value returned is unspecified.
+//
+// Remarks: A sys_days in the range [days{-12687428}, days{11248737}] which
+//   is converted to a year_month_day shall have the same value when
+//   converted back to a sys_days.
+//
+// [Example:
+//   static_assert(year_month_day{sys_days{2017y/January/0}}  == 2016y/December/31);
+//   static_assert(year_month_day{sys_days{2017y/January/31}} == 2017y/January/31);
+//   static_assert(year_month_day{sys_days{2017y/January/32}} == 2017y/February/1);
+// —end example]
+
+#include <chrono>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+void RunTheExample()
+{
+    using namespace std::chrono;
+
+    static_assert(year_month_day{sys_days{2017y/January/0}}  == 2016y/December/31);
+    static_assert(year_month_day{sys_days{2017y/January/31}} == 2017y/January/31);
+    static_assert(year_month_day{sys_days{2017y/January/32}} == 2017y/February/1);  
+}
+
+int main()
+{
+    using year           = std::chrono::year;
+    using month          = std::chrono::month;
+    using day            = std::chrono::day;
+    using sys_days       = std::chrono::sys_days;
+    using days           = std::chrono::days;
+    using year_month_day = std::chrono::year_month_day;
+
+    ASSERT_NOEXCEPT(sys_days(std::declval<year_month_day>()));
+    RunTheExample();
+
+    {
+    constexpr year_month_day ymd{year{1970}, month{1}, day{1}};
+    constexpr sys_days sd{ymd};
+
+    static_assert( sd.time_since_epoch() == days{0}, "");
+    static_assert( year_month_day{sd} == ymd, ""); // and back
+    }
+
+    {
+    constexpr year_month_day ymd{year{2000}, month{2}, day{2}};
+    constexpr sys_days sd{ymd};
+
+    static_assert( sd.time_since_epoch() == days{10957+32}, "");
+    static_assert( year_month_day{sd} == ymd, ""); // and back
+    }
+
+//  There's one more leap day between 1/1/40 and 1/1/70
+//  when compared to 1/1/70 -> 1/1/2000
+    {
+    constexpr year_month_day ymd{year{1940}, month{1}, day{2}};
+    constexpr sys_days sd{ymd};
+
+    static_assert( sd.time_since_epoch() == days{-10957}, "");
+    static_assert( year_month_day{sd} == ymd, ""); // and back
+    }
+
+    {
+    year_month_day ymd{year{1939}, month{11}, day{29}};
+    sys_days sd{ymd};
+
+    assert( sd.time_since_epoch() == days{-(10957+34)});
+    assert( year_month_day{sd} == ymd); // and back
+    }
+
+}

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/day.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/day.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/day.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/day.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_day_last;
@@ -29,15 +28,24 @@ int main()
     using month_day_last      = std::chrono::month_day_last;
     using year_month_day_last = std::chrono::year_month_day_last;
 
-//  TODO: wait for calendar
-//     ASSERT_NOEXCEPT(               std::declval<const year_month_day_last>().day());
-//     ASSERT_SAME_TYPE(day, decltype(std::declval<const year_month_day_last>().day()));
-//
-//     static_assert( year_month_day_last{}.day() == day{}, "");
+    ASSERT_NOEXCEPT(               std::declval<const year_month_day_last>().day());
+    ASSERT_SAME_TYPE(day, decltype(std::declval<const year_month_day_last>().day()));
 
-    for (unsigned i = 1; i <= 12; ++i)
-    {
-        year_month_day_last ymd(year{1234}, month_day_last{month{i}});
-        assert( static_cast<unsigned>(ymd.day()) == i);
-    }
+//  Some months have a 31st
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 1}}}.day() == day{31}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 2}}}.day() == day{29}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 3}}}.day() == day{31}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 4}}}.day() == day{30}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 5}}}.day() == day{31}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 6}}}.day() == day{30}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 7}}}.day() == day{31}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 8}}}.day() == day{31}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{ 9}}}.day() == day{30}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{10}}}.day() == day{31}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{11}}}.day() == day{30}, "");
+    static_assert( year_month_day_last{year{2020}, month_day_last{month{12}}}.day() == day{31}, "");
+
+    assert((year_month_day_last{year{2019}, month_day_last{month{ 2}}}.day() == day{28}));
+    assert((year_month_day_last{year{2020}, month_day_last{month{ 2}}}.day() == day{29}));
+    assert((year_month_day_last{year{2021}, month_day_last{month{ 2}}}.day() == day{28}));
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_local_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_local_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_local_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_local_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_day_last;
@@ -24,13 +23,39 @@
 int main()
 {
     using year                = std::chrono::year;
-    using month               = std::chrono::month;
-    using day                 = std::chrono::day;
     using month_day_last      = std::chrono::month_day_last;
     using year_month_day_last = std::chrono::year_month_day_last;
-//  using sys_days            = std::chrono::local_days;
+    using local_days          = std::chrono::local_days;
+    using days                = std::chrono::days;
 
-//  ASSERT_NOEXCEPT(                static_cast<local_days>(std::declval<const year_month_day_last>().year()));
-//  ASSERT_SAME_TYPE(year, decltype(static_cast<local_days>(std::declval<const year_month_day_last>().year()));
-    assert(false);
+    ASSERT_NOEXCEPT(                      static_cast<local_days>(std::declval<const year_month_day_last>()));
+    ASSERT_SAME_TYPE(local_days, decltype(static_cast<local_days>(std::declval<const year_month_day_last>())));
+
+    { // Last day in Jan 1970 was the 31st
+    constexpr year_month_day_last ymdl{year{1970}, month_day_last{std::chrono::January}};
+    constexpr local_days sd{ymdl};
+    
+    static_assert(sd.time_since_epoch() == days{30}, "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{2000}, month_day_last{std::chrono::January}};
+    constexpr local_days sd{ymdl};
+
+    static_assert(sd.time_since_epoch() == days{10957+30}, "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{1940}, month_day_last{std::chrono::January}};
+    constexpr local_days sd{ymdl};
+
+    static_assert(sd.time_since_epoch() == days{-10957+29}, "");
+    }
+
+    {
+    year_month_day_last ymdl{year{1939}, month_day_last{std::chrono::November}};
+    local_days sd{ymdl};
+
+    assert(sd.time_since_epoch() == days{-(10957+33)});
+    }
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_sys_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_sys_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_sys_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.members/op_sys_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_day_last;
@@ -24,13 +23,39 @@
 int main()
 {
     using year                = std::chrono::year;
-    using month               = std::chrono::month;
-    using day                 = std::chrono::day;
     using month_day_last      = std::chrono::month_day_last;
     using year_month_day_last = std::chrono::year_month_day_last;
-//  using sys_days            = std::chrono::sys_days;
+    using sys_days            = std::chrono::sys_days;
+    using days                = std::chrono::days;
 
-//  ASSERT_NOEXCEPT(                static_cast<sys_days>(std::declval<const year_month_day_last>().year()));
-//  ASSERT_SAME_TYPE(year, decltype(static_cast<sys_days>(std::declval<const year_month_day_last>().year()));
-    assert(false);
+    ASSERT_NOEXCEPT(                    static_cast<sys_days>(std::declval<const year_month_day_last>()));
+    ASSERT_SAME_TYPE(sys_days, decltype(static_cast<sys_days>(std::declval<const year_month_day_last>())));
+
+    { // Last day in Jan 1970 was the 31st
+    constexpr year_month_day_last ymdl{year{1970}, month_day_last{std::chrono::January}};
+    constexpr sys_days sd{ymdl};
+    
+    static_assert(sd.time_since_epoch() == days{30}, "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{2000}, month_day_last{std::chrono::January}};
+    constexpr sys_days sd{ymdl};
+
+    static_assert(sd.time_since_epoch() == days{10957+30}, "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{1940}, month_day_last{std::chrono::January}};
+    constexpr sys_days sd{ymdl};
+
+    static_assert(sd.time_since_epoch() == days{-10957+29}, "");
+    }
+
+    {
+    year_month_day_last ymdl{year{1939}, month_day_last{std::chrono::November}};
+    sys_days sd{ymdl};
+
+    assert(sd.time_since_epoch() == days{-(10957+33)});
+    }
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.local_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.local_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.local_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.local_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_weekday;
@@ -33,12 +32,64 @@
 
 int main()
 {
-    using year           = std::chrono::year;
-    using month          = std::chrono::month;
-    using day            = std::chrono::day;
-//  using local_days     = std::chrono::local_days;
+    using year               = std::chrono::year;
+    using days               = std::chrono::days;
+    using local_days         = std::chrono::local_days;
+    using weekday_indexed    = std::chrono::weekday_indexed;
     using year_month_weekday = std::chrono::year_month_weekday;
 
-//  ASSERT_NOEXCEPT(year_month_weekday{std::declval<const local_days>()});
-    assert(false);
+    ASSERT_NOEXCEPT(year_month_weekday{std::declval<const local_days>()});
+
+    {
+    constexpr local_days sd{}; // 1-Jan-1970 was a Thursday
+    constexpr year_month_weekday ymwd{sd};
+
+    static_assert( ymwd.ok(),                                                            "");
+    static_assert( ymwd.year()            == year{1970},                                 "");
+    static_assert( ymwd.month()           == std::chrono::January,                       "");
+    static_assert( ymwd.weekday()         == std::chrono::Thursday,                      "");
+    static_assert( ymwd.index()           == 1,                                          "");
+    static_assert( ymwd.weekday_indexed() == weekday_indexed{std::chrono::Thursday, 1},  "");
+    static_assert( ymwd                   == year_month_weekday{local_days{ymwd}},       ""); // round trip
+    }
+
+    {
+    constexpr local_days sd{days{10957+32}}; // 2-Feb-2000 was a Wednesday
+    constexpr year_month_weekday ymwd{sd};
+
+    static_assert( ymwd.ok(),                                                            "");
+    static_assert( ymwd.year()            == year{2000},                                 "");
+    static_assert( ymwd.month()           == std::chrono::February,                      "");
+    static_assert( ymwd.weekday()         == std::chrono::Wednesday,                     "");
+    static_assert( ymwd.index()           == 1,                                          "");
+    static_assert( ymwd.weekday_indexed() == weekday_indexed{std::chrono::Wednesday, 1}, "");
+    static_assert( ymwd                   == year_month_weekday{local_days{ymwd}},       ""); // round trip
+    }
+
+
+    {
+    constexpr local_days sd{days{-10957}}; // 2-Jan-1940 was a Tuesday
+    constexpr year_month_weekday ymwd{sd};
+
+    static_assert( ymwd.ok(),                                                            "");
+    static_assert( ymwd.year()            == year{1940},                                 "");
+    static_assert( ymwd.month()           == std::chrono::January,                       "");
+    static_assert( ymwd.weekday()         == std::chrono::Tuesday,                       "");
+    static_assert( ymwd.index()           == 1,                                          "");
+    static_assert( ymwd.weekday_indexed() == weekday_indexed{std::chrono::Tuesday, 1},   "");
+    static_assert( ymwd                   == year_month_weekday{local_days{ymwd}},       ""); // round trip
+    }
+
+    {
+    local_days sd{days{-(10957+34)}}; // 29-Nov-1939 was a Wednesday
+    year_month_weekday ymwd{sd};
+
+    assert( ymwd.ok());
+    assert( ymwd.year()            == year{1939});
+    assert( ymwd.month()           == std::chrono::November);
+    assert( ymwd.weekday()         == std::chrono::Wednesday);
+    assert( ymwd.index()           == 5);
+    assert((ymwd.weekday_indexed() == weekday_indexed{std::chrono::Wednesday, 5}));
+    assert( ymwd                   == year_month_weekday{local_days{ymwd}}); // round trip
+    }
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.sys_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.sys_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.sys_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.sys_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_weekday;
@@ -32,12 +31,64 @@
 
 int main()
 {
-    using year           = std::chrono::year;
-    using month          = std::chrono::month;
-    using day            = std::chrono::day;
-//  using sys_days     = std::chrono::sys_days;
+    using year               = std::chrono::year;
+    using days               = std::chrono::days;
+    using sys_days           = std::chrono::sys_days;
+    using weekday_indexed    = std::chrono::weekday_indexed;
     using year_month_weekday = std::chrono::year_month_weekday;
 
-//  ASSERT_NOEXCEPT(year_month_weekday{std::declval<const sys_days>()});
-    assert(false);
+    ASSERT_NOEXCEPT(year_month_weekday{std::declval<const sys_days>()});
+
+    {
+    constexpr sys_days sd{}; // 1-Jan-1970 was a Thursday
+    constexpr year_month_weekday ymwd{sd};
+
+    static_assert( ymwd.ok(),                                                            "");
+    static_assert( ymwd.year()            == year{1970},                                 "");
+    static_assert( ymwd.month()           == std::chrono::January,                       "");
+    static_assert( ymwd.weekday()         == std::chrono::Thursday,                      "");
+    static_assert( ymwd.index()           == 1,                                          "");
+    static_assert( ymwd.weekday_indexed() == weekday_indexed{std::chrono::Thursday, 1},  "");
+    static_assert( ymwd                   == year_month_weekday{sys_days{ymwd}},         ""); // round trip
+    }
+
+    {
+    constexpr sys_days sd{days{10957+32}}; // 2-Feb-2000 was a Wednesday
+    constexpr year_month_weekday ymwd{sd};
+
+    static_assert( ymwd.ok(),                                                            "");
+    static_assert( ymwd.year()            == year{2000},                                 "");
+    static_assert( ymwd.month()           == std::chrono::February,                      "");
+    static_assert( ymwd.weekday()         == std::chrono::Wednesday,                     "");
+    static_assert( ymwd.index()           == 1,                                          "");
+    static_assert( ymwd.weekday_indexed() == weekday_indexed{std::chrono::Wednesday, 1}, "");
+    static_assert( ymwd                   == year_month_weekday{sys_days{ymwd}},         ""); // round trip
+    }
+
+
+    {
+    constexpr sys_days sd{days{-10957}}; // 2-Jan-1940 was a Tuesday
+    constexpr year_month_weekday ymwd{sd};
+
+    static_assert( ymwd.ok(),                                                            "");
+    static_assert( ymwd.year()            == year{1940},                                 "");
+    static_assert( ymwd.month()           == std::chrono::January,                       "");
+    static_assert( ymwd.weekday()         == std::chrono::Tuesday,                       "");
+    static_assert( ymwd.index()           == 1,                                          "");
+    static_assert( ymwd.weekday_indexed() == weekday_indexed{std::chrono::Tuesday, 1},   "");
+    static_assert( ymwd                   == year_month_weekday{sys_days{ymwd}},         ""); // round trip
+    }
+
+    {
+    sys_days sd{days{-(10957+34)}}; // 29-Nov-1939 was a Wednesday
+    year_month_weekday ymwd{sd};
+
+    assert( ymwd.ok());
+    assert( ymwd.year()            == year{1939});
+    assert( ymwd.month()           == std::chrono::November);
+    assert( ymwd.weekday()         == std::chrono::Wednesday);
+    assert( ymwd.index()           == 5);
+    assert((ymwd.weekday_indexed() == weekday_indexed{std::chrono::Wednesday, 5}));
+    assert( ymwd                   == year_month_weekday{sys_days{ymwd}}); // round trip
+    }
 }

Removed: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.year_month_day_last.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.year_month_day_last.pass.cpp?rev=350928&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.year_month_day_last.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/ctor.year_month_day_last.pass.cpp (removed)
@@ -1,41 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
-
-// <chrono>
-// class year_month_weekday;
-
-//  constexpr year_month_weekday(const year_month_weekday_last& ymdl) noexcept;
-//
-//  Effects:  Constructs an object of type year_month_weekday by initializing
-//              y_ with ymdl.year(), m_ with ymdl.month(), and d_ with ymdl.day().
-//
-//  constexpr chrono::year   year() const noexcept;
-//  constexpr chrono::month month() const noexcept;
-//  constexpr chrono::day     day() const noexcept;
-//  constexpr bool             ok() const noexcept;
-
-#include <chrono>
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-int main()
-{
-    using year                = std::chrono::year;
-    using month               = std::chrono::month;
-    using day                 = std::chrono::day;
-    using year_month_weekday_last = std::chrono::year_month_weekday_last;
-    using year_month_weekday      = std::chrono::year_month_weekday;
-
-    ASSERT_NOEXCEPT(year_month_weekday{std::declval<const year_month_weekday_last>()});
-
-}

Added: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.local_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.local_days.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.local_days.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.local_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+// class year_month_weekday;
+
+// explicit constexpr operator local_days() const noexcept;
+//
+// Returns: If y_.ok() && m_.ok() && wdi_.weekday().ok(), returns a
+//    sys_days that represents the date (index() - 1) * 7 days after the first
+//    weekday() of year()/month(). If index() is 0 the returned sys_days
+//    represents the date 7 days prior to the first weekday() of
+//    year()/month(). Otherwise the returned value is unspecified.
+//
+
+#include <chrono>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+    using year               = std::chrono::year;
+    using month              = std::chrono::month;
+    using weekday_indexed    = std::chrono::weekday_indexed;
+    using local_days         = std::chrono::local_days;
+    using days               = std::chrono::days;
+    using year_month_weekday = std::chrono::year_month_weekday;
+
+    ASSERT_NOEXCEPT(local_days(std::declval<year_month_weekday>()));
+
+    {
+    constexpr year_month_weekday ymwd{year{1970}, month{1}, weekday_indexed{std::chrono::Thursday, 1}};
+    constexpr local_days sd{ymwd};
+
+    static_assert( sd.time_since_epoch() == days{0}, "");
+    static_assert( year_month_weekday{sd} == ymwd, ""); // and back
+    }
+
+    {
+    constexpr year_month_weekday ymwd{year{2000}, month{2}, weekday_indexed{std::chrono::Wednesday, 1}};
+    constexpr local_days sd{ymwd};
+
+    static_assert( sd.time_since_epoch() == days{10957+32}, "");
+    static_assert( year_month_weekday{sd} == ymwd, ""); // and back
+    }
+
+//  There's one more leap day between 1/1/40 and 1/1/70
+//  when compared to 1/1/70 -> 1/1/2000
+    {
+    constexpr year_month_weekday ymwd{year{1940}, month{1},weekday_indexed{std::chrono::Tuesday, 1}};
+    constexpr local_days sd{ymwd};
+
+    static_assert( sd.time_since_epoch() == days{-10957}, "");
+    static_assert( year_month_weekday{sd} == ymwd, ""); // and back
+    }
+
+    {
+    year_month_weekday ymwd{year{1939}, month{11}, weekday_indexed{std::chrono::Wednesday, 5}};
+    local_days sd{ymwd};
+
+    assert( sd.time_since_epoch() == days{-(10957+34)});
+    assert( year_month_weekday{sd} == ymwd); // and back
+    }
+
+}

Added: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.sys_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.sys_days.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.sys_days.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwd/time.cal.ymwd.members/op.sys_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+// class year_month_weekday;
+
+// constexpr operator sys_days() const noexcept;
+//
+// Returns: If y_.ok() && m_.ok() && wdi_.weekday().ok(), returns a
+//    sys_days that represents the date (index() - 1) * 7 days after the first
+//    weekday() of year()/month(). If index() is 0 the returned sys_days
+//    represents the date 7 days prior to the first weekday() of
+//    year()/month(). Otherwise the returned value is unspecified.
+//
+
+#include <chrono>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+    using year               = std::chrono::year;
+    using month              = std::chrono::month;
+    using weekday_indexed    = std::chrono::weekday_indexed;
+    using sys_days           = std::chrono::sys_days;
+    using days               = std::chrono::days;
+    using year_month_weekday = std::chrono::year_month_weekday;
+
+    ASSERT_NOEXCEPT(sys_days(std::declval<year_month_weekday>()));
+
+    {
+    constexpr year_month_weekday ymwd{year{1970}, month{1}, weekday_indexed{std::chrono::Thursday, 1}};
+    constexpr sys_days sd{ymwd};
+
+    static_assert( sd.time_since_epoch() == days{0}, "");
+    static_assert( year_month_weekday{sd} == ymwd, ""); // and back
+    }
+
+    {
+    constexpr year_month_weekday ymwd{year{2000}, month{2}, weekday_indexed{std::chrono::Wednesday, 1}};
+    constexpr sys_days sd{ymwd};
+
+    static_assert( sd.time_since_epoch() == days{10957+32}, "");
+    static_assert( year_month_weekday{sd} == ymwd, ""); // and back
+    }
+
+//  There's one more leap day between 1/1/40 and 1/1/70
+//  when compared to 1/1/70 -> 1/1/2000
+    {
+    constexpr year_month_weekday ymwd{year{1940}, month{1},weekday_indexed{std::chrono::Tuesday, 1}};
+    constexpr sys_days sd{ymwd};
+
+    static_assert( sd.time_since_epoch() == days{-10957}, "");
+    static_assert( year_month_weekday{sd} == ymwd, ""); // and back
+    }
+
+    {
+    year_month_weekday ymwd{year{1939}, month{11}, weekday_indexed{std::chrono::Wednesday, 5}};
+    sys_days sd{ymwd};
+
+    assert( sd.time_since_epoch() == days{-(10957+34)});
+    assert( year_month_weekday{sd} == ymwd); // and back
+    }
+
+}

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_local_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_local_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_local_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_local_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
 // class year_month_day_last;
@@ -24,12 +23,39 @@
 int main()
 {
     using year                = std::chrono::year;
-    using month               = std::chrono::month;
-    using day                 = std::chrono::day;
     using month_day_last      = std::chrono::month_day_last;
     using year_month_day_last = std::chrono::year_month_day_last;
-    using sys_days            = std::chrono::local_days;
+    using local_days          = std::chrono::local_days;
+    using days                = std::chrono::days;
 
-    ASSERT_NOEXCEPT(                static_cast<local_days>(std::declval<const year_month_day_last>().year()));
-    ASSERT_SAME_TYPE(year, decltype(static_cast<local_days>(std::declval<const year_month_day_last>().year()));
+    ASSERT_NOEXCEPT(                      static_cast<local_days>(std::declval<const year_month_day_last>()));
+    ASSERT_SAME_TYPE(local_days, decltype(static_cast<local_days>(std::declval<const year_month_day_last>())));
+
+    { // Last day in Jan 1970 was the 31st
+    constexpr year_month_day_last ymdl{year{1970}, month_day_last{std::chrono::January}};
+    constexpr local_days sd{ymdl};
+    
+    static_assert(sd.time_since_epoch() == days{30}, "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{2000}, month_day_last{std::chrono::January}};
+    constexpr local_days sd{ymdl};
+
+    static_assert(sd.time_since_epoch() == days{10957+30}, "");
+    }
+
+    {
+    constexpr year_month_day_last ymdl{year{1940}, month_day_last{std::chrono::January}};
+    constexpr local_days sd{ymdl};
+
+    static_assert(sd.time_since_epoch() == days{-10957+29}, "");
+    }
+
+    {
+    year_month_day_last ymdl{year{1939}, month_day_last{std::chrono::November}};
+    local_days sd{ymdl};
+
+    assert(sd.time_since_epoch() == days{-(10957+33)});
+    }
 }

Modified: libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_sys_days.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_sys_days.pass.cpp?rev=350929&r1=350928&r2=350929&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_sys_days.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.members/op_sys_days.pass.cpp Fri Jan 11 07:12:04 2019
@@ -7,13 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// XFAIL: *
 
 // <chrono>
-// class year_month_day_last;
+// class year_month_weekday_last;
 
 // constexpr operator sys_days() const noexcept;
-//  Returns: sys_days{year()/month()/day()}.
+//  Returns: If ok() == true, returns a sys_days that represents the last weekday() 
+//             of year()/month(). Otherwise the returned value is unspecified.
 
 #include <chrono>
 #include <type_traits>
@@ -21,16 +21,49 @@
 
 #include "test_macros.h"
 
+#include <iostream>
+
 int main()
 {
-    using year                = std::chrono::year;
-    using month               = std::chrono::month;
-    using day                 = std::chrono::day;
-    using month_day_last      = std::chrono::month_day_last;
-    using year_month_day_last = std::chrono::year_month_day_last;
-    using sys_days            = std::chrono::sys_days;
-
-    ASSERT_NOEXCEPT(                static_cast<sys_days>(std::declval<const year_month_day_last>().year()));
-    ASSERT_SAME_TYPE(year, decltype(static_cast<sys_days>(std::declval<const year_month_day_last>().year()));
+    using year                    = std::chrono::year;
+    using month                   = std::chrono::month;
+    using year_month_weekday_last = std::chrono::year_month_weekday_last;
+    using sys_days                = std::chrono::sys_days;
+    using days                    = std::chrono::days;
+    using weekday                 = std::chrono::weekday;
+    using weekday_last            = std::chrono::weekday_last;
+
+    ASSERT_NOEXCEPT(                    static_cast<sys_days>(std::declval<const year_month_weekday_last>()));
+    ASSERT_SAME_TYPE(sys_days, decltype(static_cast<sys_days>(std::declval<const year_month_weekday_last>())));
+
+    constexpr month   January = std::chrono::January;
+    constexpr weekday Tuesday = std::chrono::Tuesday;
+
+    { // Last Tuesday in Jan 1970 was the 27th
+    constexpr year_month_weekday_last ymwdl{year{1970}, January, weekday_last{Tuesday}};
+    constexpr sys_days sd{ymwdl};
+    
+    static_assert(sd.time_since_epoch() == days{26}, "");
+    }
+
+    { // Last Tuesday in Jan 2000 was the 25th
+    constexpr year_month_weekday_last ymwdl{year{2000}, January, weekday_last{Tuesday}};
+    constexpr sys_days sd{ymwdl};
+    
+    static_assert(sd.time_since_epoch() == days{10957+24}, "");
+    }
+
+    { // Last Tuesday in Jan 1940 was the 30th
+    constexpr year_month_weekday_last ymwdl{year{1940}, January, weekday_last{Tuesday}};
+    constexpr sys_days sd{ymwdl};
+    
+    static_assert(sd.time_since_epoch() == days{-10958+29}, "");
+    }
+
+    { // Last Tuesday in Nov 1939 was the 28th
+    year_month_weekday_last ymdl{year{1939}, std::chrono::November, weekday_last{Tuesday}};
+    sys_days sd{ymdl};
 
+    assert(sd.time_since_epoch() == days{-(10957+35)});
+    }
 }

Added: libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/local_time.types.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/local_time.types.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/local_time.types.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/local_time.types.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+
+// struct local_t {};
+// template<class Duration>
+//   using local_time  = time_point<system_clock, Duration>;
+// using local_seconds = sys_time<seconds>;
+// using local_days    = sys_time<days>;
+
+// [Example: 
+//   sys_seconds{sys_days{1970y/January/1}}.time_since_epoch() is 0s. 
+//   sys_seconds{sys_days{2000y/January/1}}.time_since_epoch() is 946’684’800s, which is 10’957 * 86’400s.
+// —end example]
+
+
+#include <chrono>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+    using local_t = std::chrono::local_t;
+    using year    = std::chrono::year;
+
+    using seconds = std::chrono::seconds;
+    using minutes = std::chrono::minutes;
+    using days    = std::chrono::days;
+    
+    using local_seconds = std::chrono::local_seconds;
+    using local_minutes = std::chrono::local_time<minutes>;
+    using local_days    = std::chrono::local_days;
+
+    constexpr std::chrono::month January = std::chrono::January;
+
+    ASSERT_SAME_TYPE(std::chrono::local_time<seconds>, local_seconds);
+    ASSERT_SAME_TYPE(std::chrono::local_time<days>,    local_days);
+
+//  Test the long form, too
+    ASSERT_SAME_TYPE(std::chrono::time_point<local_t, seconds>, local_seconds);
+    ASSERT_SAME_TYPE(std::chrono::time_point<local_t, minutes>, local_minutes);
+    ASSERT_SAME_TYPE(std::chrono::time_point<local_t, days>,    local_days);
+    
+//  Test some well known values
+    local_days d0 = local_days{year{1970}/January/1};
+    local_days d1 = local_days{year{2000}/January/1};
+    ASSERT_SAME_TYPE(decltype(d0.time_since_epoch()), days);
+    assert( d0.time_since_epoch().count() == 0);
+    assert( d1.time_since_epoch().count() == 10957);
+
+    local_seconds s0{d0};
+    local_seconds s1{d1};
+    ASSERT_SAME_TYPE(decltype(s0.time_since_epoch()), seconds);
+    assert( s0.time_since_epoch().count() == 0);
+    assert( s1.time_since_epoch().count() == 946684800L);
+}

Added: libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/sys.time.types.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/sys.time.types.pass.cpp?rev=350929&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/sys.time.types.pass.cpp (added)
+++ libcxx/trunk/test/std/utilities/time/time.clock/time.clock.system/sys.time.types.pass.cpp Fri Jan 11 07:12:04 2019
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <chrono>
+
+// template<class Duration>
+//   using sys_time  = time_point<system_clock, Duration>;
+// using sys_seconds = sys_time<seconds>;
+// using sys_days    = sys_time<days>;
+
+// [Example: 
+//   sys_seconds{sys_days{1970y/January/1}}.time_since_epoch() is 0s. 
+//   sys_seconds{sys_days{2000y/January/1}}.time_since_epoch() is 946’684’800s, which is 10’957 * 86’400s.
+// —end example]
+
+
+#include <chrono>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+    using system_clock = std::chrono::system_clock;
+    using year         = std::chrono::year;
+
+    using seconds = std::chrono::seconds;
+    using minutes = std::chrono::minutes;
+    using days    = std::chrono::days;
+    
+    using sys_seconds = std::chrono::sys_seconds;
+    using sys_minutes = std::chrono::sys_time<minutes>;
+    using sys_days    = std::chrono::sys_days;
+
+    constexpr std::chrono::month January = std::chrono::January;
+
+    ASSERT_SAME_TYPE(std::chrono::sys_time<seconds>, sys_seconds);
+    ASSERT_SAME_TYPE(std::chrono::sys_time<days>,    sys_days);
+
+//  Test the long form, too
+    ASSERT_SAME_TYPE(std::chrono::time_point<system_clock, seconds>, sys_seconds);
+    ASSERT_SAME_TYPE(std::chrono::time_point<system_clock, minutes>, sys_minutes);
+    ASSERT_SAME_TYPE(std::chrono::time_point<system_clock, days>,    sys_days);
+    
+//  Test some well known values
+    sys_days d0 = sys_days{year{1970}/January/1};
+    sys_days d1 = sys_days{year{2000}/January/1};
+    ASSERT_SAME_TYPE(decltype(d0.time_since_epoch()), days);
+    assert( d0.time_since_epoch().count() == 0);
+    assert( d1.time_since_epoch().count() == 10957);
+
+    sys_seconds s0{d0};
+    sys_seconds s1{d1};
+    ASSERT_SAME_TYPE(decltype(s0.time_since_epoch()), seconds);
+    assert( s0.time_since_epoch().count() == 0);
+    assert( s1.time_since_epoch().count() == 946684800L);
+}




More information about the libcxx-commits mailing list