1 /* Copyright (c) 2002,2003 CrystalClear Software, Inc.
2  * Use, modification and distribution is subject to the
3  * Boost Software License, Version 1.0. (See accompanying
4  * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5  * Author: Jeff Garland, Bart Garst
6  */
7 
8 #include <boost/cstdint.hpp>
9 #include "boost/date_time/gregorian/gregorian.hpp"
10 #include "../testfrmwk.hpp"
11 #include <iostream>
12 #include <sstream>
13 
test_yearlimit(int yr,bool allowed)14 void test_yearlimit(int yr, bool allowed)
15 {
16     std::stringstream sdesc;
17     sdesc << "should" << (allowed ? "" : " not") << " be able to make a date in year " << yr;
18 
19     try {
20         boost::gregorian::date chkyr(yr, 1, 1);
21         check(sdesc.str(), allowed);
22     }
23     catch (std::out_of_range&) { check(sdesc.str(), !allowed); }
24 }
25 
26 int
main()27 main()
28 {
29 
30   using namespace boost::gregorian;
31 
32   //various constructors
33 #if !defined(DATE_TIME_NO_DEFAULT_CONSTRUCTOR)
34   date def;
35   check("Default constructor", def == date(not_a_date_time));
36 #endif
37 
38 #ifdef BOOST_NO_CXX14_CONSTEXPR
39   check("constexpr not configured", true);
40 #else
41   //check constexpr case
42   {
43     constexpr date d1(1900,1,1);
44     static_assert(d1.day() == 1,     "constexpr construction day()");
45     static_assert(d1.month() == 1,   "constexpr construction month()");
46     static_assert(d1.year() == 1900, "constexpr construction year()");
47     constexpr date d2 = date(2000,12,31);
48     constexpr date d3(d2);
49     static_assert(d3.day() == 31,      "constexpr construct and copy day()");
50     static_assert(d3.month() == 12,    "constexpr construct and copy month()");
51     static_assert(d3.year() == 2000,   "constexpr construct and copy year()");
52     check("constexpr tests compiled", true);
53   }
54 #endif
55 
56 
57   date d1(1900,1,1);
58   date d2 = date(2000,1,1);
59   date d3(d2);
60   check("Copy constructor", d3 == d2);
61   date d4(2000,12,31);
62   date d4a(2000,Dec,31);
63   //d4a.print(std::cout); std::cout << std::endl;
64   check("month_rep constructor",   d4 == d4a);
65   //std::cout << d3 << std::endl;
66   //retrieval functions
67   check_equal("1900-01-01 day is 01",     d1.day(),   1);
68   check_equal("1900-01-01 month is 01",   d1.month(), 1);
69   check_equal("1900-01-01 year is 1900",  d1.year(),  1900);
70   check_equal("2000-12-31 day is 31",     d4.day(),   31);
71   check_equal("2000-12-31 month is 12",   d4.month(), 12);
72   check_equal("2000-12-31 year is 2000",  d4.year(),  2000);
73   //operator<
74   check("1900-01-01 is less than 2000-01-01",          d1 < d2);
75   check("2000-01-01 is NOT less than 2000-01-01",      !(d1 < d1));
76   //operator<=
77   check("2000-01-01 is less equal than 2000-01-01",    d1 <= d1);
78   //operator>
79   check("2000-01-01 is greater than 1900-01-01",       d2 > d1);
80   check("2000-01-01 is NOT greater than 2000-01-01",   !(d1 < d1));
81   //operator>=
82   check("2000-01-01 is greater equal than 2000-01-01", d1 >= d1);
83   //operator!=
84   check("2000-01-01 is NOT equal to 1900-01-01",       d2 != d1);
85   //operator==
86   check_equal("2000-01-01 is equal 2000-01-01",        d3,   d2);
87   check("2000-01-01 is greater equal 2000-01-01",      d3 >= d2);
88   check("2000-01-01 is greater equal 2000-01-01",      d3 <= d2);
89 
90   date::ymd_type ymd = d1.year_month_day();
91   check_equal("ymd year",  ymd.year,  1900);
92   check_equal("ymd month", ymd.month, 1);
93   check_equal("ymd day",   ymd.day,   1);
94 
95   //The max function will not compile with Borland 5.5
96   //Complains about must specialize basic_data<limits> ???
97 //   std::cout << "Max date is " << (date::max)() << std::endl;
98 //   //std::cout << "Max date is " << (basic_date< date_limits<unsigned int,1900> >::max)() << std::endl;
99 //   //std::cout << "Max date is " << (date_limits<unsigned int, 1900>::max)() << std::endl;
100 
101   const date answers[] = {date(1900,Jan,1),date(1900,Jan,4),date(1900,Jan,7),
102                           date(1900,Jan,10),date(1900,Jan,13)};
103   date_duration off(3);
104   date d5(1900,1,1);
105   for (int i=0; i < 5; ++i) {
106     //std::cout << d5 << "  ";
107     check(" addition ", d5 == answers[i]);
108     d5 = d5 + off;
109   }
110   std::cout << std::endl;
111 
112    const date answers1[] = {date(2000,2,26),date(2000,2,28),date(2000,Mar,1)};
113    date d8(2000,Feb,26);
114    for (int j=0; j < 3; ++j) {
115      //std::cout << d8 << "  ";
116      check(" more addition ", d8 == answers1[j]);
117      d8 = d8 + days(2);
118    }
119    // std::cout << std::endl;
120 
121   date d6(2000,2,28);
122   date d7(2000,3,1);
123   date_duration twoDays(2);
124   date_duration negtwoDays(-2);
125   date_duration zeroDays(0);
126   check_equal("2000-03-01 - 2000-02-28 == 2 days",   twoDays,     (d7-d6));
127   check_equal("2000-02-28 - 2000-03-01 == - 2 days", negtwoDays,  (d6-d7));
128   check_equal("2000-02-28 - 2000-02-28 == 0 days",   zeroDays,    (d6-d6));
129   check_equal("2000-02-28 + 2 days == 2000-03-01 ",  d6 + twoDays, d7);
130   check_equal("2000-03-01 - 2 days == 2000-02-28 ",  d7 - twoDays, d6);
131   check_equal("Add duration to date", date(1999,1,1) + date_duration(365), date(2000,1,1));
132   check_equal("Add zero days", date(1999,1,1) + zeroDays, date(1999,1,1));
133   //can't do this...
134   //check("Add date to duration", date_duration(365) + date(1999,1,1) == date(2000,1,1));
135 
136   {
137     date d(2003,Oct,31);
138     date_duration dd(55);
139     d += dd;
140     check("date += date_duration", d == date(2003,Dec,25));
141     d -= dd;
142     check("date -= date_duration", d == date(2003,Oct,31));
143     /* special_values is more thoroughly tested later,
144      * this is just a test of += & -= with special values */
145     d += date_duration(pos_infin);
146     check("date += inf_dur", d == date(pos_infin));
147     d -= dd;
148     check("inf_date -= dur", d == date(pos_infin));
149   }
150   {
151     date d(2003,Oct,31);
152     date_duration dd1(pos_infin), dd2(neg_infin), dd3(not_a_date_time);
153     check_equal("date + inf_dur", d + dd1, date(pos_infin));
154     check_equal("date + inf_dur", d + dd2, date(neg_infin));
155     check_equal("date + nan_dur", d + dd3, date(not_a_date_time));
156     check_equal("date - inf_dur", d - dd1, date(neg_infin));
157     check_equal("date - inf_dur", d - dd2, date(pos_infin));
158     check_equal("date - nan_dur", d - dd3, date(not_a_date_time));
159     check_equal("inf_date + inf_dur", date(pos_infin) + dd1, date(pos_infin));
160     check_equal("inf_date - inf_dur", date(pos_infin) - dd1, date(not_a_date_time));
161     check_equal("inf_date + inf_dur", date(neg_infin) + dd1, date(not_a_date_time));
162     check_equal("inf_date - inf_dur", date(neg_infin) - dd1, date(neg_infin));
163   }
164 
165 
166   try {
167     date d9(2000, Jan, 32);
168     check("day out of range", false);
169     //never reached if working -- but stops compiler warnings :-)
170     std::cout << "Oops: " << to_iso_string(d9) << std::endl;
171   }
172   catch (bad_day_of_month&) {
173     check("day out of range", true);
174   }
175   try {
176     date d9(2000, Jan, 0);
177     check("day out of range", false);
178     //never reached if working -- but stops compiler warnings :-)
179     std::cout << "Oops: " << to_iso_string(d9) << std::endl;
180   }
181   catch (bad_day_of_month&) {
182     check("day out of range", true);
183   }
184 
185   try {
186     date d20(2000, Feb, 31);
187     check("day out of range", false);
188     //never reached if working -- but stops compiler warnings :-)
189     std::cout << "Oops: " << to_iso_string(d20) << std::endl;
190   }
191   catch (bad_day_of_month&) {
192     check("day out of range", true);
193   }
194 
195   //more subtle -- one day past in a leap year
196   try {
197     date d21(2000, Feb, 30);
198     check("day out of range", false);
199     //never reached if working -- but stops compiler warnings :-)
200     std::cout << "Oops: " << to_iso_string(d21) << std::endl;
201   }
202   catch (bad_day_of_month&) {
203     check("day out of range", true);
204   }
205 
206   //more subtle -- one day past in a leap year
207   try {
208     date d22(2000, Feb, 29);
209     check("last day of month ok", true);
210     std::cout << to_iso_string(d22) << std::endl; //stop compiler warning
211   }
212   catch (bad_day_of_month&) {
213     check("last day of month -- oops bad exception", false);
214   }
215 
216   //Not a leap year -- now Feb 29 is bad
217   try {
218     date d23(1999, Feb, 29);
219     check("day out of range", false);
220     //never reached if working -- but stops compiler warnings :-)
221     std::cout << "Oops: " << to_iso_string(d23) << std::endl;
222   }
223   catch (bad_day_of_month&) {
224     check("day out of range", true);
225   }
226 
227   //check out some special values
228   check("check not a date - false",           !d7.is_not_a_date());
229   check("check positive infinity - false",    !d7.is_pos_infinity());
230   check("check negative infinity - false",    !d7.is_neg_infinity());
231 
232   date d10(neg_infin);
233   check("check negative infinity - true",     d10.is_infinity());
234   d10 = d10 + twoDays; //still neg infinity
235   check("check negative infinity - true",     d10.is_neg_infinity());
236 
237   date d11(pos_infin);
238   check("check positive infinity - true",     d11.is_infinity());
239   d11 = d11 + twoDays;
240   check("check positive infinity add - true", d11.is_pos_infinity());
241 
242   date d12(not_a_date_time);
243   check("check not a date",                   d12.is_not_a_date());
244   check("check infinity compare   ",          d10 != d11);
245   check("check infinity compare   ",          d10 < d11);
246   check("check infinity nad compare   ",      d12 != d11);
247   date d13(max_date_time);
248   check("check infinity - max compare   ",      d13 < d11);
249   check_equal("max date_time value   ",       d13, date(9999,Dec, 31));
250   std::cout << to_simple_string(d13) << std::endl;
251   date d14(min_date_time);
252   check("check infinity - min compare   ",      d14 > d10);
253   std::cout << to_simple_string(d14) << std::endl;
254   check_equal("min date_time value   ",      d14, date(1400,Jan, 1));
255 
256 
257   date d15(1400,1,1);
258   std::cout << d15.day_of_week().as_long_string() << std::endl;
259   check("check infinity - min compare   ",      d10 < d15);
260 
261   // most of this testing is in the gregorian_calendar tests
262   std::cout << d15.julian_day() << std::endl;
263   check_equal("check julian day   ", d15.julian_day(),
264       static_cast<boost::uint32_t>(2232400));
265   check_equal("check modjulian day   ", d15.modjulian_day(), -167601);
266   date d16(2004,2,29);
267   check_equal("check julian day   ", d16.julian_day(),
268       static_cast<boost::uint32_t>(2453065));
269   check_equal("check modjulian day   ", d16.modjulian_day(),
270       static_cast<boost::uint32_t>(53064));
271 
272   // most of this testing is in the gregorian_calendar tests
273   date d31(2000, Jun, 1);
274   check_equal("check iso week number   ", d31.week_number(), 22);
275   date d32(2000, Aug, 1);
276   check_equal("check iso week number   ", d32.week_number(), 31);
277   date d33(2000, Oct, 1);
278   check_equal("check iso week number   ", d33.week_number(), 39);
279   date d34(2000, Dec, 1);
280   check_equal("check iso week number   ", d34.week_number(), 48);
281   date d35(2000, Dec, 24);
282   check_equal("check iso week number   ", d35.week_number(), 51);
283   date d36(2000, Dec, 25);
284   check_equal("check iso week number   ", d36.week_number(), 52);
285   date d37(2000, Dec, 31);
286   check_equal("check iso week number   ", d37.week_number(), 52);
287   date d38(2001, Jan, 1);
288   check_equal("check iso week number   ", d38.week_number(), 1);
289 
290   try {
291     int dayofyear1 = d38.day_of_year();
292     check_equal("check day of year number", dayofyear1, 1);
293     check_equal("check day of year number", d37.day_of_year(), 366);
294     date d39(2001,Dec,31);
295     check_equal("check day of year number", d39.day_of_year(), 365);
296     date d40(2000,Feb,29);
297     check_equal("check day of year number", d40.day_of_year(), 60);
298     date d41(1400,Jan,1);
299     check_equal("check day of year number", d41.day_of_year(), 1);
300     date d42(1400,Jan,1);
301     check_equal("check day of year number", d42.day_of_year(), 1);
302     date d43(2002,Nov,17);
303     check_equal("check day of year number", d43.day_of_year(), 321);
304   }
305   catch(std::exception& e) {
306     std::cout << e.what() << std::endl;
307     check("check day of year number", false);
308   }
309 
310   //converts to date and back -- should get same result
311   check_equal("tm conversion functions 2000-1-1", date_from_tm(to_tm(d2)), d2);
312   check_equal("tm conversion functions 1900-1-1", date_from_tm(to_tm(d1)), d1);
313   check_equal("tm conversion functions min date 1400-1-1 ", date_from_tm(to_tm(d14)), d14);
314   check_equal("tm conversion functions max date 9999-12-31", date_from_tm(to_tm(d13)), d13);
315 
316   try{
317     date d(neg_infin);
318     tm d_tm = to_tm(d);
319     check("Exception not thrown (special_value to_tm)", false);
320     std::cout << d_tm.tm_sec << std::endl; //does nothing useful but stops compiler from complaining about unused d_tm
321   }catch(std::out_of_range&){
322     check("Caught expected exception (special_value to_tm)", true);
323   }catch(...){
324     check("Caught un-expected exception (special_value to_tm)", false);
325   }
326 
327   // trac-13159
328   test_yearlimit(    0, false);
329   test_yearlimit( 1399, false);
330   test_yearlimit( 1400,  true);
331   test_yearlimit( 1401,  true);
332   test_yearlimit( 9999,  true);
333   test_yearlimit(10000, false);
334   test_yearlimit(10001, false);
335 
336   return printTestStats();
337 }
338 
339