369 lines
12 KiB
C++
369 lines
12 KiB
C++
/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc.
|
|
* Use, modification and distribution is subject to the
|
|
* Boost Software License, Version 1.0. (See accompanying
|
|
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
|
* Author: Jeff Garland, Bart Garst
|
|
*/
|
|
|
|
#include "boost/date_time/gregorian/gregorian.hpp"
|
|
#include "../testfrmwk.hpp"
|
|
#include "boost/lexical_cast.hpp"
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
// missing or misspelled parts of date string tests
|
|
// 'output_str' will be overwritten with what() from caught exception
|
|
bool failure_tests(std::string date_spec,
|
|
std::string& output_str)
|
|
{
|
|
using namespace boost::gregorian;
|
|
bool result = false;
|
|
date d(not_a_date_time);
|
|
try {
|
|
d = from_simple_string(date_spec);
|
|
}
|
|
catch(bad_year& by){ // ex: "205-Jan-15"
|
|
result = true;
|
|
output_str = by.what();
|
|
}
|
|
catch(bad_month& bm){ // ex: "2005-Jsn-15"
|
|
result = true;
|
|
output_str = bm.what();
|
|
}
|
|
catch(bad_day_of_month& bd){ // ex: "2005-Jan-51"
|
|
result = true;
|
|
output_str = bd.what();
|
|
}
|
|
catch(...){
|
|
// test failed - unexpected exception, leave result set to false
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
|
|
|
|
// Examples from 8601
|
|
// Full date
|
|
// Extended CCYY-MM-DD
|
|
std::string s("2001-10-5");
|
|
|
|
//This one aborts gcc2.95.3 on mandrake 8.1 linux with
|
|
//bad lexical cast?
|
|
try {
|
|
boost::gregorian::date d(boost::gregorian::from_string(s));
|
|
check("check year", d.year() == 2001);
|
|
check("check month", d.month() == 10);
|
|
check("check day", d.day() == 5);
|
|
}
|
|
catch(std::exception& e) {
|
|
check("parse 2001-10-5", false);
|
|
std::cout << "Fail: " << e.what() << std::endl;
|
|
}
|
|
|
|
{
|
|
using namespace boost::gregorian;
|
|
// date objects from strings & strings to date objects
|
|
date d(2000, 2, 29);
|
|
date d2 = from_string("2000-2-29");
|
|
check("2000-2-29", d2 == d);
|
|
date d3 = from_string("2000-FEB-29");
|
|
check("2000-FEB-29 (uppercase)", d3 == d);
|
|
date d4 = from_string("2000-february-29");
|
|
check("2000-february-29 (lowercase)", d4 == d);
|
|
date d5 = from_string(to_simple_string(d));
|
|
check("date to string to date", d5 == d);
|
|
date d6 = from_string(to_iso_extended_string(d));
|
|
check("date to string to date", d6 == d);
|
|
date d7 = from_us_string("Feb-29-2000");
|
|
check("date from month-day-year string", d7 == d);
|
|
date d8 = from_uk_string("29-Feb-2000");
|
|
check("date from day-month-year string", d8 == d);
|
|
{
|
|
std::string sn("20050229"); // no Feb-29 in 2005
|
|
date dn(not_a_date_time);
|
|
try {
|
|
dn = date_from_iso_string(sn);
|
|
check("Expected exception not thrown: from ISO string (bad_day_of_month)", false);
|
|
std::cout << date_from_iso_string(sn) << std::endl;
|
|
}
|
|
catch(bad_day_of_month&) {
|
|
check("Caught expected exception: bad_day_of_month ", true);
|
|
}
|
|
catch(...) {
|
|
check("Caught unexpected exception", false);
|
|
}
|
|
/* not currently passing due to a bug in boost::offset_separator (reported 2005-Aug-02)
|
|
sn = "2005022"; // missing a digit
|
|
try {
|
|
d = date_from_iso_string(sn);
|
|
check("Expected exception not thrown: from ISO string (missing digit)", false);
|
|
std::cout << date_from_iso_string(sn) << std::endl;
|
|
}
|
|
catch(bad_day_of_month& e) {
|
|
check("Caught expected exception: bad_day_of_month ", true);
|
|
}
|
|
catch(...) {
|
|
check("Caught unexpected exception", false);
|
|
}
|
|
*/
|
|
sn = "20050228"; // now it's correct
|
|
dn = date_from_iso_string(sn);
|
|
check("from ISO string", date(2005,Feb,28) == dn);
|
|
}
|
|
|
|
date d9 = from_us_string(__DATE__);
|
|
std::cout << "Today's date: " << to_simple_string(d9) << std::endl;
|
|
date d10 = from_us_string("Feb 29, 2000");
|
|
std::cout << "With comma: " << to_simple_string(d10) << std::endl;
|
|
check("american date with comma: Feb 29, 2000 ", d10 == d);
|
|
|
|
date d11 = from_us_string("feb 29 2000");
|
|
check("american date with comma: feb 29 2000 ", d11 == d);
|
|
|
|
// test for missing or misspelled date spec components
|
|
std::string output_str("unexpected exception caught");
|
|
check("Year misspelled/out of range: " + output_str,
|
|
failure_tests("205-Jan-15", output_str));
|
|
output_str = "unexpected exception caught";
|
|
check("Month misspelled: " + output_str,
|
|
failure_tests("2005-Jsn-15", output_str));
|
|
output_str = "unexpected exception caught";
|
|
check("Day out of range: " + output_str,
|
|
failure_tests("2005-Jan-55", output_str));
|
|
output_str = "unexpected exception caught";
|
|
check("Missing month and day: " + output_str,
|
|
failure_tests("2005", output_str));
|
|
output_str = "unexpected exception caught";
|
|
check("Missing day: " + output_str,
|
|
failure_tests("2005-Jan", output_str));
|
|
|
|
|
|
#if defined(BOOST_DATE_TIME_NO_LOCALE) || defined(BOOST_NO_STD_ITERATOR_TRAITS) || !defined(USE_DATE_TIME_PRE_1_33_FACET_IO)
|
|
|
|
//TODO -- all these PRE_1_33 exclusions need to be removed. In the meantime, don't make
|
|
//this stuff fail.
|
|
#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO)
|
|
check("input streaming for date not available", false); // force a failure
|
|
#endif
|
|
#else
|
|
{
|
|
std::stringstream ss("2000-2-29");
|
|
ss >> d2;
|
|
check("2000-2-29 stream-in", d2 == d);
|
|
}
|
|
{
|
|
std::stringstream ss("2000-FEB-29");
|
|
ss >> d2;
|
|
//std::cout << d2 << std::endl;
|
|
check("2000-FEB-29 stream-in (uppercase)", d2 == d);
|
|
}
|
|
{
|
|
std::stringstream ss("2000-february-29");
|
|
ss >> d2;
|
|
check("2000-february-29 stream-in (lowercase)", d2 == d);
|
|
}
|
|
// the removed (3) tests require a stream manipulator for date_order
|
|
// and date_separator (not yet implemented)
|
|
/*{
|
|
std::stringstream ss("Feb-29-2000");
|
|
ss >> d2;
|
|
check("date from month-day-year string stream-in", d2 == d);
|
|
}
|
|
{
|
|
std::stringstream ss("29-Feb-2000");
|
|
ss >> d2;
|
|
check("date from day-month-year string stream-in", d2 == d);
|
|
}
|
|
{
|
|
std::stringstream ss("Feb 29, 2000");
|
|
ss >> d2;
|
|
check("american date with comma: Feb 29, 2000 stream-in", d2 == d);
|
|
}*/
|
|
#endif //BOOST_DATE_TIME_NO_LOCALE
|
|
|
|
|
|
|
|
// check proper range
|
|
d = date(2001, 1, 1);
|
|
d2 = from_string("2001-Jan-1");
|
|
d3 = from_string("2001-January-1");
|
|
check("January", d == d2);
|
|
check("January", d == d3);
|
|
d = date(2001, 12, 1);
|
|
d2 = from_string("2001-Dec-1");
|
|
d3 = from_string("2001-December-1");
|
|
check("December", d == d2);
|
|
check("December", d == d3);
|
|
#if defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
|
check("date from stream not available: no std iterator traits", false);
|
|
#else
|
|
// from stream
|
|
d = date(2000, 10, 31);
|
|
std::stringstream ss("");
|
|
ss << "2000-Oct-31 is Halloween 2k!";
|
|
std::istream_iterator<std::string> iter(ss), eos;
|
|
check("from stream - stringstream", d == from_stream(iter, eos));
|
|
#if !(defined(BOOST_NO_STD_WSTRING))
|
|
#if !(defined(BOOST_DATE_TIME_NO_WISTREAM_ITERATOR))
|
|
std::wstringstream ws;
|
|
ws << "2000-Oct-31 is Halloween 2k!";
|
|
std::istream_iterator<std::wstring, wchar_t> witer(ws), weos;
|
|
check("from stream - wstringstream", d == from_stream(witer, weos));
|
|
#endif // NO_WSTREAM_ITERATOR
|
|
#endif // BOOST_NO_WSTRING
|
|
char d2_string[] = {"2000-10-31 is Halloween 2k!"};
|
|
char* end = d2_string + sizeof(d2_string) - 1;
|
|
check("from stream - char[]", d == from_stream(d2_string, end));
|
|
|
|
std::string s1_string("2000-Oct-31 is Halloween 2k!");
|
|
std::string::iterator s1_start = s1_string.begin();
|
|
std::string::iterator s1_end = s1_string.end();
|
|
check("from stream - string", d == from_stream(s1_start, s1_end));
|
|
#ifndef BOOST_NO_STD_WSTRING
|
|
std::wstring w1_string(boost::lexical_cast<std::wstring>("2000-Oct-31 is Halloween 2k!"));
|
|
std::wstring::iterator w1_start = w1_string.begin();
|
|
std::wstring::iterator w1_end = w1_string.end();
|
|
check("from stream - wstring", d == from_stream(w1_start, w1_end));
|
|
#endif // BOOST_NO_STD_WSTRING
|
|
#endif // BOOST_NO_STD_ITERATOR_TRAITS
|
|
/* date objects from strings & strings to date objects
|
|
* with misspelled months */
|
|
try {
|
|
date bd = from_string("2002-Jull-4");
|
|
std::cout << "Shouldn't be reached." <<
|
|
boost::gregorian::to_simple_string(bd) << std::endl;
|
|
}
|
|
catch(boost::gregorian::bad_month&){
|
|
check("bad spelling 'Jull'", true);
|
|
}
|
|
catch(std::exception& e){
|
|
check("bad spelling", false);
|
|
std::cout << "Fail: " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
try {
|
|
std::string s2("2001-12-41"); //oops should be 31
|
|
boost::gregorian::date bad_day(boost::gregorian::from_string(s2)); //won't construct
|
|
check("check bad day", false);
|
|
//The line below won't execute, but make the compiler think
|
|
//we are using bad day....
|
|
std::cout << "Oh oh, this shouldn't be reached: "
|
|
<< boost::gregorian::to_iso_string(bad_day) << std::endl;
|
|
|
|
}
|
|
catch(boost::gregorian::bad_day_of_month&) { //expected
|
|
check("check bad day", true);
|
|
}
|
|
catch(std::exception& e) {
|
|
//oops wrong exception
|
|
check("check bad day", false);
|
|
std::cout << "Fail: " << e.what() << std::endl;
|
|
}
|
|
|
|
try {
|
|
std::string s2("2001-02-29"); //oops should be 28
|
|
boost::gregorian::date bad_day(boost::gregorian::from_string(s2)); //won't construct
|
|
check("check bad leap year", false);
|
|
//The line below won't execute, but make the compiler think
|
|
//we are using bad day....
|
|
std::cout << "Oh oh, this shouldn't be reached: "
|
|
<< boost::gregorian::to_iso_string(bad_day) << std::endl;
|
|
|
|
}
|
|
catch(boost::gregorian::bad_day_of_month&) { //expected
|
|
check("check bad leap year", true);
|
|
}
|
|
catch(std::exception& e) {
|
|
//oops wrong exception
|
|
check("check bad leap year", false);
|
|
std::cout << "Fail: " << e.what() << std::endl;
|
|
}
|
|
|
|
try {
|
|
std::string s2("2001-14-1"); //oops should be <= 12
|
|
boost::gregorian::date bad_month(boost::date_time::parse_date<boost::gregorian::date>(s2));
|
|
check("check bad month", false); //fail the test
|
|
//The line below won't execute, but make the compiler think
|
|
//we are using bad day....
|
|
std::cout << "Oh oh, this shouldn't be reached: "
|
|
<< boost::gregorian::to_iso_string(bad_month) << std::endl;
|
|
|
|
}
|
|
catch(boost::gregorian::bad_month&) { //expected
|
|
check("check bad month", true);
|
|
}
|
|
catch(std::exception& e) {
|
|
//oops wrong exception
|
|
check("check bad month", false);
|
|
std::cout << "Fail: " << e.what() << std::endl;
|
|
}
|
|
|
|
//This one aborts gcc2.95.3 on mandrake 8.1 linux with
|
|
//bad lexical cast?
|
|
try {
|
|
//Example of ISO Standard -- CCYYMMDD
|
|
using namespace boost::gregorian;
|
|
std::string ud("20011009"); //2001-Oct-09
|
|
date d1(boost::gregorian::from_undelimited_string(ud));
|
|
// std::cout << to_string(d1) << std::endl;
|
|
check("undelimited date string", d1 == date(2001,Oct,9));
|
|
|
|
|
|
std::string ad("2001/10/09");
|
|
date d2(boost::date_time::parse_date<date>(ad));
|
|
check("check american date", d2 == date(2001,Oct,9));
|
|
}
|
|
catch(std::exception& e) {
|
|
check("more parsing", false);
|
|
std::cout << "Fail: " << e.what() << std::endl;
|
|
}
|
|
|
|
using namespace boost::gregorian;
|
|
std::string s2("2003-07-28");
|
|
date d2(from_string(s2));
|
|
check("check date", d2.month() == 7 &&
|
|
d2.year() == 2003 &&
|
|
d2.day() == 28);
|
|
// std::string s1("2001-Oct-5");
|
|
// gregorian::date d1(parse_date<gregorian::date>(s1));
|
|
// check("check month", d1.month() == 10);
|
|
|
|
|
|
//Check that the from_string and to_string can be reversed
|
|
date d10(2003, 10, 19);
|
|
std::string d10s = to_simple_string(d10);
|
|
date d11 = from_simple_string(d10s);
|
|
check("to from string inversion", d10 == d11);
|
|
|
|
try {
|
|
using namespace boost::gregorian;
|
|
std::string ud(""); //empty string error sf bug# 1155556
|
|
date d1(from_simple_string(ud));
|
|
check("empty string", false); //should never reach this piont
|
|
(void)d1;
|
|
}
|
|
catch(std::exception& e) {
|
|
check(std::string("empty string parse (exception expected): ") + e.what(), true);
|
|
}
|
|
|
|
|
|
//Calendar Week + Day Number
|
|
// CCYYWwwDThhmmss
|
|
// 1986W105T
|
|
// week == 10 day=5
|
|
// see page 5
|
|
|
|
|
|
//Duration rep
|
|
//CCYYMMDDThhmmss/PnYnMnDTnHnMnS
|
|
|
|
return printTestStats();
|
|
|
|
}
|
|
|