1 // The MIT License (MIT)
2 //
3 // Copyright (c) 2015, 2016 Howard Hinnant
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 // class weekday
24 // {
25 //     unsigned char wd_;
26 // public:
27 //     explicit constexpr weekday(unsigned wd) noexcept;
28 //     constexpr weekday(const sys_days& dp) noexcept;
29 //
30 //     weekday& operator++()    noexcept;
31 //     weekday  operator++(int) noexcept;
32 //     weekday& operator--()    noexcept;
33 //     weekday  operator--(int) noexcept;
34 //
35 //     weekday& operator+=(const days& d) noexcept;
36 //     weekday& operator-=(const days& d) noexcept;
37 //
38 //     constexpr explicit operator unsigned() const noexcept;
39 //     constexpr bool ok() const noexcept;
40 //
41 //     // tested with weekday_indexed
42 //     constexpr weekday_indexed operator[](unsigned index) const noexcept;
43 //     // tested with weekday_last
44 //     constexpr weekday_last    operator[](last_spec)      const noexcept;
45 // };
46 
47 // constexpr bool operator==(const weekday& x, const weekday& y) noexcept;
48 // constexpr bool operator!=(const weekday& x, const weekday& y) noexcept;
49 
50 // constexpr weekday operator+(const weekday& x, const days&    y) noexcept;
51 // constexpr weekday operator+(const days&    x, const weekday& y) noexcept;
52 // constexpr weekday operator-(const weekday& x, const days&    y) noexcept;
53 // constexpr days    operator-(const weekday& x, const weekday& y) noexcept;
54 
55 // std::ostream& operator<<(std::ostream& os, const weekday& wd);
56 
57 // constexpr weekday sun{0};
58 // constexpr weekday mon{1};
59 // constexpr weekday tue{2};
60 // constexpr weekday wed{3};
61 // constexpr weekday thu{4};
62 // constexpr weekday fri{5};
63 // constexpr weekday sat{6};
64 
65 #include "date.h"
66 
67 #include <cassert>
68 #include <sstream>
69 #include <type_traits>
70 
71 static_assert( std::is_trivially_destructible<date::weekday>{}, "");
72 static_assert( std::is_default_constructible<date::weekday>{}, "");
73 static_assert( std::is_trivially_copy_constructible<date::weekday>{}, "");
74 static_assert( std::is_trivially_copy_assignable<date::weekday>{}, "");
75 static_assert( std::is_trivially_move_constructible<date::weekday>{}, "");
76 static_assert( std::is_trivially_move_assignable<date::weekday>{}, "");
77 
78 static_assert( std::is_nothrow_constructible<date::weekday, unsigned>{}, "");
79 static_assert( std::is_nothrow_constructible<date::weekday, date::sys_days>{}, "");
80 static_assert(!std::is_convertible<unsigned, date::weekday>{}, "");
81 static_assert( std::is_convertible<date::sys_days, date::weekday>{}, "");
82 static_assert(!std::is_convertible<date::weekday, unsigned>{}, "");
83 
84 static_assert( date::weekday{0u}.ok(), "");
85 static_assert( date::weekday{1u}.ok(), "");
86 static_assert( date::weekday{2u}.ok(), "");
87 static_assert( date::weekday{3u}.ok(), "");
88 static_assert( date::weekday{4u}.ok(), "");
89 static_assert( date::weekday{5u}.ok(), "");
90 static_assert( date::weekday{6u}.ok(), "");
91 static_assert( date::weekday{7u}.ok(), "");
92 static_assert(!date::weekday{8u}.ok(), "");
93 
94 void
test_weekday_arithmetic()95 test_weekday_arithmetic()
96 {
97     using namespace date;
98     constexpr unsigned a[7][7] =
99     {// -    Sun Mon Tue Wed Thu Fri Sat
100      /*Sun*/ {0,  6,  5,  4,  3,  2,  1},
101      /*Mon*/ {1,  0,  6,  5,  4,  3,  2},
102      /*Tue*/ {2,  1,  0,  6,  5,  4,  3},
103      /*Wed*/ {3,  2,  1,  0,  6,  5,  4},
104      /*Thu*/ {4,  3,  2,  1,  0,  6,  5},
105      /*Fri*/ {5,  4,  3,  2,  1,  0,  6},
106      /*Sat*/ {6,  5,  4,  3,  2,  1,  0}
107     };
108     for (unsigned x = 0; x < 7; ++x)
109     {
110         for (unsigned y = 0; y < 7; ++y)
111         {
112             assert(weekday{x} - weekday{y} == days{a[x][y]});
113             assert(weekday{x} - days{a[x][y]} == weekday{y});
114             assert(weekday{x} == weekday{y} + days{a[x][y]});
115             assert(weekday{x} == days{a[x][y]} + weekday{y});
116         }
117     }
118     for (unsigned x = 0; x < 7; ++x)
119     {
120         for (int y = -21; y < 21; ++y)
121         {
122             weekday wx{x};
123             days dy{y};
124             wx += dy;
125             weekday wz = weekday{x} + days{y};
126             assert(wx.ok());
127             assert(wz.ok());
128             assert(wx == wz);
129             assert(wx - weekday{x} == days{y % 7 + (y % 7 < 0 ? 7 : 0)});
130         }
131     }
132     for (unsigned x = 0; x < 7; ++x)
133     {
134         for (int y = -21; y < 21; ++y)
135         {
136             weekday wx{x};
137             days dy{y};
138             wx -= dy;
139             assert(wx == weekday{x} + days{-y});
140         }
141     }
142     for (unsigned x = 0; x < 7; ++x)
143     {
144         weekday wx{x};
145         assert(++wx - weekday{x} == days{1});
146         assert(wx++ - weekday{x} == days{1});
147         assert(wx - weekday{x} == days{2});
148         assert(wx-- - weekday{x} == days{2});
149         assert(wx - weekday{x} == days{1});
150         assert(--wx - weekday{x} == days{0});
151     }
152 }
153 
154 int
main()155 main()
156 {
157     using namespace date;
158 
159     static_assert(sun == weekday{0u}, "");
160     static_assert(mon == weekday{1u}, "");
161     static_assert(tue == weekday{2u}, "");
162     static_assert(wed == weekday{3u}, "");
163     static_assert(thu == weekday{4u}, "");
164     static_assert(fri == weekday{5u}, "");
165     static_assert(sat == weekday{6u}, "");
166 
167     static_assert(!(sun != sun), "");
168     static_assert(  sun != mon, "");
169     static_assert(  mon != sun, "");
170 
171     test_weekday_arithmetic();
172 
173     std::ostringstream os;
174 
175     os << sun;
176     assert(os.str() == "Sun");
177     os.str("");
178 
179     os << mon;
180     assert(os.str() == "Mon");
181     os.str("");
182 
183     os << tue;
184     assert(os.str() == "Tue");
185     os.str("");
186 
187     os << wed;
188     assert(os.str() == "Wed");
189     os.str("");
190 
191     os << thu;
192     assert(os.str() == "Thu");
193     os.str("");
194 
195     os << fri;
196     assert(os.str() == "Fri");
197     os.str("");
198 
199     os << sat;
200     assert(os.str() == "Sat");
201 }
202