| 1 | |
| 2 | /* Copyright (c) 2004 CrystalClear Software, Inc. |
| 3 | * Use, modification and distribution is subject to the |
| 4 | * Boost Software License, Version 1.0. (See accompanying |
| 5 | * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
| 6 | * Author: Jeff Garland |
| 7 | */ |
| 8 | |
| 9 | |
| 10 | #include "boost/date_time/gregorian/gregorian.hpp" |
| 11 | #include "../testfrmwk.hpp" |
| 12 | #include "boost/date_time/format_date_parser.hpp" |
| 13 | #include <sstream> |
| 14 | #include <algorithm> |
| 15 | #include <iostream> |
| 16 | |
| 17 | const wchar_t* const wmonth_short_names[]={L"Jan" ,L"Feb" ,L"Mar" , |
| 18 | L"Apr" ,L"May" ,L"Jun" , |
| 19 | L"Jul" ,L"Aug" ,L"Sep" , |
| 20 | L"Oct" ,L"Nov" ,L"Dec" }; |
| 21 | |
| 22 | const char* const month_short_names[]={"Jan" ,"Feb" ,"Mar" , |
| 23 | "Apr" ,"May" ,"Jun" , |
| 24 | "Jul" ,"Aug" ,"Sep" , |
| 25 | "Oct" ,"Nov" ,"Dec" }; |
| 26 | |
| 27 | const char* const month_long_names[]={"January" ,"February" ,"March" , |
| 28 | "April" ,"May" ,"June" , |
| 29 | "July" ,"August" ,"September" , |
| 30 | "October" ,"November" ,"December" }; |
| 31 | |
| 32 | const wchar_t* const wmonth_long_names[]={L"January" ,L"February" ,L"March" , |
| 33 | L"April" ,L"May" ,L"June" , |
| 34 | L"July" ,L"August" ,L"September" , |
| 35 | L"October" ,L"Novomber" ,L"December" }; |
| 36 | |
| 37 | const wchar_t* const wweek_short_names[]= {L"Sun" , L"Mon" , L"Tue" , L"Wed" , |
| 38 | L"Thu" , L"Fri" , L"Sat" }; |
| 39 | |
| 40 | const char* const week_short_names[]={"Sun" , "Mon" ,"Tue" ,"Wed" , |
| 41 | "Thu" ,"Fri" ,"Sat" }; |
| 42 | |
| 43 | const wchar_t* const wweek_long_names[]= {L"Sunday" , L"Monday" , L"Tuesday" , |
| 44 | L"Wednesday" , L"Thursday" , |
| 45 | L"Friday" , L"Saturday" }; |
| 46 | |
| 47 | const char* const week_long_names[]= {"Sunday" , "Monday" , "Tuesday" , |
| 48 | "Wednesday" , "Thursday" , |
| 49 | "Friday" , "Saturday" }; |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | std::vector<std::basic_string<char> > short_month_names; |
| 55 | std::vector<std::basic_string<wchar_t> > wshort_month_names; |
| 56 | std::vector<std::basic_string<char> > long_month_names; |
| 57 | std::vector<std::basic_string<wchar_t> > wlong_month_names; |
| 58 | std::vector<std::basic_string<char> > short_week_names; |
| 59 | std::vector<std::basic_string<wchar_t> > wshort_week_names; |
| 60 | std::vector<std::basic_string<char> > long_week_names; |
| 61 | std::vector<std::basic_string<wchar_t> > wlong_week_names; |
| 62 | |
| 63 | |
| 64 | using namespace boost::gregorian; |
| 65 | |
| 66 | void |
| 67 | wtest_format(const std::basic_string<wchar_t>& format, |
| 68 | const std::basic_string<wchar_t>& value, |
| 69 | const std::string& testname, |
| 70 | boost::gregorian::date expected_res) |
| 71 | { |
| 72 | typedef boost::date_time::format_date_parser<date, wchar_t> parser_type; |
| 73 | typedef std::basic_string<wchar_t> string_type; |
| 74 | typedef std::istreambuf_iterator<wchar_t> iter_type; |
| 75 | try { |
| 76 | // string_type format(format); |
| 77 | std::basic_stringstream<wchar_t> ws; |
| 78 | ws << value; |
| 79 | iter_type sitr(ws); |
| 80 | iter_type stream_end; |
| 81 | |
| 82 | parser_type p(format, wshort_month_names, wlong_month_names, |
| 83 | wshort_week_names, wlong_week_names); |
| 84 | date d = p.parse_date(sitr, stream_end, format); |
| 85 | check_equal(testname, left: d, right: expected_res); |
| 86 | } |
| 87 | catch(std::exception& e) { |
| 88 | std::cout << "Got an exception: " << e.what() << std::endl; |
| 89 | check(testname, testcond: false); |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | |
| 94 | void |
| 95 | test_format(const std::basic_string<char>& format, |
| 96 | const std::basic_string<char>& value, |
| 97 | const std::string& testname, |
| 98 | boost::gregorian::date expected_res) |
| 99 | { |
| 100 | typedef boost::date_time::format_date_parser<date, char> parser_type; |
| 101 | typedef std::basic_string<char> string_type; |
| 102 | typedef std::istreambuf_iterator<char> iter_type; |
| 103 | try { |
| 104 | string_type format(format); |
| 105 | std::basic_stringstream<char> ws; |
| 106 | ws << value; |
| 107 | iter_type sitr(ws); |
| 108 | iter_type stream_end; |
| 109 | |
| 110 | parser_type pt(format, short_month_names, long_month_names, |
| 111 | short_week_names, long_week_names); |
| 112 | date d = pt.parse_date(sitr, stream_end, format); |
| 113 | check_equal(testname, left: d, right: expected_res); |
| 114 | } |
| 115 | catch(std::exception& e) { |
| 116 | std::cout << "Got an exception: " << e.what() << std::endl; |
| 117 | check(testname, testcond: false); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | |
| 122 | template<typename charT> |
| 123 | void |
| 124 | test_format2(boost::date_time::format_date_parser<date, charT>& parser, |
| 125 | const charT* const format, |
| 126 | const charT* const value, |
| 127 | const std::string& testname, |
| 128 | boost::gregorian::date expected_res) |
| 129 | { |
| 130 | try { |
| 131 | date d = parser.parse_date(value, format); |
| 132 | check_equal(testname, d == expected_res); |
| 133 | } |
| 134 | catch(std::exception& e) { |
| 135 | std::cout << "Got an exception: " << e.what() << std::endl; |
| 136 | check(testname, testcond: false); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | int |
| 141 | main() |
| 142 | { |
| 143 | std::copy(first: &wmonth_short_names[0], |
| 144 | last: &wmonth_short_names[12], |
| 145 | result: std::back_inserter(x&: wshort_month_names)); |
| 146 | |
| 147 | std::copy(first: &month_short_names[0], |
| 148 | last: &month_short_names[12], |
| 149 | result: std::back_inserter(x&: short_month_names)); |
| 150 | |
| 151 | std::copy(first: &month_long_names[0], |
| 152 | last: &month_long_names[12], |
| 153 | result: std::back_inserter(x&: long_month_names)); |
| 154 | |
| 155 | std::copy(first: &wmonth_long_names[0], |
| 156 | last: &wmonth_long_names[12], |
| 157 | result: std::back_inserter(x&: wlong_month_names)); |
| 158 | |
| 159 | |
| 160 | std::copy(first: &wweek_short_names[0], |
| 161 | last: &wweek_short_names[7], |
| 162 | result: std::back_inserter(x&: wshort_week_names)); |
| 163 | |
| 164 | std::copy(first: &week_short_names[0], |
| 165 | last: &week_short_names[7], |
| 166 | result: std::back_inserter(x&: short_week_names)); |
| 167 | |
| 168 | std::copy(first: &wweek_long_names[0], |
| 169 | last: &wweek_long_names[7], |
| 170 | result: std::back_inserter(x&: wlong_week_names)); |
| 171 | |
| 172 | std::copy(first: &week_long_names[0], |
| 173 | last: &week_long_names[7], |
| 174 | result: std::back_inserter(x&: long_week_names)); |
| 175 | |
| 176 | |
| 177 | wtest_format(format: L"1%%23%Y %m %d" , value: L"1232004 12 31 other stuff..." , |
| 178 | testname: "wide and weird" , expected_res: date(2004,12,31)); |
| 179 | |
| 180 | wtest_format(format: L"%Y-%m-%d" , value: L"2004-12-31" , |
| 181 | testname: "%Y-%m-%d wide" , expected_res: date(2004,12,31)); |
| 182 | |
| 183 | wtest_format(format: L"%Y day %j" , value: L"2004 day 001" , |
| 184 | testname: "%Y day %j wide" , expected_res: date(2004,1,1)); |
| 185 | |
| 186 | test_format(format: "%m/%d/%y" , value: "10/31/04" , |
| 187 | testname: "%m/%d/%y" , expected_res: date(2004,10,31)); |
| 188 | |
| 189 | |
| 190 | wtest_format(format: L"%Y/%m/%d" , value: L"2004-12-31" , |
| 191 | testname: "%Y/%m/%d wide 2004-12-31 input" , expected_res: date(2004,12,31)); |
| 192 | |
| 193 | test_format(format: "%Y.%d.%m" , value: "2004.31.1" , |
| 194 | testname: "%Y.%d.%m var length" , expected_res: date(2004,Jan,31)); |
| 195 | |
| 196 | test_format(format: "%d.%m.%Y" , value: "1.1.2004" , |
| 197 | testname: "%d.%m.%Y var length month and day" , expected_res: date(2004,1,1)); |
| 198 | |
| 199 | test_format(format: "%Y.%m.%d" , value: "2004.1.31" , |
| 200 | testname: "%Y.%m.%d var length month" , expected_res: date(2004,Jan,31)); |
| 201 | |
| 202 | test_format(format: "%Y.%b.%d" , value: "2004.Jan.1" , |
| 203 | testname: "%Y.%b.%d var length month" , expected_res: date(2004,Jan,1)); |
| 204 | |
| 205 | test_format(format: "%Y%m%d" , value: "20041231" , |
| 206 | testname: "%Y%m%d undelimited" , expected_res: date(2004,12,31)); |
| 207 | |
| 208 | test_format(format: "%Y/%d/%b" , value: "2004/01/Jan" , |
| 209 | testname: "%Y/%d/%b month at end" , expected_res: date(2004,1,1)); |
| 210 | |
| 211 | test_format(format: "%Y/%b/%d" , value: "2004/Jan/01" , |
| 212 | testname: "%Y/%b/%d named month jan" , expected_res: date(2004,1,1)); |
| 213 | |
| 214 | test_format(format: "%Y/%b/%d" , value: "2004/Dec/20" , |
| 215 | testname: "%Y/%b/%d named month dec" , expected_res: date(2004,12,20)); |
| 216 | |
| 217 | wtest_format(format: L"%Y/%b/%d" , value: L"2004-Jul-31" , |
| 218 | testname: "%Y/%b/%d wide 2004-Jul-31 input" , expected_res: date(2004,7,31)); |
| 219 | |
| 220 | wtest_format(format: L"%B %d, %Y" , value: L"March 15, 2004" , |
| 221 | testname: "%B %d, %Y" , expected_res: date(2004,3,15)); |
| 222 | |
| 223 | wtest_format(format: L"%a %B %d, %Y" , value: L"Sun March 15, 2004" , |
| 224 | testname: "%a %B %d, %Y" , expected_res: date(2004,3,15)); |
| 225 | |
| 226 | wtest_format(format: L"%A %B %d, %Y" , value: L"Sunday March 15, 2004" , |
| 227 | testname: "%A %B %d, %Y" , expected_res: date(2004,3,15)); |
| 228 | |
| 229 | // bad format case... |
| 230 | |
| 231 | { |
| 232 | try { |
| 233 | std::wstring format(L"%Y-%d" ); |
| 234 | std::wstringstream ws; |
| 235 | ws << L"2004-12-31" ; |
| 236 | std::istreambuf_iterator<wchar_t> sitr(ws); |
| 237 | std::istreambuf_iterator<wchar_t> stream_end; |
| 238 | |
| 239 | boost::date_time::format_date_parser<date,wchar_t> pt(format, |
| 240 | wshort_month_names, |
| 241 | wlong_month_names, |
| 242 | wshort_week_names, |
| 243 | wlong_week_names); |
| 244 | date d = pt.parse_date(sitr, stream_end); |
| 245 | check(testname: "Bad format spec test" , testcond: false); |
| 246 | } |
| 247 | catch(std::exception& e) { |
| 248 | std::cout << "Got an expected exception: " << e.what() << std::endl; |
| 249 | check(testname: "Bad format spec test -- pass" , testcond: true); |
| 250 | |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | { |
| 255 | //some interesting month names |
| 256 | const char* const roman_months[]={"I" ,"II" ,"III" , |
| 257 | "IV" ,"V" ,"VI" , |
| 258 | "VII" ,"VIII" ,"IX" , |
| 259 | "X" ,"XI" ,"XII" }; |
| 260 | std::vector<std::basic_string<char> > roman_month_names; |
| 261 | std::copy(first: &roman_months[0], |
| 262 | last: &roman_months[12], |
| 263 | result: std::back_inserter(x&: roman_month_names)); |
| 264 | |
| 265 | std::string format("%Y.%b.%d" ); |
| 266 | |
| 267 | boost::date_time::format_date_parser<date,char> parser(format, |
| 268 | roman_month_names, |
| 269 | long_month_names, |
| 270 | short_week_names, |
| 271 | long_week_names); |
| 272 | |
| 273 | |
| 274 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-I-1" , |
| 275 | testname: "roman I" , expected_res: date(2004,Jan,1)); |
| 276 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-II-01" , |
| 277 | testname: "roman II" , expected_res: date(2004,Feb,1)); |
| 278 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-III-01" , |
| 279 | testname: "roman III" , expected_res: date(2004,Mar,1)); |
| 280 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-IV-01" , |
| 281 | testname: "roman IV" , expected_res: date(2004,Apr,1)); |
| 282 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-V-01" , |
| 283 | testname: "roman V" , expected_res: date(2004,May,1)); |
| 284 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-VI-01" , |
| 285 | testname: "roman VI" , expected_res: date(2004,Jun,1)); |
| 286 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-VII-01" , |
| 287 | testname: "roman VII" , expected_res: date(2004,Jul,1)); |
| 288 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-VIII-01" , |
| 289 | testname: "roman VIII" , expected_res: date(2004,Aug,1)); |
| 290 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-IX-01" , |
| 291 | testname: "roman IX" , expected_res: date(2004,Sep,1)); |
| 292 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-X-01" , |
| 293 | testname: "roman X" , expected_res: date(2004,Oct,1)); |
| 294 | test_format2(parser, format: "%Y.%b.%d" , value: "2004-XI-01" , |
| 295 | testname: "roman XI" , expected_res: date(2004,Nov,1)); |
| 296 | test_format2(parser, format: "%Y.%b.%d" , value: "2004 XII 1" , |
| 297 | testname: "roman XII" , expected_res: date(2004,Dec,1)); |
| 298 | |
| 299 | } |
| 300 | |
| 301 | { |
| 302 | //alternate constructor that takes month/weekday strings |
| 303 | //from a locale |
| 304 | std::string format("%Y %m %d" ); |
| 305 | boost::date_time::format_date_parser<date,char> parser(format, |
| 306 | std::locale::classic()); |
| 307 | test_format2(parser, format: "%a %Y.%b.%d" , value: "Sun 2004 Jan 1" , |
| 308 | testname: "strings from locale" , expected_res: date(2004,Jan,1)); |
| 309 | test_format2(parser, format: "%a %Y.%b.%d" , value: "Mon 2004 Feb 1" , |
| 310 | testname: "strings from locale" , expected_res: date(2004,Feb,1)); |
| 311 | test_format2(parser, format: "%a %Y.%b.%d" , value: "Tue 2004 Mar 1" , |
| 312 | testname: "strings from locale" , expected_res: date(2004,Mar,1)); |
| 313 | test_format2(parser, format: "%a %Y.%b.%d" , value: "Wed 2004 Apr 1" , |
| 314 | testname: "strings from locale" , expected_res: date(2004,Apr,1)); |
| 315 | test_format2(parser, format: "%a %Y.%b.%d" , value: "thu 2004 May 1" , |
| 316 | testname: "strings from locale" , expected_res: date(2004,May,1)); |
| 317 | test_format2(parser, format: "%a %Y.%b.%d" , value: "fri 2004 Jun 1" , |
| 318 | testname: "strings from locale" , expected_res: date(2004,Jun,1)); |
| 319 | test_format2(parser, format: "%a %Y.%b.%d" , value: "sat 2004 Jul 1" , |
| 320 | testname: "strings from locale" , expected_res: date(2004,Jul,1)); |
| 321 | test_format2(parser, format: "%Y.%b.%d" , value: "2004 Aug 1" , |
| 322 | testname: "strings from locale" , expected_res: date(2004,Aug,1)); |
| 323 | test_format2(parser, format: "%Y.%b.%d" , value: "2004 Sep 1" , |
| 324 | testname: "strings from locale" , expected_res: date(2004,Sep,1)); |
| 325 | test_format2(parser, format: "%Y.%b.%d" , value: "2004 Sep 1" , |
| 326 | testname: "strings from locale" , expected_res: date(2004,Sep,1)); |
| 327 | test_format2(parser, format: "%Y.%b.%d" , value: "2004 Oct 1" , |
| 328 | testname: "strings from locale" , expected_res: date(2004,Oct,1)); |
| 329 | test_format2(parser, format: "%Y.%b.%d" , value: "2004 Nov 1" , |
| 330 | testname: "strings from locale" , expected_res: date(2004,Nov,1)); |
| 331 | test_format2(parser, format: "%Y.%b.%d" , value: "2004 Dec 1" , |
| 332 | testname: "strings from locale" , expected_res: date(2004,Dec,1)); |
| 333 | |
| 334 | test_format2(parser, format: "%A %B %d, %Y" , value: "Sunday January 1, 2004" , |
| 335 | testname: "long strings from locale" , expected_res: date(2004,Jan,1)); |
| 336 | test_format2(parser, format: "%A %B %d, %Y" , value: "Monday February 29, 2004" , |
| 337 | testname: "long strings from locale" , expected_res: date(2004,Feb,29)); |
| 338 | test_format2(parser, format: "%A %B %d, %Y" , value: "Tuesday March 1, 2004" , |
| 339 | testname: "long strings from locale" , expected_res: date(2004,Mar,1)); |
| 340 | test_format2(parser, format: "%A %B %d, %Y" , value: "Wednesday APRIL 1, 2004" , |
| 341 | testname: "long strings from locale" , expected_res: date(2004,Apr,1)); |
| 342 | test_format2(parser, format: "%A %B %d, %Y" , value: "thursday may 15, 2004" , |
| 343 | testname: "long strings from locale" , expected_res: date(2004,May,15)); |
| 344 | test_format2(parser, format: "%A %B %d, %Y" , value: "friday june 15, 2004" , |
| 345 | testname: "long strings from locale" , expected_res: date(2004,Jun,15)); |
| 346 | test_format2(parser, format: "%A %B %d, %Y" , value: "saturday july 30, 2004" , |
| 347 | testname: "long strings from locale" , expected_res: date(2004,Jul,30)); |
| 348 | test_format2(parser, format: "%A %B %d, %Y" , value: "thursday auguST 15, 2004" , |
| 349 | testname: "long strings from locale" , expected_res: date(2004,Aug,15)); |
| 350 | test_format2(parser, format: "%A %B %d, %Y" , value: "thursday september 1, 2004" , |
| 351 | testname: "long strings from locale" , expected_res: date(2004,Sep,1)); |
| 352 | test_format2(parser, format: "%A %B %d, %Y" , value: "thursday october 1, 2004" , |
| 353 | testname: "long strings from locale" , expected_res: date(2004,Oct,1)); |
| 354 | test_format2(parser, format: "%A %B %d, %Y" , value: "thursday november 1, 2004" , |
| 355 | testname: "long strings from locale" , expected_res: date(2004,Nov,1)); |
| 356 | test_format2(parser, format: "%A %B %d, %Y" , value: "thursday december 31, 2004" , |
| 357 | testname: "long strings from locale" , expected_res: date(2004,Dec,31)); |
| 358 | |
| 359 | } |
| 360 | |
| 361 | return printTestStats(); |
| 362 | |
| 363 | } |
| 364 | |