date_facet.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. #ifndef _DATE_TIME_DATE_FACET__HPP___
  2. #define _DATE_TIME_DATE_FACET__HPP___
  3. /* Copyright (c) 2004-2005 CrystalClear Software, Inc.
  4. * Use, modification and distribution is subject to the
  5. * Boost Software License, Version 1.0. (See accompanying
  6. * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
  7. * Author: Martin Andrian, Jeff Garland, Bart Garst
  8. * $Date$
  9. */
  10. #include <iterator> // ostreambuf_iterator
  11. #include <locale>
  12. #include <string>
  13. #include <vector>
  14. #include <boost/throw_exception.hpp>
  15. #include <boost/algorithm/string/replace.hpp>
  16. #include <boost/date_time/compiler_config.hpp>
  17. #include <boost/date_time/period.hpp>
  18. #include <boost/date_time/special_defs.hpp>
  19. #include <boost/date_time/special_values_formatter.hpp>
  20. #include <boost/date_time/period_formatter.hpp>
  21. #include <boost/date_time/period_parser.hpp>
  22. #include <boost/date_time/date_generator_formatter.hpp>
  23. #include <boost/date_time/date_generator_parser.hpp>
  24. #include <boost/date_time/format_date_parser.hpp>
  25. namespace boost { namespace date_time {
  26. /*! Class that provides format based I/O facet for date types.
  27. *
  28. * This class allows the formatting of dates by using format string.
  29. * Format strings are:
  30. *
  31. * - %A => long_weekday_format - Full name Ex: Tuesday
  32. * - %a => short_weekday_format - Three letter abbreviation Ex: Tue
  33. * - %B => long_month_format - Full name Ex: October
  34. * - %b => short_month_format - Three letter abbreviation Ex: Oct
  35. * - %x => standard_format_specifier - defined by the locale
  36. * - %Y-%b-%d => default_date_format - YYYY-Mon-dd
  37. *
  38. * Default month format == %b
  39. * Default weekday format == %a
  40. */
  41. template <class date_type,
  42. class CharT,
  43. class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
  44. class BOOST_SYMBOL_VISIBLE date_facet : public std::locale::facet {
  45. public:
  46. typedef typename date_type::duration_type duration_type;
  47. // greg_weekday is gregorian_calendar::day_of_week_type
  48. typedef typename date_type::day_of_week_type day_of_week_type;
  49. typedef typename date_type::day_type day_type;
  50. typedef typename date_type::month_type month_type;
  51. typedef boost::date_time::period<date_type,duration_type> period_type;
  52. typedef std::basic_string<CharT> string_type;
  53. typedef CharT char_type;
  54. typedef boost::date_time::period_formatter<CharT> period_formatter_type;
  55. typedef boost::date_time::special_values_formatter<CharT> special_values_formatter_type;
  56. typedef std::vector<std::basic_string<CharT> > input_collection_type;
  57. // used for the output of the date_generators
  58. typedef date_generator_formatter<date_type, CharT> date_gen_formatter_type;
  59. typedef partial_date<date_type> partial_date_type;
  60. typedef nth_kday_of_month<date_type> nth_kday_type;
  61. typedef first_kday_of_month<date_type> first_kday_type;
  62. typedef last_kday_of_month<date_type> last_kday_type;
  63. typedef first_kday_after<date_type> kday_after_type;
  64. typedef first_kday_before<date_type> kday_before_type;
  65. static const char_type long_weekday_format[3];
  66. static const char_type short_weekday_format[3];
  67. static const char_type long_month_format[3];
  68. static const char_type short_month_format[3];
  69. static const char_type default_period_separator[4];
  70. static const char_type standard_format_specifier[3];
  71. static const char_type iso_format_specifier[7];
  72. static const char_type iso_format_extended_specifier[9];
  73. static const char_type default_date_format[9]; // YYYY-Mon-DD
  74. static std::locale::id id;
  75. #if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
  76. std::locale::id& __get_id (void) const { return id; }
  77. #endif
  78. explicit date_facet(::size_t a_ref = 0)
  79. : std::locale::facet(a_ref),
  80. //m_format(standard_format_specifier)
  81. m_format(default_date_format),
  82. m_month_format(short_month_format),
  83. m_weekday_format(short_weekday_format)
  84. {}
  85. explicit date_facet(const char_type* format_str,
  86. const input_collection_type& short_names,
  87. ::size_t ref_count = 0)
  88. : std::locale::facet(ref_count),
  89. m_format(format_str),
  90. m_month_format(short_month_format),
  91. m_weekday_format(short_weekday_format),
  92. m_month_short_names(short_names)
  93. {}
  94. explicit date_facet(const char_type* format_str,
  95. period_formatter_type per_formatter = period_formatter_type(),
  96. special_values_formatter_type sv_formatter = special_values_formatter_type(),
  97. date_gen_formatter_type dg_formatter = date_gen_formatter_type(),
  98. ::size_t ref_count = 0)
  99. : std::locale::facet(ref_count),
  100. m_format(format_str),
  101. m_month_format(short_month_format),
  102. m_weekday_format(short_weekday_format),
  103. m_period_formatter(per_formatter),
  104. m_date_gen_formatter(dg_formatter),
  105. m_special_values_formatter(sv_formatter)
  106. {}
  107. void format(const char_type* const format_str) {
  108. m_format = format_str;
  109. }
  110. virtual void set_iso_format()
  111. {
  112. m_format = iso_format_specifier;
  113. }
  114. virtual void set_iso_extended_format()
  115. {
  116. m_format = iso_format_extended_specifier;
  117. }
  118. void month_format(const char_type* const format_str) {
  119. m_month_format = format_str;
  120. }
  121. void weekday_format(const char_type* const format_str) {
  122. m_weekday_format = format_str;
  123. }
  124. void period_formatter(period_formatter_type per_formatter) {
  125. m_period_formatter= per_formatter;
  126. }
  127. void special_values_formatter(const special_values_formatter_type& svf)
  128. {
  129. m_special_values_formatter = svf;
  130. }
  131. void short_weekday_names(const input_collection_type& short_names)
  132. {
  133. m_weekday_short_names = short_names;
  134. }
  135. void long_weekday_names(const input_collection_type& long_names)
  136. {
  137. m_weekday_long_names = long_names;
  138. }
  139. void short_month_names(const input_collection_type& short_names)
  140. {
  141. m_month_short_names = short_names;
  142. }
  143. void long_month_names(const input_collection_type& long_names)
  144. {
  145. m_month_long_names = long_names;
  146. }
  147. void date_gen_phrase_strings(const input_collection_type& new_strings,
  148. typename date_gen_formatter_type::phrase_elements beg_pos=date_gen_formatter_type::first)
  149. {
  150. m_date_gen_formatter.elements(new_strings, beg_pos);
  151. }
  152. OutItrT put(OutItrT next,
  153. std::ios_base& a_ios,
  154. char_type fill_char,
  155. const date_type& d) const
  156. {
  157. if (d.is_special()) {
  158. return do_put_special(next, a_ios, fill_char, d.as_special());
  159. }
  160. //The following line of code required the date to support a to_tm function
  161. return do_put_tm(next, a_ios, fill_char, to_tm(d), m_format);
  162. }
  163. OutItrT put(OutItrT next,
  164. std::ios_base& a_ios,
  165. char_type fill_char,
  166. const duration_type& dd) const
  167. {
  168. if (dd.is_special()) {
  169. return do_put_special(next, a_ios, fill_char, dd.get_rep().as_special());
  170. }
  171. typedef std::num_put<CharT, OutItrT> num_put;
  172. if (std::has_facet<num_put>(a_ios.getloc())) {
  173. return std::use_facet<num_put>(a_ios.getloc()).put(next, a_ios, fill_char, dd.get_rep().as_number());
  174. }
  175. else {
  176. num_put* f = new num_put();
  177. std::locale l = std::locale(a_ios.getloc(), f);
  178. a_ios.imbue(l);
  179. return f->put(next, a_ios, fill_char, dd.get_rep().as_number());
  180. }
  181. }
  182. OutItrT put(OutItrT next,
  183. std::ios_base& a_ios,
  184. char_type fill_char,
  185. const month_type& m) const
  186. {
  187. //if (d.is_special()) {
  188. // return do_put_special(next, a_ios, fill_char, d.as_special());
  189. //}
  190. //The following line of code required the date to support a to_tm function
  191. std::tm dtm;
  192. std::memset(&dtm, 0, sizeof(dtm));
  193. dtm.tm_mon = m - 1;
  194. return do_put_tm(next, a_ios, fill_char, dtm, m_month_format);
  195. }
  196. //! puts the day of month
  197. OutItrT put(OutItrT next,
  198. std::ios_base& a_ios,
  199. char_type fill_char,
  200. const day_type& day) const
  201. {
  202. std::tm dtm;
  203. std::memset(&dtm, 0, sizeof(dtm));
  204. dtm.tm_mday = day.as_number();
  205. char_type tmp[3] = {'%','d'};
  206. string_type temp_format(tmp);
  207. return do_put_tm(next, a_ios, fill_char, dtm, temp_format);
  208. }
  209. OutItrT put(OutItrT next,
  210. std::ios_base& a_ios,
  211. char_type fill_char,
  212. const day_of_week_type& dow) const
  213. {
  214. //if (d.is_special()) {
  215. // return do_put_special(next, a_ios, fill_char, d.as_special());
  216. //}
  217. //The following line of code required the date to support a to_tm function
  218. std::tm dtm;
  219. std::memset(&dtm, 0, sizeof(dtm));
  220. dtm.tm_wday = dow;
  221. return do_put_tm(next, a_ios, fill_char, dtm, m_weekday_format);
  222. }
  223. OutItrT put(OutItrT next,
  224. std::ios_base& a_ios,
  225. char_type fill_char,
  226. const period_type& p) const
  227. {
  228. return m_period_formatter.put_period(next, a_ios, fill_char, p, *this);
  229. }
  230. OutItrT put(OutItrT next,
  231. std::ios_base& a_ios,
  232. char_type fill_char,
  233. const partial_date_type& pd) const
  234. {
  235. return m_date_gen_formatter.put_partial_date(next, a_ios, fill_char, pd, *this);
  236. }
  237. OutItrT put(OutItrT next,
  238. std::ios_base& a_ios,
  239. char_type fill_char,
  240. const nth_kday_type& nkd) const
  241. {
  242. return m_date_gen_formatter.put_nth_kday(next, a_ios, fill_char, nkd, *this);
  243. }
  244. OutItrT put(OutItrT next,
  245. std::ios_base& a_ios,
  246. char_type fill_char,
  247. const first_kday_type& fkd) const
  248. {
  249. return m_date_gen_formatter.put_first_kday(next, a_ios, fill_char, fkd, *this);
  250. }
  251. OutItrT put(OutItrT next,
  252. std::ios_base& a_ios,
  253. char_type fill_char,
  254. const last_kday_type& lkd) const
  255. {
  256. return m_date_gen_formatter.put_last_kday(next, a_ios, fill_char, lkd, *this);
  257. }
  258. OutItrT put(OutItrT next,
  259. std::ios_base& a_ios,
  260. char_type fill_char,
  261. const kday_before_type& fkb) const
  262. {
  263. return m_date_gen_formatter.put_kday_before(next, a_ios, fill_char, fkb, *this);
  264. }
  265. OutItrT put(OutItrT next,
  266. std::ios_base& a_ios,
  267. char_type fill_char,
  268. const kday_after_type& fka) const
  269. {
  270. return m_date_gen_formatter.put_kday_after(next, a_ios, fill_char, fka, *this);
  271. }
  272. protected:
  273. virtual OutItrT do_put_special(OutItrT next,
  274. std::ios_base& /*a_ios*/,
  275. char_type /*fill_char*/,
  276. const boost::date_time::special_values sv) const
  277. {
  278. m_special_values_formatter.put_special(next, sv);
  279. return next;
  280. }
  281. virtual OutItrT do_put_tm(OutItrT next,
  282. std::ios_base& a_ios,
  283. char_type fill_char,
  284. const tm& tm_value,
  285. string_type a_format) const
  286. {
  287. // update format string with custom names
  288. if (!m_weekday_long_names.empty()) {
  289. boost::algorithm::replace_all(a_format,
  290. long_weekday_format,
  291. m_weekday_long_names[tm_value.tm_wday]);
  292. }
  293. if (!m_weekday_short_names.empty()) {
  294. boost::algorithm::replace_all(a_format,
  295. short_weekday_format,
  296. m_weekday_short_names[tm_value.tm_wday]);
  297. }
  298. if (!m_month_long_names.empty()) {
  299. boost::algorithm::replace_all(a_format,
  300. long_month_format,
  301. m_month_long_names[tm_value.tm_mon]);
  302. }
  303. if (!m_month_short_names.empty()) {
  304. boost::algorithm::replace_all(a_format,
  305. short_month_format,
  306. m_month_short_names[tm_value.tm_mon]);
  307. }
  308. // use time_put facet to create final string
  309. const char_type* p_format = a_format.c_str();
  310. return std::use_facet<std::time_put<CharT> >(a_ios.getloc()).put(next, a_ios,
  311. fill_char,
  312. &tm_value,
  313. p_format,
  314. p_format + a_format.size());
  315. }
  316. protected:
  317. string_type m_format;
  318. string_type m_month_format;
  319. string_type m_weekday_format;
  320. period_formatter_type m_period_formatter;
  321. date_gen_formatter_type m_date_gen_formatter;
  322. special_values_formatter_type m_special_values_formatter;
  323. input_collection_type m_month_short_names;
  324. input_collection_type m_month_long_names;
  325. input_collection_type m_weekday_short_names;
  326. input_collection_type m_weekday_long_names;
  327. private:
  328. };
  329. template <class date_type, class CharT, class OutItrT>
  330. std::locale::id date_facet<date_type, CharT, OutItrT>::id;
  331. template <class date_type, class CharT, class OutItrT>
  332. const typename date_facet<date_type, CharT, OutItrT>::char_type
  333. date_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'};
  334. template <class date_type, class CharT, class OutItrT>
  335. const typename date_facet<date_type, CharT, OutItrT>::char_type
  336. date_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'};
  337. template <class date_type, class CharT, class OutItrT>
  338. const typename date_facet<date_type, CharT, OutItrT>::char_type
  339. date_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'};
  340. template <class date_type, class CharT, class OutItrT>
  341. const typename date_facet<date_type, CharT, OutItrT>::char_type
  342. date_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'};
  343. template <class date_type, class CharT, class OutItrT>
  344. const typename date_facet<date_type, CharT, OutItrT>::char_type
  345. date_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '};
  346. template <class date_type, class CharT, class OutItrT>
  347. const typename date_facet<date_type, CharT, OutItrT>::char_type
  348. date_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] =
  349. {'%', 'x' };
  350. template <class date_type, class CharT, class OutItrT>
  351. const typename date_facet<date_type, CharT, OutItrT>::char_type
  352. date_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] =
  353. {'%', 'Y', '%', 'm', '%', 'd' };
  354. template <class date_type, class CharT, class OutItrT>
  355. const typename date_facet<date_type, CharT, OutItrT>::char_type
  356. date_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] =
  357. {'%', 'Y', '-', '%', 'm', '-', '%', 'd' };
  358. template <class date_type, class CharT, class OutItrT>
  359. const typename date_facet<date_type, CharT, OutItrT>::char_type
  360. date_facet<date_type, CharT, OutItrT>::default_date_format[9] =
  361. {'%','Y','-','%','b','-','%','d'};
  362. //! Input facet
  363. template <class date_type,
  364. class CharT,
  365. class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
  366. class BOOST_SYMBOL_VISIBLE date_input_facet : public std::locale::facet {
  367. public:
  368. typedef typename date_type::duration_type duration_type;
  369. // greg_weekday is gregorian_calendar::day_of_week_type
  370. typedef typename date_type::day_of_week_type day_of_week_type;
  371. typedef typename date_type::day_type day_type;
  372. typedef typename date_type::month_type month_type;
  373. typedef typename date_type::year_type year_type;
  374. typedef boost::date_time::period<date_type,duration_type> period_type;
  375. typedef std::basic_string<CharT> string_type;
  376. typedef CharT char_type;
  377. typedef boost::date_time::period_parser<date_type, CharT> period_parser_type;
  378. typedef boost::date_time::special_values_parser<date_type,CharT> special_values_parser_type;
  379. typedef std::vector<std::basic_string<CharT> > input_collection_type;
  380. typedef format_date_parser<date_type, CharT> format_date_parser_type;
  381. // date_generators stuff goes here
  382. typedef date_generator_parser<date_type, CharT> date_gen_parser_type;
  383. typedef partial_date<date_type> partial_date_type;
  384. typedef nth_kday_of_month<date_type> nth_kday_type;
  385. typedef first_kday_of_month<date_type> first_kday_type;
  386. typedef last_kday_of_month<date_type> last_kday_type;
  387. typedef first_kday_after<date_type> kday_after_type;
  388. typedef first_kday_before<date_type> kday_before_type;
  389. static const char_type long_weekday_format[3];
  390. static const char_type short_weekday_format[3];
  391. static const char_type long_month_format[3];
  392. static const char_type short_month_format[3];
  393. static const char_type four_digit_year_format[3];
  394. static const char_type two_digit_year_format[3];
  395. static const char_type default_period_separator[4];
  396. static const char_type standard_format_specifier[3];
  397. static const char_type iso_format_specifier[7];
  398. static const char_type iso_format_extended_specifier[9];
  399. static const char_type default_date_format[9]; // YYYY-Mon-DD
  400. static std::locale::id id;
  401. explicit date_input_facet(::size_t a_ref = 0)
  402. : std::locale::facet(a_ref),
  403. m_format(default_date_format),
  404. m_month_format(short_month_format),
  405. m_weekday_format(short_weekday_format),
  406. m_year_format(four_digit_year_format),
  407. m_parser(m_format, std::locale::classic())
  408. // default period_parser & special_values_parser used
  409. {}
  410. explicit date_input_facet(const string_type& format_str,
  411. ::size_t a_ref = 0)
  412. : std::locale::facet(a_ref),
  413. m_format(format_str),
  414. m_month_format(short_month_format),
  415. m_weekday_format(short_weekday_format),
  416. m_year_format(four_digit_year_format),
  417. m_parser(m_format, std::locale::classic())
  418. // default period_parser & special_values_parser used
  419. {}
  420. explicit date_input_facet(const string_type& format_str,
  421. const format_date_parser_type& date_parser,
  422. const special_values_parser_type& sv_parser,
  423. const period_parser_type& per_parser,
  424. const date_gen_parser_type& date_gen_parser,
  425. ::size_t ref_count = 0)
  426. : std::locale::facet(ref_count),
  427. m_format(format_str),
  428. m_month_format(short_month_format),
  429. m_weekday_format(short_weekday_format),
  430. m_year_format(four_digit_year_format),
  431. m_parser(date_parser),
  432. m_date_gen_parser(date_gen_parser),
  433. m_period_parser(per_parser),
  434. m_sv_parser(sv_parser)
  435. {}
  436. void format(const char_type* const format_str) {
  437. m_format = format_str;
  438. }
  439. virtual void set_iso_format()
  440. {
  441. m_format = iso_format_specifier;
  442. }
  443. virtual void set_iso_extended_format()
  444. {
  445. m_format = iso_format_extended_specifier;
  446. }
  447. void month_format(const char_type* const format_str) {
  448. m_month_format = format_str;
  449. }
  450. void weekday_format(const char_type* const format_str) {
  451. m_weekday_format = format_str;
  452. }
  453. void year_format(const char_type* const format_str) {
  454. m_year_format = format_str;
  455. }
  456. void period_parser(period_parser_type per_parser) {
  457. m_period_parser = per_parser;
  458. }
  459. void short_weekday_names(const input_collection_type& weekday_names)
  460. {
  461. m_parser.short_weekday_names(weekday_names);
  462. }
  463. void long_weekday_names(const input_collection_type& weekday_names)
  464. {
  465. m_parser.long_weekday_names(weekday_names);
  466. }
  467. void short_month_names(const input_collection_type& month_names)
  468. {
  469. m_parser.short_month_names(month_names);
  470. }
  471. void long_month_names(const input_collection_type& month_names)
  472. {
  473. m_parser.long_month_names(month_names);
  474. }
  475. void date_gen_element_strings(const input_collection_type& col)
  476. {
  477. m_date_gen_parser.element_strings(col);
  478. }
  479. void date_gen_element_strings(const string_type& first,
  480. const string_type& second,
  481. const string_type& third,
  482. const string_type& fourth,
  483. const string_type& fifth,
  484. const string_type& last,
  485. const string_type& before,
  486. const string_type& after,
  487. const string_type& of)
  488. {
  489. m_date_gen_parser.element_strings(first,second,third,fourth,fifth,last,before,after,of);
  490. }
  491. void special_values_parser(special_values_parser_type sv_parser)
  492. {
  493. m_sv_parser = sv_parser;
  494. }
  495. InItrT get(InItrT& from,
  496. InItrT& to,
  497. std::ios_base& /*a_ios*/,
  498. date_type& d) const
  499. {
  500. d = m_parser.parse_date(from, to, m_format, m_sv_parser);
  501. return from;
  502. }
  503. InItrT get(InItrT& from,
  504. InItrT& to,
  505. std::ios_base& /*a_ios*/,
  506. month_type& m) const
  507. {
  508. m = m_parser.parse_month(from, to, m_month_format);
  509. return from;
  510. }
  511. InItrT get(InItrT& from,
  512. InItrT& to,
  513. std::ios_base& /*a_ios*/,
  514. day_of_week_type& wd) const
  515. {
  516. wd = m_parser.parse_weekday(from, to, m_weekday_format);
  517. return from;
  518. }
  519. //! Expects 1 or 2 digit day range: 1-31
  520. InItrT get(InItrT& from,
  521. InItrT& to,
  522. std::ios_base& /*a_ios*/,
  523. day_type& d) const
  524. {
  525. d = m_parser.parse_var_day_of_month(from, to);
  526. return from;
  527. }
  528. InItrT get(InItrT& from,
  529. InItrT& to,
  530. std::ios_base& /*a_ios*/,
  531. year_type& y) const
  532. {
  533. y = m_parser.parse_year(from, to, m_year_format);
  534. return from;
  535. }
  536. InItrT get(InItrT& from,
  537. InItrT& to,
  538. std::ios_base& a_ios,
  539. duration_type& dd) const
  540. {
  541. // skip leading whitespace
  542. while(std::isspace(*from) && from != to) { ++from; }
  543. /* num_get.get() will always consume the first character if it
  544. * is a sign indicator (+/-). Special value strings may begin
  545. * with one of these signs so we'll need a copy of it
  546. * in case num_get.get() fails. */
  547. char_type c = '\0';
  548. // TODO Are these characters somewhere in the locale?
  549. if(*from == '-' || *from == '+') {
  550. c = *from;
  551. }
  552. typedef std::num_get<CharT, InItrT> num_get;
  553. typename duration_type::duration_rep_type val = 0;
  554. std::ios_base::iostate err = std::ios_base::goodbit;
  555. if (std::has_facet<num_get>(a_ios.getloc())) {
  556. from = std::use_facet<num_get>(a_ios.getloc()).get(from, to, a_ios, err, val);
  557. }
  558. else {
  559. num_get* ng = new num_get();
  560. std::locale l = std::locale(a_ios.getloc(), ng);
  561. a_ios.imbue(l);
  562. from = ng->get(from, to, a_ios, err, val);
  563. }
  564. if(err & std::ios_base::failbit){
  565. typedef typename special_values_parser_type::match_results match_results;
  566. match_results mr;
  567. if(c == '-' || c == '+') { // was the first character consumed?
  568. mr.cache += c;
  569. }
  570. m_sv_parser.match(from, to, mr);
  571. if(mr.current_match == match_results::PARSE_ERROR) {
  572. boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"));
  573. BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return from); // should never reach
  574. }
  575. dd = duration_type(static_cast<special_values>(mr.current_match));
  576. }
  577. else {
  578. dd = duration_type(val);
  579. }
  580. return from;
  581. }
  582. InItrT get(InItrT& from,
  583. InItrT& to,
  584. std::ios_base& a_ios,
  585. period_type& p) const
  586. {
  587. p = m_period_parser.get_period(from, to, a_ios, p, duration_type::unit(), *this);
  588. return from;
  589. }
  590. InItrT get(InItrT& from,
  591. InItrT& to,
  592. std::ios_base& a_ios,
  593. nth_kday_type& nkd) const
  594. {
  595. nkd = m_date_gen_parser.get_nth_kday_type(from, to, a_ios, *this);
  596. return from;
  597. }
  598. InItrT get(InItrT& from,
  599. InItrT& to,
  600. std::ios_base& a_ios,
  601. partial_date_type& pd) const
  602. {
  603. pd = m_date_gen_parser.get_partial_date_type(from, to, a_ios, *this);
  604. return from;
  605. }
  606. InItrT get(InItrT& from,
  607. InItrT& to,
  608. std::ios_base& a_ios,
  609. first_kday_type& fkd) const
  610. {
  611. fkd = m_date_gen_parser.get_first_kday_type(from, to, a_ios, *this);
  612. return from;
  613. }
  614. InItrT get(InItrT& from,
  615. InItrT& to,
  616. std::ios_base& a_ios,
  617. last_kday_type& lkd) const
  618. {
  619. lkd = m_date_gen_parser.get_last_kday_type(from, to, a_ios, *this);
  620. return from;
  621. }
  622. InItrT get(InItrT& from,
  623. InItrT& to,
  624. std::ios_base& a_ios,
  625. kday_before_type& fkb) const
  626. {
  627. fkb = m_date_gen_parser.get_kday_before_type(from, to, a_ios, *this);
  628. return from;
  629. }
  630. InItrT get(InItrT& from,
  631. InItrT& to,
  632. std::ios_base& a_ios,
  633. kday_after_type& fka) const
  634. {
  635. fka = m_date_gen_parser.get_kday_after_type(from, to, a_ios, *this);
  636. return from;
  637. }
  638. protected:
  639. string_type m_format;
  640. string_type m_month_format;
  641. string_type m_weekday_format;
  642. string_type m_year_format;
  643. format_date_parser_type m_parser;
  644. date_gen_parser_type m_date_gen_parser;
  645. period_parser_type m_period_parser;
  646. special_values_parser_type m_sv_parser;
  647. private:
  648. };
  649. template <class date_type, class CharT, class OutItrT>
  650. std::locale::id date_input_facet<date_type, CharT, OutItrT>::id;
  651. template <class date_type, class CharT, class OutItrT>
  652. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  653. date_input_facet<date_type, CharT, OutItrT>::long_weekday_format[3] = {'%','A'};
  654. template <class date_type, class CharT, class OutItrT>
  655. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  656. date_input_facet<date_type, CharT, OutItrT>::short_weekday_format[3] = {'%','a'};
  657. template <class date_type, class CharT, class OutItrT>
  658. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  659. date_input_facet<date_type, CharT, OutItrT>::long_month_format[3] = {'%','B'};
  660. template <class date_type, class CharT, class OutItrT>
  661. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  662. date_input_facet<date_type, CharT, OutItrT>::short_month_format[3] = {'%','b'};
  663. template <class date_type, class CharT, class OutItrT>
  664. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  665. date_input_facet<date_type, CharT, OutItrT>::four_digit_year_format[3] = {'%','Y'};
  666. template <class date_type, class CharT, class OutItrT>
  667. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  668. date_input_facet<date_type, CharT, OutItrT>::two_digit_year_format[3] = {'%','y'};
  669. template <class date_type, class CharT, class OutItrT>
  670. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  671. date_input_facet<date_type, CharT, OutItrT>::default_period_separator[4] = { ' ', '/', ' '};
  672. template <class date_type, class CharT, class OutItrT>
  673. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  674. date_input_facet<date_type, CharT, OutItrT>::standard_format_specifier[3] =
  675. {'%', 'x' };
  676. template <class date_type, class CharT, class OutItrT>
  677. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  678. date_input_facet<date_type, CharT, OutItrT>::iso_format_specifier[7] =
  679. {'%', 'Y', '%', 'm', '%', 'd' };
  680. template <class date_type, class CharT, class OutItrT>
  681. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  682. date_input_facet<date_type, CharT, OutItrT>::iso_format_extended_specifier[9] =
  683. {'%', 'Y', '-', '%', 'm', '-', '%', 'd' };
  684. template <class date_type, class CharT, class OutItrT>
  685. const typename date_input_facet<date_type, CharT, OutItrT>::char_type
  686. date_input_facet<date_type, CharT, OutItrT>::default_date_format[9] =
  687. {'%','Y','-','%','b','-','%','d'};
  688. } } // namespaces
  689. #endif