time_facet.hpp 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. #ifndef _DATE_TIME_FACET__HPP__
  2. #define _DATE_TIME_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: 2008-11-23 06:13:35 -0500 (Sun, 23 Nov 2008) $
  9. */
  10. #include <cctype>
  11. #include <locale>
  12. #include <limits>
  13. #include <string>
  14. #include <sstream>
  15. #include <iomanip>
  16. #include <iterator> // i/ostreambuf_iterator
  17. #include <exception>
  18. #include <boost/assert.hpp>
  19. #include <boost/lexical_cast.hpp>
  20. #include <boost/throw_exception.hpp>
  21. #include <boost/algorithm/string/erase.hpp>
  22. #include <boost/algorithm/string/replace.hpp>
  23. #include <boost/date_time/compiler_config.hpp>
  24. #include <boost/date_time/date_facet.hpp>
  25. #include <boost/date_time/string_convert.hpp>
  26. #include <boost/date_time/special_defs.hpp>
  27. namespace boost {
  28. namespace date_time {
  29. template <class CharT>
  30. struct time_formats {
  31. public:
  32. typedef CharT char_type;
  33. static const char_type fractional_seconds_format[3]; // f
  34. static const char_type fractional_seconds_or_none_format[3]; // F
  35. static const char_type seconds_with_fractional_seconds_format[3]; // s
  36. static const char_type seconds_format[3]; // S
  37. static const char_type hours_format[3]; // H
  38. static const char_type unrestricted_hours_format[3]; // O
  39. static const char_type standard_format[9]; // x X
  40. static const char_type zone_abbrev_format[3]; // z
  41. static const char_type zone_name_format[3]; // Z
  42. static const char_type zone_iso_format[3]; // q
  43. static const char_type zone_iso_extended_format[3]; // Q
  44. static const char_type posix_zone_string_format[4]; // ZP
  45. static const char_type duration_sign_negative_only[3]; // -
  46. static const char_type duration_sign_always[3]; // +
  47. static const char_type duration_seperator[2];
  48. static const char_type negative_sign[2]; //-
  49. static const char_type positive_sign[2]; //+
  50. static const char_type iso_time_format_specifier[18];
  51. static const char_type iso_time_format_extended_specifier[22];
  52. //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz]
  53. static const char_type default_time_format[23];
  54. // default_time_input_format uses a posix_time_zone_string instead of a time zone abbrev
  55. static const char_type default_time_input_format[24];
  56. //default time_duration format is HH:MM:SS[.fff...]
  57. static const char_type default_time_duration_format[11];
  58. };
  59. template <class CharT>
  60. const typename time_formats<CharT>::char_type
  61. time_formats<CharT>::fractional_seconds_format[3] = {'%','f'};
  62. template <class CharT>
  63. const typename time_formats<CharT>::char_type
  64. time_formats<CharT>::fractional_seconds_or_none_format[3] = {'%','F'};
  65. template <class CharT>
  66. const typename time_formats<CharT>::char_type
  67. time_formats<CharT>::seconds_with_fractional_seconds_format[3] =
  68. {'%','s'};
  69. template <class CharT>
  70. const typename time_formats<CharT>::char_type
  71. time_formats<CharT>::seconds_format[3] = {'%','S'};
  72. template <class CharT>
  73. const typename time_formats<CharT>::char_type
  74. time_formats<CharT>::hours_format[3] = {'%','H'};
  75. template <class CharT>
  76. const typename time_formats<CharT>::char_type
  77. time_formats<CharT>::unrestricted_hours_format[3] = {'%','O'};
  78. template <class CharT>
  79. const typename time_formats<CharT>::char_type
  80. //time_formats<CharT>::standard_format[5] = {'%','c',' ','%','z'};
  81. time_formats<CharT>::standard_format[9] = {'%','x',' ','%','X',' ','%','z'};
  82. template <class CharT>
  83. const typename time_formats<CharT>::char_type
  84. time_formats<CharT>::zone_abbrev_format[3] = {'%','z'};
  85. template <class CharT>
  86. const typename time_formats<CharT>::char_type
  87. time_formats<CharT>::zone_name_format[3] = {'%','Z'};
  88. template <class CharT>
  89. const typename time_formats<CharT>::char_type
  90. time_formats<CharT>::zone_iso_format[3] = {'%','q'};
  91. template <class CharT>
  92. const typename time_formats<CharT>::char_type
  93. time_formats<CharT>::zone_iso_extended_format[3] ={'%','Q'};
  94. template <class CharT>
  95. const typename time_formats<CharT>::char_type
  96. time_formats<CharT>::posix_zone_string_format[4] ={'%','Z','P'};
  97. template <class CharT>
  98. const typename time_formats<CharT>::char_type
  99. time_formats<CharT>::duration_seperator[2] = {':'};
  100. template <class CharT>
  101. const typename time_formats<CharT>::char_type
  102. time_formats<CharT>::negative_sign[2] = {'-'};
  103. template <class CharT>
  104. const typename time_formats<CharT>::char_type
  105. time_formats<CharT>::positive_sign[2] = {'+'};
  106. template <class CharT>
  107. const typename time_formats<CharT>::char_type
  108. time_formats<CharT>::duration_sign_negative_only[3] ={'%','-'};
  109. template <class CharT>
  110. const typename time_formats<CharT>::char_type
  111. time_formats<CharT>::duration_sign_always[3] ={'%','+'};
  112. template <class CharT>
  113. const typename time_formats<CharT>::char_type
  114. time_formats<CharT>::iso_time_format_specifier[18] =
  115. {'%', 'Y', '%', 'm', '%', 'd', 'T',
  116. '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' };
  117. template <class CharT>
  118. const typename time_formats<CharT>::char_type
  119. time_formats<CharT>::iso_time_format_extended_specifier[22] =
  120. {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ',
  121. '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'};
  122. template <class CharT>
  123. const typename time_formats<CharT>::char_type
  124. time_formats<CharT>::default_time_format[23] =
  125. {'%','Y','-','%','b','-','%','d',' ',
  126. '%','H',':','%','M',':','%','S','%','F',' ','%','z'};
  127. template <class CharT>
  128. const typename time_formats<CharT>::char_type
  129. time_formats<CharT>::default_time_input_format[24] =
  130. {'%','Y','-','%','b','-','%','d',' ',
  131. '%','H',':','%','M',':','%','S','%','F',' ','%','Z','P'};
  132. template <class CharT>
  133. const typename time_formats<CharT>::char_type
  134. time_formats<CharT>::default_time_duration_format[11] =
  135. {'%','H',':','%','M',':','%','S','%','F'};
  136. /*! Facet used for format-based output of time types
  137. * This class provides for the use of format strings to output times. In addition
  138. * to the flags for formatting date elements, the following are the allowed format flags:
  139. * - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z")
  140. * - %f => fractional seconds ".123456"
  141. * - %F => fractional seconds or none: like frac sec but empty if frac sec == 0
  142. * - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f)
  143. * - %S => seconds "02"
  144. * - %z => abbreviated time zone "EDT"
  145. * - %Z => full time zone name "Eastern Daylight Time"
  146. */
  147. template <class time_type,
  148. class CharT,
  149. class OutItrT = std::ostreambuf_iterator<CharT, std::char_traits<CharT> > >
  150. class time_facet :
  151. public boost::date_time::date_facet<typename time_type::date_type , CharT, OutItrT> {
  152. public:
  153. typedef typename time_type::date_type date_type;
  154. typedef typename time_type::time_duration_type time_duration_type;
  155. typedef boost::date_time::period<time_type,time_duration_type> period_type;
  156. typedef boost::date_time::date_facet<typename time_type::date_type, CharT, OutItrT> base_type;
  157. typedef typename base_type::string_type string_type;
  158. typedef typename base_type::char_type char_type;
  159. typedef typename base_type::period_formatter_type period_formatter_type;
  160. typedef typename base_type::special_values_formatter_type special_values_formatter_type;
  161. typedef typename base_type::date_gen_formatter_type date_gen_formatter_type;
  162. static const char_type* fractional_seconds_format; // %f
  163. static const char_type* fractional_seconds_or_none_format; // %F
  164. static const char_type* seconds_with_fractional_seconds_format; // %s
  165. static const char_type* seconds_format; // %S
  166. static const char_type* hours_format; // %H
  167. static const char_type* unrestricted_hours_format; // %O
  168. static const char_type* standard_format; // %x X
  169. static const char_type* zone_abbrev_format; // %z
  170. static const char_type* zone_name_format; // %Z
  171. static const char_type* zone_iso_format; // %q
  172. static const char_type* zone_iso_extended_format; // %Q
  173. static const char_type* posix_zone_string_format; // %ZP
  174. static const char_type* duration_seperator;
  175. static const char_type* duration_sign_always; // %+
  176. static const char_type* duration_sign_negative_only; // %-
  177. static const char_type* negative_sign; //-
  178. static const char_type* positive_sign; //+
  179. static const char_type* iso_time_format_specifier;
  180. static const char_type* iso_time_format_extended_specifier;
  181. //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz]
  182. static const char_type* default_time_format;
  183. //default time_duration format is HH:MM:SS[.fff...]
  184. static const char_type* default_time_duration_format;
  185. static std::locale::id id;
  186. #if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
  187. std::locale::id& __get_id (void) const { return id; }
  188. #endif
  189. //! sets default formats for ptime, local_date_time, and time_duration
  190. explicit time_facet(::size_t a_ref = 0)
  191. : base_type(default_time_format, period_formatter_type(), special_values_formatter_type(), date_gen_formatter_type(), a_ref),
  192. m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format)
  193. {}
  194. //! Construct the facet with an explicitly specified format
  195. explicit time_facet(const char_type* a_format,
  196. period_formatter_type period_formatter = period_formatter_type(),
  197. const special_values_formatter_type& special_value_formatter = special_values_formatter_type(),
  198. date_gen_formatter_type dg_formatter = date_gen_formatter_type(),
  199. ::size_t a_ref = 0)
  200. : base_type(a_format,
  201. period_formatter,
  202. special_value_formatter,
  203. dg_formatter,
  204. a_ref),
  205. m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format)
  206. {}
  207. //! Changes format for time_duration
  208. void time_duration_format(const char_type* const format)
  209. {
  210. m_time_duration_format = format;
  211. }
  212. virtual void set_iso_format()
  213. {
  214. this->m_format = iso_time_format_specifier;
  215. }
  216. virtual void set_iso_extended_format()
  217. {
  218. this->m_format = iso_time_format_extended_specifier;
  219. }
  220. OutItrT put(OutItrT a_next,
  221. std::ios_base& a_ios,
  222. char_type a_fill,
  223. const time_type& a_time) const
  224. {
  225. if (a_time.is_special()) {
  226. return this->do_put_special(a_next, a_ios, a_fill,
  227. a_time.date().as_special());
  228. }
  229. string_type format(this->m_format);
  230. string_type frac_str;
  231. if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) {
  232. // replace %s with %S.nnn
  233. frac_str =
  234. fractional_seconds_as_string(a_time.time_of_day(), false);
  235. char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point();
  236. string_type replace_string(seconds_format);
  237. replace_string += sep;
  238. replace_string += frac_str;
  239. boost::algorithm::replace_all(format,
  240. seconds_with_fractional_seconds_format,
  241. replace_string);
  242. }
  243. /* NOTE: replacing posix_zone_string_format must be done BEFORE
  244. * zone_name_format: "%ZP" & "%Z", if Z is checked first it will
  245. * incorrectly replace a zone_name where a posix_string should go */
  246. if (format.find(posix_zone_string_format) != string_type::npos) {
  247. if(a_time.zone_abbrev().empty()) {
  248. // if zone_abbrev() returns an empty string, we want to
  249. // erase posix_zone_string_format from format
  250. boost::algorithm::erase_all(format, posix_zone_string_format);
  251. }
  252. else{
  253. boost::algorithm::replace_all(format,
  254. posix_zone_string_format,
  255. a_time.zone_as_posix_string());
  256. }
  257. }
  258. if (format.find(zone_name_format) != string_type::npos) {
  259. if(a_time.zone_name().empty()) {
  260. /* TODO: this'll probably create problems if a user places
  261. * the zone_*_format flag in the format with a ptime. This
  262. * code removes the flag from the default formats */
  263. // if zone_name() returns an empty string, we want to
  264. // erase zone_name_format & one preceeding space
  265. std::basic_ostringstream<char_type> ss;
  266. ss << ' ' << zone_name_format;
  267. boost::algorithm::erase_all(format, ss.str());
  268. }
  269. else{
  270. boost::algorithm::replace_all(format,
  271. zone_name_format,
  272. a_time.zone_name());
  273. }
  274. }
  275. if (format.find(zone_abbrev_format) != string_type::npos) {
  276. if(a_time.zone_abbrev(false).empty()) {
  277. /* TODO: this'll probably create problems if a user places
  278. * the zone_*_format flag in the format with a ptime. This
  279. * code removes the flag from the default formats */
  280. // if zone_abbrev() returns an empty string, we want to
  281. // erase zone_abbrev_format & one preceeding space
  282. std::basic_ostringstream<char_type> ss;
  283. ss << ' ' << zone_abbrev_format;
  284. boost::algorithm::erase_all(format, ss.str());
  285. }
  286. else{
  287. boost::algorithm::replace_all(format,
  288. zone_abbrev_format,
  289. a_time.zone_abbrev(false));
  290. }
  291. }
  292. if (format.find(zone_iso_extended_format) != string_type::npos) {
  293. if(a_time.zone_name(true).empty()) {
  294. /* TODO: this'll probably create problems if a user places
  295. * the zone_*_format flag in the format with a ptime. This
  296. * code removes the flag from the default formats */
  297. // if zone_name() returns an empty string, we want to
  298. // erase zone_iso_extended_format from format
  299. boost::algorithm::erase_all(format, zone_iso_extended_format);
  300. }
  301. else{
  302. boost::algorithm::replace_all(format,
  303. zone_iso_extended_format,
  304. a_time.zone_name(true));
  305. }
  306. }
  307. if (format.find(zone_iso_format) != string_type::npos) {
  308. if(a_time.zone_abbrev(true).empty()) {
  309. /* TODO: this'll probably create problems if a user places
  310. * the zone_*_format flag in the format with a ptime. This
  311. * code removes the flag from the default formats */
  312. // if zone_abbrev() returns an empty string, we want to
  313. // erase zone_iso_format from format
  314. boost::algorithm::erase_all(format, zone_iso_format);
  315. }
  316. else{
  317. boost::algorithm::replace_all(format,
  318. zone_iso_format,
  319. a_time.zone_abbrev(true));
  320. }
  321. }
  322. if (format.find(fractional_seconds_format) != string_type::npos) {
  323. // replace %f with nnnnnnn
  324. if (!frac_str.size()) {
  325. frac_str = fractional_seconds_as_string(a_time.time_of_day(), false);
  326. }
  327. boost::algorithm::replace_all(format,
  328. fractional_seconds_format,
  329. frac_str);
  330. }
  331. if (format.find(fractional_seconds_or_none_format) != string_type::npos) {
  332. // replace %F with nnnnnnn or nothing if fs == 0
  333. frac_str =
  334. fractional_seconds_as_string(a_time.time_of_day(), true);
  335. if (frac_str.size()) {
  336. char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point();
  337. string_type replace_string;
  338. replace_string += sep;
  339. replace_string += frac_str;
  340. boost::algorithm::replace_all(format,
  341. fractional_seconds_or_none_format,
  342. replace_string);
  343. }
  344. else {
  345. boost::algorithm::erase_all(format,
  346. fractional_seconds_or_none_format);
  347. }
  348. }
  349. return this->do_put_tm(a_next, a_ios, a_fill,
  350. to_tm(a_time), format);
  351. }
  352. //! put function for time_duration
  353. OutItrT put(OutItrT a_next,
  354. std::ios_base& a_ios,
  355. char_type a_fill,
  356. const time_duration_type& a_time_dur) const
  357. {
  358. if (a_time_dur.is_special()) {
  359. return this->do_put_special(a_next, a_ios, a_fill,
  360. a_time_dur.get_rep().as_special());
  361. }
  362. string_type format(m_time_duration_format);
  363. if (a_time_dur.is_negative()) {
  364. // replace %- with minus sign. Should we use the numpunct facet?
  365. boost::algorithm::replace_all(format,
  366. duration_sign_negative_only,
  367. negative_sign);
  368. // remove all the %+ in the string with '-'
  369. boost::algorithm::replace_all(format,
  370. duration_sign_always,
  371. negative_sign);
  372. }
  373. else { //duration is positive
  374. // remove all the %- combos from the string
  375. boost::algorithm::erase_all(format, duration_sign_negative_only);
  376. // remove all the %+ in the string with '+'
  377. boost::algorithm::replace_all(format,
  378. duration_sign_always,
  379. positive_sign);
  380. }
  381. /*
  382. * It is possible for a time duration to span more then 24 hours.
  383. * Standard time_put::put is obliged to behave the same as strftime
  384. * (See ISO 14882-2003 22.2.5.3.1 par. 1) and strftime's behavior is
  385. * unspecified for the case when tm_hour field is outside 0-23 range
  386. * (See ISO 9899-1999 7.23.3.5 par. 3). So we must output %H and %O
  387. * here ourself.
  388. */
  389. string_type hours_str;
  390. if (format.find(unrestricted_hours_format) != string_type::npos) {
  391. hours_str = hours_as_string(a_time_dur);
  392. boost::algorithm::replace_all(format, unrestricted_hours_format, hours_str);
  393. }
  394. // We still have to process restricted hours format specifier. In order to
  395. // support parseability of durations in ISO format (%H%M%S), we'll have to
  396. // restrict the stringified hours length to 2 characters.
  397. if (format.find(hours_format) != string_type::npos) {
  398. if (hours_str.empty())
  399. hours_str = hours_as_string(a_time_dur);
  400. BOOST_ASSERT(hours_str.length() <= 2);
  401. boost::algorithm::replace_all(format, hours_format, hours_str);
  402. }
  403. string_type frac_str;
  404. if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) {
  405. // replace %s with %S.nnn
  406. frac_str =
  407. fractional_seconds_as_string(a_time_dur, false);
  408. char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point();
  409. string_type replace_string(seconds_format);
  410. replace_string += sep;
  411. replace_string += frac_str;
  412. boost::algorithm::replace_all(format,
  413. seconds_with_fractional_seconds_format,
  414. replace_string);
  415. }
  416. if (format.find(fractional_seconds_format) != string_type::npos) {
  417. // replace %f with nnnnnnn
  418. if (!frac_str.size()) {
  419. frac_str = fractional_seconds_as_string(a_time_dur, false);
  420. }
  421. boost::algorithm::replace_all(format,
  422. fractional_seconds_format,
  423. frac_str);
  424. }
  425. if (format.find(fractional_seconds_or_none_format) != string_type::npos) {
  426. // replace %F with nnnnnnn or nothing if fs == 0
  427. frac_str =
  428. fractional_seconds_as_string(a_time_dur, true);
  429. if (frac_str.size()) {
  430. char_type sep = std::use_facet<std::numpunct<char_type> >(a_ios.getloc()).decimal_point();
  431. string_type replace_string;
  432. replace_string += sep;
  433. replace_string += frac_str;
  434. boost::algorithm::replace_all(format,
  435. fractional_seconds_or_none_format,
  436. replace_string);
  437. }
  438. else {
  439. boost::algorithm::erase_all(format,
  440. fractional_seconds_or_none_format);
  441. }
  442. }
  443. return this->do_put_tm(a_next, a_ios, a_fill,
  444. to_tm(a_time_dur), format);
  445. }
  446. OutItrT put(OutItrT next, std::ios_base& a_ios,
  447. char_type fill, const period_type& p) const
  448. {
  449. return this->m_period_formatter.put_period(next, a_ios, fill,p,*this);
  450. }
  451. protected:
  452. static
  453. string_type
  454. fractional_seconds_as_string(const time_duration_type& a_time,
  455. bool null_when_zero)
  456. {
  457. typename time_duration_type::fractional_seconds_type frac_sec =
  458. a_time.fractional_seconds();
  459. if (null_when_zero && (frac_sec == 0)) {
  460. return string_type();
  461. }
  462. //make sure there is no sign
  463. return integral_as_string(
  464. date_time::absolute_value(frac_sec),
  465. time_duration_type::num_fractional_digits());
  466. }
  467. static
  468. string_type
  469. hours_as_string(const time_duration_type& a_time, int width = 2)
  470. {
  471. return integral_as_string(date_time::absolute_value(a_time.hours()), width);
  472. }
  473. template< typename IntT >
  474. static
  475. string_type
  476. integral_as_string(IntT val, int width = 2)
  477. {
  478. std::basic_ostringstream<char_type> ss;
  479. ss.imbue(std::locale::classic()); // don't want any formatting
  480. ss << std::setw(width)
  481. << std::setfill(static_cast<char_type>('0'));
  482. #if (defined(BOOST_MSVC) && (_MSC_VER < 1300))
  483. // JDG [7/6/02 VC++ compatibility]
  484. char_type buff[34];
  485. ss << _i64toa(static_cast<boost::int64_t>(val), buff, 10);
  486. #else
  487. ss << val;
  488. #endif
  489. return ss.str();
  490. }
  491. private:
  492. string_type m_time_duration_format;
  493. };
  494. template <class time_type, class CharT, class OutItrT>
  495. std::locale::id time_facet<time_type, CharT, OutItrT>::id;
  496. template <class time_type, class CharT, class OutItrT>
  497. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  498. time_facet<time_type, CharT, OutItrT>::fractional_seconds_format = time_formats<CharT>::fractional_seconds_format;
  499. template <class time_type, class CharT, class OutItrT>
  500. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  501. time_facet<time_type, CharT, OutItrT>::fractional_seconds_or_none_format = time_formats<CharT>::fractional_seconds_or_none_format;
  502. template <class time_type, class CharT, class OutItrT>
  503. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  504. time_facet<time_type, CharT, OutItrT>::seconds_with_fractional_seconds_format =
  505. time_formats<CharT>::seconds_with_fractional_seconds_format;
  506. template <class time_type, class CharT, class OutItrT>
  507. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  508. time_facet<time_type, CharT, OutItrT>::zone_name_format = time_formats<CharT>::zone_name_format;
  509. template <class time_type, class CharT, class OutItrT>
  510. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  511. time_facet<time_type, CharT, OutItrT>::zone_abbrev_format = time_formats<CharT>::zone_abbrev_format;
  512. template <class time_type, class CharT, class OutItrT>
  513. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  514. time_facet<time_type, CharT, OutItrT>::zone_iso_extended_format =time_formats<CharT>::zone_iso_extended_format;
  515. template <class time_type, class CharT, class OutItrT>
  516. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  517. time_facet<time_type, CharT, OutItrT>::posix_zone_string_format =time_formats<CharT>::posix_zone_string_format;
  518. template <class time_type, class CharT, class OutItrT>
  519. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  520. time_facet<time_type, CharT, OutItrT>::zone_iso_format = time_formats<CharT>::zone_iso_format;
  521. template <class time_type, class CharT, class OutItrT>
  522. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  523. time_facet<time_type, CharT, OutItrT>::seconds_format = time_formats<CharT>::seconds_format;
  524. template <class time_type, class CharT, class OutItrT>
  525. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  526. time_facet<time_type, CharT, OutItrT>::hours_format = time_formats<CharT>::hours_format;
  527. template <class time_type, class CharT, class OutItrT>
  528. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  529. time_facet<time_type, CharT, OutItrT>::unrestricted_hours_format = time_formats<CharT>::unrestricted_hours_format;
  530. template <class time_type, class CharT, class OutItrT>
  531. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  532. time_facet<time_type, CharT, OutItrT>::standard_format = time_formats<CharT>::standard_format;
  533. template <class time_type, class CharT, class OutItrT>
  534. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  535. time_facet<time_type, CharT, OutItrT>::duration_seperator = time_formats<CharT>::duration_seperator;
  536. template <class time_type, class CharT, class OutItrT>
  537. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  538. time_facet<time_type, CharT, OutItrT>::negative_sign = time_formats<CharT>::negative_sign;
  539. template <class time_type, class CharT, class OutItrT>
  540. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  541. time_facet<time_type, CharT, OutItrT>::positive_sign = time_formats<CharT>::positive_sign;
  542. template <class time_type, class CharT, class OutItrT>
  543. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  544. time_facet<time_type, CharT, OutItrT>::duration_sign_negative_only = time_formats<CharT>::duration_sign_negative_only;
  545. template <class time_type, class CharT, class OutItrT>
  546. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  547. time_facet<time_type, CharT, OutItrT>::duration_sign_always = time_formats<CharT>::duration_sign_always;
  548. template <class time_type, class CharT, class OutItrT>
  549. const typename time_facet<time_type,CharT, OutItrT>::char_type*
  550. time_facet<time_type,CharT, OutItrT>::iso_time_format_specifier = time_formats<CharT>::iso_time_format_specifier;
  551. template <class time_type, class CharT, class OutItrT>
  552. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  553. time_facet<time_type, CharT, OutItrT>::iso_time_format_extended_specifier = time_formats<CharT>::iso_time_format_extended_specifier;
  554. template <class time_type, class CharT, class OutItrT>
  555. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  556. time_facet<time_type, CharT, OutItrT>::default_time_format =
  557. time_formats<CharT>::default_time_format;
  558. template <class time_type, class CharT, class OutItrT>
  559. const typename time_facet<time_type, CharT, OutItrT>::char_type*
  560. time_facet<time_type, CharT, OutItrT>::default_time_duration_format =
  561. time_formats<CharT>::default_time_duration_format;
  562. //! Facet for format-based input.
  563. /*!
  564. */
  565. template <class time_type,
  566. class CharT,
  567. class InItrT = std::istreambuf_iterator<CharT, std::char_traits<CharT> > >
  568. class time_input_facet :
  569. public boost::date_time::date_input_facet<typename time_type::date_type , CharT, InItrT> {
  570. public:
  571. typedef typename time_type::date_type date_type;
  572. typedef typename time_type::time_duration_type time_duration_type;
  573. typedef typename time_duration_type::fractional_seconds_type fracional_seconds_type;
  574. typedef boost::date_time::period<time_type,time_duration_type> period_type;
  575. typedef boost::date_time::date_input_facet<typename time_type::date_type, CharT, InItrT> base_type;
  576. typedef typename base_type::duration_type date_duration_type;
  577. typedef typename base_type::year_type year_type;
  578. typedef typename base_type::month_type month_type;
  579. typedef typename base_type::day_type day_type;
  580. typedef typename base_type::string_type string_type;
  581. typedef typename string_type::const_iterator const_itr;
  582. typedef typename base_type::char_type char_type;
  583. typedef typename base_type::format_date_parser_type format_date_parser_type;
  584. typedef typename base_type::period_parser_type period_parser_type;
  585. typedef typename base_type::special_values_parser_type special_values_parser_type;
  586. typedef typename base_type::date_gen_parser_type date_gen_parser_type;
  587. typedef typename base_type::special_values_parser_type::match_results match_results;
  588. static const char_type* fractional_seconds_format; // f
  589. static const char_type* fractional_seconds_or_none_format; // F
  590. static const char_type* seconds_with_fractional_seconds_format; // s
  591. static const char_type* seconds_format; // S
  592. static const char_type* standard_format; // x X
  593. static const char_type* zone_abbrev_format; // z
  594. static const char_type* zone_name_format; // Z
  595. static const char_type* zone_iso_format; // q
  596. static const char_type* zone_iso_extended_format; // Q
  597. static const char_type* duration_seperator;
  598. static const char_type* iso_time_format_specifier;
  599. static const char_type* iso_time_format_extended_specifier;
  600. static const char_type* default_time_input_format;
  601. static const char_type* default_time_duration_format;
  602. static std::locale::id id;
  603. //! Constructor that takes a format string for a ptime
  604. explicit time_input_facet(const string_type& format, ::size_t a_ref = 0)
  605. : base_type(format, a_ref),
  606. m_time_duration_format(default_time_duration_format)
  607. { }
  608. explicit time_input_facet(const string_type& format,
  609. const format_date_parser_type& date_parser,
  610. const special_values_parser_type& sv_parser,
  611. const period_parser_type& per_parser,
  612. const date_gen_parser_type& date_gen_parser,
  613. ::size_t a_ref = 0)
  614. : base_type(format,
  615. date_parser,
  616. sv_parser,
  617. per_parser,
  618. date_gen_parser,
  619. a_ref),
  620. m_time_duration_format(default_time_duration_format)
  621. {}
  622. //! sets default formats for ptime, local_date_time, and time_duration
  623. explicit time_input_facet(::size_t a_ref = 0)
  624. : base_type(default_time_input_format, a_ref),
  625. m_time_duration_format(default_time_duration_format)
  626. { }
  627. //! Set the format for time_duration
  628. void time_duration_format(const char_type* const format) {
  629. m_time_duration_format = format;
  630. }
  631. virtual void set_iso_format()
  632. {
  633. this->m_format = iso_time_format_specifier;
  634. }
  635. virtual void set_iso_extended_format()
  636. {
  637. this->m_format = iso_time_format_extended_specifier;
  638. }
  639. InItrT get(InItrT& sitr,
  640. InItrT& stream_end,
  641. std::ios_base& a_ios,
  642. period_type& p) const
  643. {
  644. p = this->m_period_parser.get_period(sitr,
  645. stream_end,
  646. a_ios,
  647. p,
  648. time_duration_type::unit(),
  649. *this);
  650. return sitr;
  651. }
  652. //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz]
  653. //default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...]
  654. InItrT get(InItrT& sitr,
  655. InItrT& stream_end,
  656. std::ios_base& a_ios,
  657. time_duration_type& td) const
  658. {
  659. // skip leading whitespace
  660. while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; }
  661. bool use_current_char = false;
  662. // num_get will consume the +/-, we may need a copy if special_value
  663. char_type c = '\0';
  664. if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) {
  665. c = *sitr;
  666. }
  667. typedef typename time_duration_type::hour_type hour_type;
  668. typedef typename time_duration_type::min_type min_type;
  669. typedef typename time_duration_type::sec_type sec_type;
  670. hour_type hour = 0;
  671. min_type min = 0;
  672. sec_type sec = 0;
  673. typename time_duration_type::fractional_seconds_type frac(0);
  674. typedef std::num_get<CharT, InItrT> num_get;
  675. if(!std::has_facet<num_get>(a_ios.getloc())) {
  676. num_get* ng = new num_get();
  677. std::locale loc = std::locale(a_ios.getloc(), ng);
  678. a_ios.imbue(loc);
  679. }
  680. const_itr itr(m_time_duration_format.begin());
  681. while (itr != m_time_duration_format.end() && (sitr != stream_end)) {
  682. if (*itr == '%') {
  683. ++itr;
  684. if (*itr != '%') {
  685. switch(*itr) {
  686. case 'O':
  687. {
  688. // A period may span more than 24 hours. In that case the format
  689. // string should be composed with the unrestricted hours specifier.
  690. hour = var_string_to_int<hour_type, CharT>(sitr, stream_end,
  691. std::numeric_limits<hour_type>::digits10 + 1);
  692. if(hour == -1){
  693. return check_special_value(sitr, stream_end, td, c);
  694. }
  695. break;
  696. }
  697. case 'H':
  698. {
  699. match_results mr;
  700. hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2);
  701. if(hour == -1){
  702. return check_special_value(sitr, stream_end, td, c);
  703. }
  704. break;
  705. }
  706. case 'M':
  707. {
  708. match_results mr;
  709. min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2);
  710. if(min == -1){
  711. return check_special_value(sitr, stream_end, td, c);
  712. }
  713. break;
  714. }
  715. case 's':
  716. case 'S':
  717. {
  718. match_results mr;
  719. sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2);
  720. if(sec == -1){
  721. return check_special_value(sitr, stream_end, td, c);
  722. }
  723. if (*itr == 'S')
  724. break;
  725. // %s is the same as %S%f so we drop through into %f
  726. }
  727. case 'f':
  728. {
  729. // check for decimal, check special_values if missing
  730. if(*sitr == '.') {
  731. ++sitr;
  732. parse_frac_type(sitr, stream_end, frac);
  733. // sitr will point to next expected char after this parsing
  734. // is complete so no need to advance it
  735. use_current_char = true;
  736. }
  737. else {
  738. return check_special_value(sitr, stream_end, td, c);
  739. }
  740. break;
  741. }
  742. case 'F':
  743. {
  744. // check for decimal, skip if missing
  745. if(*sitr == '.') {
  746. ++sitr;
  747. parse_frac_type(sitr, stream_end, frac);
  748. // sitr will point to next expected char after this parsing
  749. // is complete so no need to advance it
  750. use_current_char = true;
  751. }
  752. else {
  753. // nothing was parsed so we don't want to advance sitr
  754. use_current_char = true;
  755. }
  756. break;
  757. }
  758. default:
  759. {} // ignore what we don't understand?
  760. }// switch
  761. }
  762. else { // itr == '%', second consecutive
  763. ++sitr;
  764. }
  765. ++itr; //advance past format specifier
  766. }
  767. else { //skip past chars in format and in buffer
  768. ++itr;
  769. // set use_current_char when sitr is already
  770. // pointing at the next character to process
  771. if (use_current_char) {
  772. use_current_char = false;
  773. }
  774. else {
  775. ++sitr;
  776. }
  777. }
  778. }
  779. td = time_duration_type(hour, min, sec, frac);
  780. return sitr;
  781. }
  782. //! Parses a time object from the input stream
  783. InItrT get(InItrT& sitr,
  784. InItrT& stream_end,
  785. std::ios_base& a_ios,
  786. time_type& t) const
  787. {
  788. string_type tz_str;
  789. return get(sitr, stream_end, a_ios, t, tz_str, false);
  790. }
  791. //! Expects a time_zone in the input stream
  792. InItrT get_local_time(InItrT& sitr,
  793. InItrT& stream_end,
  794. std::ios_base& a_ios,
  795. time_type& t,
  796. string_type& tz_str) const
  797. {
  798. return get(sitr, stream_end, a_ios, t, tz_str, true);
  799. }
  800. protected:
  801. InItrT get(InItrT& sitr,
  802. InItrT& stream_end,
  803. std::ios_base& a_ios,
  804. time_type& t,
  805. string_type& tz_str,
  806. bool time_is_local) const
  807. {
  808. // skip leading whitespace
  809. while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; }
  810. bool use_current_char = false;
  811. bool use_current_format_char = false; // used whith two character flags
  812. // num_get will consume the +/-, we may need a copy if special_value
  813. char_type c = '\0';
  814. if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) {
  815. c = *sitr;
  816. }
  817. typedef typename time_duration_type::hour_type hour_type;
  818. typedef typename time_duration_type::min_type min_type;
  819. typedef typename time_duration_type::sec_type sec_type;
  820. // time elements
  821. hour_type hour = 0;
  822. min_type min = 0;
  823. sec_type sec = 0;
  824. typename time_duration_type::fractional_seconds_type frac(0);
  825. // date elements
  826. short day_of_year(0);
  827. /* Initialized the following to their minimum values. These intermediate
  828. * objects are used so we get specific exceptions when part of the input
  829. * is unparsable.
  830. * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/
  831. year_type t_year(1400);
  832. month_type t_month(1);
  833. day_type t_day(1);
  834. typedef std::num_get<CharT, InItrT> num_get;
  835. if(!std::has_facet<num_get>(a_ios.getloc())) {
  836. num_get* ng = new num_get();
  837. std::locale loc = std::locale(a_ios.getloc(), ng);
  838. a_ios.imbue(loc);
  839. }
  840. const_itr itr(this->m_format.begin());
  841. while (itr != this->m_format.end() && (sitr != stream_end)) {
  842. if (*itr == '%') {
  843. ++itr;
  844. if (*itr != '%') {
  845. // the cases are grouped by date & time flags - not alphabetical order
  846. switch(*itr) {
  847. // date flags
  848. case 'Y':
  849. case 'y':
  850. {
  851. char_type cs[3] = { '%', *itr };
  852. string_type s(cs);
  853. match_results mr;
  854. try {
  855. t_year = this->m_parser.parse_year(sitr, stream_end, s, mr);
  856. }
  857. catch(std::out_of_range&) { // base class for bad_year exception
  858. if(this->m_sv_parser.match(sitr, stream_end, mr)) {
  859. t = time_type(static_cast<special_values>(mr.current_match));
  860. return sitr;
  861. }
  862. else {
  863. throw; // rethrow bad_year
  864. }
  865. }
  866. break;
  867. }
  868. case 'B':
  869. case 'b':
  870. case 'm':
  871. {
  872. char_type cs[3] = { '%', *itr };
  873. string_type s(cs);
  874. match_results mr;
  875. try {
  876. t_month = this->m_parser.parse_month(sitr, stream_end, s, mr);
  877. }
  878. catch(std::out_of_range&) { // base class for bad_month exception
  879. if(this->m_sv_parser.match(sitr, stream_end, mr)) {
  880. t = time_type(static_cast<special_values>(mr.current_match));
  881. return sitr;
  882. }
  883. else {
  884. throw; // rethrow bad_month
  885. }
  886. }
  887. // did m_parser already advance sitr to next char?
  888. if(mr.has_remaining()) {
  889. use_current_char = true;
  890. }
  891. break;
  892. }
  893. case 'a':
  894. case 'A':
  895. case 'w':
  896. {
  897. // weekday is not used in construction but we need to get it out of the stream
  898. char_type cs[3] = { '%', *itr };
  899. string_type s(cs);
  900. match_results mr;
  901. typename date_type::day_of_week_type wd(0);
  902. try {
  903. wd = this->m_parser.parse_weekday(sitr, stream_end, s, mr);
  904. }
  905. catch(std::out_of_range&) { // base class for bad_weekday exception
  906. if(this->m_sv_parser.match(sitr, stream_end, mr)) {
  907. t = time_type(static_cast<special_values>(mr.current_match));
  908. return sitr;
  909. }
  910. else {
  911. throw; // rethrow bad_weekday
  912. }
  913. }
  914. // did m_parser already advance sitr to next char?
  915. if(mr.has_remaining()) {
  916. use_current_char = true;
  917. }
  918. break;
  919. }
  920. case 'j':
  921. {
  922. // code that gets julian day (from format_date_parser)
  923. match_results mr;
  924. day_of_year = fixed_string_to_int<unsigned short, CharT>(sitr, stream_end, mr, 3);
  925. if(day_of_year == -1) {
  926. if(this->m_sv_parser.match(sitr, stream_end, mr)) {
  927. t = time_type(static_cast<special_values>(mr.current_match));
  928. return sitr;
  929. }
  930. }
  931. // these next two lines are so we get an exception with bad input
  932. typedef typename time_type::date_type::day_of_year_type day_of_year_type;
  933. day_of_year_type t_day_of_year(day_of_year);
  934. break;
  935. }
  936. case 'd':
  937. {
  938. try {
  939. t_day = this->m_parser.parse_day_of_month(sitr, stream_end);
  940. }
  941. catch(std::out_of_range&) { // base class for exception bad_day_of_month
  942. match_results mr;
  943. if(this->m_sv_parser.match(sitr, stream_end, mr)) {
  944. t = time_type(static_cast<special_values>(mr.current_match));
  945. return sitr;
  946. }
  947. else {
  948. throw; // rethrow bad_day_of_month
  949. }
  950. }
  951. break;
  952. }
  953. // time flags
  954. case 'H':
  955. {
  956. match_results mr;
  957. hour = fixed_string_to_int<hour_type, CharT>(sitr, stream_end, mr, 2);
  958. if(hour == -1){
  959. return check_special_value(sitr, stream_end, t, c);
  960. }
  961. break;
  962. }
  963. case 'M':
  964. {
  965. match_results mr;
  966. min = fixed_string_to_int<min_type, CharT>(sitr, stream_end, mr, 2);
  967. if(min == -1){
  968. return check_special_value(sitr, stream_end, t, c);
  969. }
  970. break;
  971. }
  972. case 's':
  973. case 'S':
  974. {
  975. match_results mr;
  976. sec = fixed_string_to_int<sec_type, CharT>(sitr, stream_end, mr, 2);
  977. if(sec == -1){
  978. return check_special_value(sitr, stream_end, t, c);
  979. }
  980. if (*itr == 'S')
  981. break;
  982. // %s is the same as %S%f so we drop through into %f
  983. }
  984. case 'f':
  985. {
  986. // check for decimal, check SV if missing
  987. if(*sitr == '.') {
  988. ++sitr;
  989. parse_frac_type(sitr, stream_end, frac);
  990. // sitr will point to next expected char after this parsing
  991. // is complete so no need to advance it
  992. use_current_char = true;
  993. }
  994. else {
  995. return check_special_value(sitr, stream_end, t, c);
  996. }
  997. break;
  998. }
  999. case 'F':
  1000. {
  1001. // check for decimal, skip if missing
  1002. if(*sitr == '.') {
  1003. ++sitr;
  1004. parse_frac_type(sitr, stream_end, frac);
  1005. // sitr will point to next expected char after this parsing
  1006. // is complete so no need to advance it
  1007. use_current_char = true;
  1008. }
  1009. else {
  1010. // nothing was parsed so we don't want to advance sitr
  1011. use_current_char = true;
  1012. }
  1013. break;
  1014. }
  1015. // time_zone flags
  1016. //case 'q':
  1017. //case 'Q':
  1018. //case 'z':
  1019. case 'Z':
  1020. {
  1021. if(time_is_local) { // skip if 't' is a ptime
  1022. ++itr;
  1023. if(*itr == 'P') {
  1024. // skip leading whitespace
  1025. while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; }
  1026. // parse zone
  1027. while((sitr != stream_end) && (!std::isspace(*sitr))) {
  1028. tz_str += *sitr;
  1029. ++sitr;
  1030. }
  1031. }
  1032. else {
  1033. use_current_format_char = true;
  1034. }
  1035. }
  1036. else {
  1037. // nothing was parsed so we don't want to advance sitr
  1038. use_current_char = true;
  1039. }
  1040. break;
  1041. }
  1042. default:
  1043. {} // ignore what we don't understand?
  1044. }// switch
  1045. }
  1046. else { // itr == '%', second consecutive
  1047. ++sitr;
  1048. }
  1049. if(use_current_format_char) {
  1050. use_current_format_char = false;
  1051. }
  1052. else {
  1053. ++itr; //advance past format specifier
  1054. }
  1055. }
  1056. else { //skip past chars in format and in buffer
  1057. ++itr;
  1058. // set use_current_char when sitr is already
  1059. // pointing at the next character to process
  1060. if (use_current_char) {
  1061. use_current_char = false;
  1062. }
  1063. else {
  1064. ++sitr;
  1065. }
  1066. }
  1067. }
  1068. date_type d(not_a_date_time);
  1069. if (day_of_year > 0) {
  1070. d = date_type(static_cast<unsigned short>(t_year-1),12,31) + date_duration_type(day_of_year);
  1071. }
  1072. else {
  1073. d = date_type(t_year, t_month, t_day);
  1074. }
  1075. time_duration_type td(hour, min, sec, frac);
  1076. t = time_type(d, td);
  1077. return sitr;
  1078. }
  1079. //! Helper function to check for special_value
  1080. /*! First character may have been consumed during original parse
  1081. * attempt. Parameter 'c' should be a copy of that character.
  1082. * Throws ios_base::failure if parse fails. */
  1083. template<class temporal_type>
  1084. inline
  1085. InItrT check_special_value(InItrT& sitr,InItrT& stream_end, temporal_type& tt, char_type c='\0') const
  1086. {
  1087. match_results mr;
  1088. if((c == '-' || c == '+') && (*sitr != c)) { // was the first character consumed?
  1089. mr.cache += c;
  1090. }
  1091. this->m_sv_parser.match(sitr, stream_end, mr);
  1092. if(mr.current_match == match_results::PARSE_ERROR) {
  1093. std::string tmp = convert_string_type<char_type, char>(mr.cache);
  1094. boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + tmp + "'"));
  1095. BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return sitr); // should never reach
  1096. }
  1097. tt = temporal_type(static_cast<special_values>(mr.current_match));
  1098. return sitr;
  1099. }
  1100. //! Helper function for parsing a fractional second type from the stream
  1101. void parse_frac_type(InItrT& sitr,
  1102. InItrT& stream_end,
  1103. fracional_seconds_type& frac) const
  1104. {
  1105. string_type cache;
  1106. while((sitr != stream_end) && std::isdigit(*sitr)) {
  1107. cache += *sitr;
  1108. ++sitr;
  1109. }
  1110. if(cache.size() > 0) {
  1111. unsigned short precision = time_duration_type::num_fractional_digits();
  1112. // input may be only the first few decimal places
  1113. if(cache.size() < precision) {
  1114. frac = lexical_cast<fracional_seconds_type>(cache);
  1115. frac = decimal_adjust(frac, static_cast<unsigned short>(precision - cache.size()));
  1116. }
  1117. else {
  1118. // if input has too many decimal places, drop excess digits
  1119. frac = lexical_cast<fracional_seconds_type>(cache.substr(0, precision));
  1120. }
  1121. }
  1122. }
  1123. private:
  1124. string_type m_time_duration_format;
  1125. //! Helper function to adjust trailing zeros when parsing fractional digits
  1126. template<class int_type>
  1127. inline
  1128. int_type decimal_adjust(int_type val, const unsigned short places) const
  1129. {
  1130. unsigned long factor = 1;
  1131. for(int i = 0; i < places; ++i){
  1132. factor *= 10; // shift decimal to the right
  1133. }
  1134. return val * factor;
  1135. }
  1136. };
  1137. template <class time_type, class CharT, class InItrT>
  1138. std::locale::id time_input_facet<time_type, CharT, InItrT>::id;
  1139. template <class time_type, class CharT, class InItrT>
  1140. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1141. time_input_facet<time_type, CharT, InItrT>::fractional_seconds_format = time_formats<CharT>::fractional_seconds_format;
  1142. template <class time_type, class CharT, class InItrT>
  1143. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1144. time_input_facet<time_type, CharT, InItrT>::fractional_seconds_or_none_format = time_formats<CharT>::fractional_seconds_or_none_format;
  1145. template <class time_type, class CharT, class InItrT>
  1146. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1147. time_input_facet<time_type, CharT, InItrT>::seconds_with_fractional_seconds_format = time_formats<CharT>::seconds_with_fractional_seconds_format;
  1148. template <class time_type, class CharT, class InItrT>
  1149. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1150. time_input_facet<time_type, CharT, InItrT>::seconds_format = time_formats<CharT>::seconds_format;
  1151. template <class time_type, class CharT, class InItrT>
  1152. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1153. time_input_facet<time_type, CharT, InItrT>::standard_format = time_formats<CharT>::standard_format;
  1154. template <class time_type, class CharT, class InItrT>
  1155. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1156. time_input_facet<time_type, CharT, InItrT>::zone_abbrev_format = time_formats<CharT>::zone_abbrev_format;
  1157. template <class time_type, class CharT, class InItrT>
  1158. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1159. time_input_facet<time_type, CharT, InItrT>::zone_name_format = time_formats<CharT>::zone_name_format;
  1160. template <class time_type, class CharT, class InItrT>
  1161. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1162. time_input_facet<time_type, CharT, InItrT>::zone_iso_format = time_formats<CharT>::zone_iso_format;
  1163. template <class time_type, class CharT, class InItrT>
  1164. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1165. time_input_facet<time_type, CharT, InItrT>::zone_iso_extended_format = time_formats<CharT>::zone_iso_extended_format;
  1166. template <class time_type, class CharT, class InItrT>
  1167. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1168. time_input_facet<time_type, CharT, InItrT>::duration_seperator = time_formats<CharT>::duration_seperator;
  1169. template <class time_type, class CharT, class InItrT>
  1170. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1171. time_input_facet<time_type, CharT, InItrT>::iso_time_format_specifier = time_formats<CharT>::iso_time_format_specifier;
  1172. template <class time_type, class CharT, class InItrT>
  1173. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1174. time_input_facet<time_type, CharT, InItrT>::iso_time_format_extended_specifier = time_formats<CharT>::iso_time_format_extended_specifier;
  1175. template <class time_type, class CharT, class InItrT>
  1176. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1177. time_input_facet<time_type, CharT, InItrT>::default_time_input_format = time_formats<CharT>::default_time_input_format;
  1178. template <class time_type, class CharT, class InItrT>
  1179. const typename time_input_facet<time_type, CharT, InItrT>::char_type*
  1180. time_input_facet<time_type, CharT, InItrT>::default_time_duration_format = time_formats<CharT>::default_time_duration_format;
  1181. } } // namespaces
  1182. #endif