date_time.hpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. //
  2. // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. #ifndef BOOST_LOCALE_DATE_TIME_HPP_INCLUDED
  7. #define BOOST_LOCALE_DATE_TIME_HPP_INCLUDED
  8. #include <boost/locale/date_time_facet.hpp>
  9. #include <boost/locale/formatting.hpp>
  10. #include <boost/locale/hold_ptr.hpp>
  11. #include <boost/locale/time_zone.hpp>
  12. #include <locale>
  13. #include <stdexcept>
  14. #include <vector>
  15. #ifdef BOOST_MSVC
  16. # pragma warning(push)
  17. # pragma warning(disable : 4275 4251 4231 4660)
  18. #endif
  19. namespace boost { namespace locale {
  20. /// \defgroup date_time Date, Time, Timezone and Calendar manipulations
  21. ///
  22. /// This module provides various calendar, timezone and date time services
  23. /// @{
  24. /// \brief This error is thrown in case of invalid state that occurred
  25. class BOOST_SYMBOL_VISIBLE date_time_error : public std::runtime_error {
  26. public:
  27. /// Constructor of date_time_error class
  28. date_time_error(const std::string& e) : std::runtime_error(e) {}
  29. };
  30. /// \brief This class represents a pair of period_type and the integer
  31. /// values that describes its amount. For example 3 days or 4 years.
  32. ///
  33. /// Usually obtained as product of period_type and integer or
  34. /// my calling a representative functions
  35. /// For example day()*3 == date_time_period(day(),3) == day(3)
  36. struct date_time_period {
  37. period::period_type type; ///< The type of period, i.e. era, year, day etc.
  38. int value; ///< The value the actual number of \a periods
  39. /// Operator + returns copy of itself
  40. date_time_period operator+() const { return *this; }
  41. /// Operator -, switches the sign of period
  42. date_time_period operator-() const { return date_time_period(type, -value); }
  43. /// Constructor that creates date_time_period from period_type \a f and a value \a v -- default 1.
  44. date_time_period(period::period_type f = period::period_type(), int v = 1) : type(f), value(v) {}
  45. };
  46. namespace period {
  47. /// Get period_type for: special invalid value, should not be used directly
  48. inline period_type invalid()
  49. {
  50. return period_type(marks::invalid);
  51. }
  52. /// Get period_type for: Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
  53. inline period_type era()
  54. {
  55. return period_type(marks::era);
  56. }
  57. /// Get period_type for: Year, it is calendar specific, for example 2011 in Gregorian calendar.
  58. inline period_type year()
  59. {
  60. return period_type(marks::year);
  61. }
  62. /// Get period_type for: Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
  63. inline period_type extended_year()
  64. {
  65. return period_type(marks::extended_year);
  66. }
  67. /// Get period_type for: The month of year, calendar specific, in Gregorian [0..11]
  68. inline period_type month()
  69. {
  70. return period_type(marks::month);
  71. }
  72. /// Get period_type for: The day of month, calendar specific, in Gregorian [1..31]
  73. inline period_type day()
  74. {
  75. return period_type(marks::day);
  76. }
  77. /// Get period_type for: The number of day in year, starting from 1, in Gregorian [1..366]
  78. inline period_type day_of_year()
  79. {
  80. return period_type(marks::day_of_year);
  81. }
  82. /// Get period_type for: Day of week, Sunday=1, Monday=2,..., Saturday=7.
  83. ///
  84. /// Note that updating this value respects local day of week, so for example,
  85. /// If first day of week is Monday and the current day is Tuesday then setting
  86. /// the value to Sunday (1) would forward the date by 5 days forward and not backward
  87. /// by two days as it could be expected if the numbers were taken as is.
  88. inline period_type day_of_week()
  89. {
  90. return period_type(marks::day_of_week);
  91. }
  92. /// Get period_type for: Original number of the day of the week in month. For example 1st Sunday,
  93. /// 2nd Sunday, etc. in Gregorian [1..5]
  94. inline period_type day_of_week_in_month()
  95. {
  96. return period_type(marks::day_of_week_in_month);
  97. }
  98. /// Get period_type for: Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
  99. inline period_type day_of_week_local()
  100. {
  101. return period_type(marks::day_of_week_local);
  102. }
  103. /// Get period_type for: 24 clock hour [0..23]
  104. inline period_type hour()
  105. {
  106. return period_type(marks::hour);
  107. }
  108. /// Get period_type for: 12 clock hour [0..11]
  109. inline period_type hour_12()
  110. {
  111. return period_type(marks::hour_12);
  112. }
  113. /// Get period_type for: am or pm marker [0..1]
  114. inline period_type am_pm()
  115. {
  116. return period_type(marks::am_pm);
  117. }
  118. /// Get period_type for: minute [0..59]
  119. inline period_type minute()
  120. {
  121. return period_type(marks::minute);
  122. }
  123. /// Get period_type for: second [0..59]
  124. inline period_type second()
  125. {
  126. return period_type(marks::second);
  127. }
  128. /// Get period_type for: The week number in the year
  129. inline period_type week_of_year()
  130. {
  131. return period_type(marks::week_of_year);
  132. }
  133. /// Get period_type for: The week number within current month
  134. inline period_type week_of_month()
  135. {
  136. return period_type(marks::week_of_month);
  137. }
  138. /// Get period_type for: First day of week, constant, for example Sunday in US = 1, Monday in France = 2
  139. inline period_type first_day_of_week()
  140. {
  141. return period_type(marks::first_day_of_week);
  142. }
  143. /// Get date_time_period for: Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
  144. inline date_time_period era(int v)
  145. {
  146. return date_time_period(era(), v);
  147. }
  148. /// Get date_time_period for: Year, it is calendar specific, for example 2011 in Gregorian calendar.
  149. inline date_time_period year(int v)
  150. {
  151. return date_time_period(year(), v);
  152. }
  153. /// Get date_time_period for: Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
  154. inline date_time_period extended_year(int v)
  155. {
  156. return date_time_period(extended_year(), v);
  157. }
  158. /// Get date_time_period for: The month of year, calendar specific, in Gregorian [0..11]
  159. inline date_time_period month(int v)
  160. {
  161. return date_time_period(month(), v);
  162. }
  163. /// Get date_time_period for: The day of month, calendar specific, in Gregorian [1..31]
  164. inline date_time_period day(int v)
  165. {
  166. return date_time_period(day(), v);
  167. }
  168. /// Get date_time_period for: The number of day in year, starting from 1, in Gregorian [1..366]
  169. inline date_time_period day_of_year(int v)
  170. {
  171. return date_time_period(day_of_year(), v);
  172. }
  173. /// Get date_time_period for: Day of week, Sunday=1, Monday=2,..., Saturday=7.
  174. ///
  175. /// Note that updating this value respects local day of week, so for example,
  176. /// If first day of week is Monday and the current day is Tuesday then setting
  177. /// the value to Sunday (1) would forward the date by 5 days forward and not backward
  178. /// by two days as it could be expected if the numbers were taken as is.
  179. inline date_time_period day_of_week(int v)
  180. {
  181. return date_time_period(day_of_week(), v);
  182. }
  183. /// Get date_time_period for: Original number of the day of the week in month. For example 1st Sunday,
  184. /// 2nd Sunday, etc. in Gregorian [1..5]
  185. inline date_time_period day_of_week_in_month(int v)
  186. {
  187. return date_time_period(day_of_week_in_month(), v);
  188. }
  189. /// Get date_time_period for: Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
  190. inline date_time_period day_of_week_local(int v)
  191. {
  192. return date_time_period(day_of_week_local(), v);
  193. }
  194. /// Get date_time_period for: 24 clock hour [0..23]
  195. inline date_time_period hour(int v)
  196. {
  197. return date_time_period(hour(), v);
  198. }
  199. /// Get date_time_period for: 12 clock hour [0..11]
  200. inline date_time_period hour_12(int v)
  201. {
  202. return date_time_period(hour_12(), v);
  203. }
  204. /// Get date_time_period for: am or pm marker [0..1]
  205. inline date_time_period am_pm(int v)
  206. {
  207. return date_time_period(am_pm(), v);
  208. }
  209. /// Get date_time_period for: minute [0..59]
  210. inline date_time_period minute(int v)
  211. {
  212. return date_time_period(minute(), v);
  213. }
  214. /// Get date_time_period for: second [0..59]
  215. inline date_time_period second(int v)
  216. {
  217. return date_time_period(second(), v);
  218. }
  219. /// Get date_time_period for: The week number in the year
  220. inline date_time_period week_of_year(int v)
  221. {
  222. return date_time_period(week_of_year(), v);
  223. }
  224. /// Get date_time_period for: The week number within current month
  225. inline date_time_period week_of_month(int v)
  226. {
  227. return date_time_period(week_of_month(), v);
  228. }
  229. /// Get date_time_period for: First day of week, constant, for example Sunday in US = 1, Monday in France = 2
  230. inline date_time_period first_day_of_week(int v)
  231. {
  232. return date_time_period(first_day_of_week(), v);
  233. }
  234. /// Get predefined constant for January
  235. inline date_time_period january()
  236. {
  237. return date_time_period(month(), 0);
  238. }
  239. /// Get predefined constant for February
  240. inline date_time_period february()
  241. {
  242. return date_time_period(month(), 1);
  243. }
  244. /// Get predefined constant for March
  245. inline date_time_period march()
  246. {
  247. return date_time_period(month(), 2);
  248. }
  249. /// Get predefined constant for April
  250. inline date_time_period april()
  251. {
  252. return date_time_period(month(), 3);
  253. }
  254. /// Get predefined constant for May
  255. inline date_time_period may()
  256. {
  257. return date_time_period(month(), 4);
  258. }
  259. /// Get predefined constant for June
  260. inline date_time_period june()
  261. {
  262. return date_time_period(month(), 5);
  263. }
  264. /// Get predefined constant for July
  265. inline date_time_period july()
  266. {
  267. return date_time_period(month(), 6);
  268. }
  269. /// Get predefined constant for August
  270. inline date_time_period august()
  271. {
  272. return date_time_period(month(), 7);
  273. }
  274. /// Get predefined constant for September
  275. inline date_time_period september()
  276. {
  277. return date_time_period(month(), 8);
  278. }
  279. /// Get predefined constant for October
  280. inline date_time_period october()
  281. {
  282. return date_time_period(month(), 9);
  283. }
  284. /// Get predefined constant for November
  285. inline date_time_period november()
  286. {
  287. return date_time_period(month(), 10);
  288. }
  289. /// Get predefined constant for December
  290. inline date_time_period december()
  291. {
  292. return date_time_period(month(), 11);
  293. }
  294. /// Get predefined constant for Sunday
  295. inline date_time_period sunday()
  296. {
  297. return date_time_period(day_of_week(), 1);
  298. }
  299. /// Get predefined constant for Monday
  300. inline date_time_period monday()
  301. {
  302. return date_time_period(day_of_week(), 2);
  303. }
  304. /// Get predefined constant for Tuesday
  305. inline date_time_period tuesday()
  306. {
  307. return date_time_period(day_of_week(), 3);
  308. }
  309. /// Get predefined constant for Wednesday
  310. inline date_time_period wednesday()
  311. {
  312. return date_time_period(day_of_week(), 4);
  313. }
  314. /// Get predefined constant for Thursday
  315. inline date_time_period thursday()
  316. {
  317. return date_time_period(day_of_week(), 5);
  318. }
  319. /// Get predefined constant for Friday
  320. inline date_time_period friday()
  321. {
  322. return date_time_period(day_of_week(), 6);
  323. }
  324. /// Get predefined constant for Saturday
  325. inline date_time_period saturday()
  326. {
  327. return date_time_period(day_of_week(), 7);
  328. }
  329. /// Get predefined constant for AM (Ante Meridiem)
  330. inline date_time_period am()
  331. {
  332. return date_time_period(am_pm(), 0);
  333. }
  334. /// Get predefined constant for PM (Post Meridiem)
  335. inline date_time_period pm()
  336. {
  337. return date_time_period(am_pm(), 1);
  338. }
  339. /// convert period_type to date_time_period(f,1)
  340. inline date_time_period operator+(period::period_type f)
  341. {
  342. return date_time_period(f);
  343. }
  344. /// convert period_type to date_time_period(f,-1)
  345. inline date_time_period operator-(period::period_type f)
  346. {
  347. return date_time_period(f, -1);
  348. }
  349. /// Create date_time_period of type \a f with value \a v.
  350. template<typename T>
  351. date_time_period operator*(period::period_type f, T v)
  352. {
  353. return date_time_period(f, v);
  354. }
  355. /// Create date_time_period of type \a f with value \a v.
  356. template<typename T>
  357. date_time_period operator*(T v, period::period_type f)
  358. {
  359. return date_time_period(f, v);
  360. }
  361. /// Create date_time_period of type \a f with value \a v.
  362. template<typename T>
  363. date_time_period operator*(T v, date_time_period f)
  364. {
  365. return date_time_period(f.type, f.value * v);
  366. }
  367. /// Create date_time_period of type \a f with value \a v.
  368. template<typename T>
  369. date_time_period operator*(date_time_period f, T v)
  370. {
  371. return date_time_period(f.type, f.value * v);
  372. }
  373. } // namespace period
  374. /// \brief this class that represents a set of periods,
  375. ///
  376. /// It is generally created by operations on periods:
  377. /// 1995*year + 3*month + 1*day. Note: operations are not commutative.
  378. class date_time_period_set {
  379. public:
  380. /// Default constructor - empty set
  381. date_time_period_set() {}
  382. /// Create a set of single period with value 1
  383. date_time_period_set(period::period_type f) { basic_[0] = date_time_period(f); }
  384. /// Create a set of single period \a fl
  385. date_time_period_set(const date_time_period& fl) { basic_[0] = fl; }
  386. /// Append date_time_period \a f to the set
  387. void add(date_time_period f)
  388. {
  389. size_t n = size();
  390. if(n < 4)
  391. basic_[n] = f;
  392. else
  393. periods_.push_back(f);
  394. }
  395. /// Get number if items in list
  396. size_t size() const
  397. {
  398. if(basic_[0].type == period::period_type())
  399. return 0;
  400. if(basic_[1].type == period::period_type())
  401. return 1;
  402. if(basic_[2].type == period::period_type())
  403. return 2;
  404. if(basic_[3].type == period::period_type())
  405. return 3;
  406. return 4 + periods_.size();
  407. }
  408. /// Get item at position \a n the set, n should be in range [0,size)
  409. const date_time_period& operator[](size_t n) const
  410. {
  411. if(n >= size())
  412. throw std::out_of_range("Invalid index to date_time_period");
  413. if(n < 4)
  414. return basic_[n];
  415. else
  416. return periods_[n - 4];
  417. }
  418. private:
  419. date_time_period basic_[4];
  420. std::vector<date_time_period> periods_;
  421. };
  422. /// Append two periods sets. Note this operator is not commutative
  423. inline date_time_period_set operator+(const date_time_period_set& a, const date_time_period_set& b)
  424. {
  425. date_time_period_set s(a);
  426. for(unsigned i = 0; i < b.size(); i++)
  427. s.add(b[i]);
  428. return s;
  429. }
  430. /// Append two period sets when all periods of set \b change their sign
  431. inline date_time_period_set operator-(const date_time_period_set& a, const date_time_period_set& b)
  432. {
  433. date_time_period_set s(a);
  434. for(unsigned i = 0; i < b.size(); i++)
  435. s.add(-b[i]);
  436. return s;
  437. }
  438. /// \brief this class provides an access to general calendar information.
  439. ///
  440. /// This information is not connected to specific date but generic to locale, and timezone.
  441. /// It is used in obtaining general information about calendar and is essential for creation of
  442. /// date_time objects.
  443. class BOOST_LOCALE_DECL calendar {
  444. public:
  445. /// Create calendar taking locale and timezone information from ios_base instance.
  446. ///
  447. /// \note throws std::bad_cast if ios does not have a locale with installed \ref calendar_facet
  448. /// facet installed
  449. calendar(std::ios_base& ios);
  450. /// Create calendar with locale \a l and time_zone \a zone
  451. ///
  452. /// \note throws std::bad_cast if loc does not have \ref calendar_facet facet installed
  453. calendar(const std::locale& l, const std::string& zone);
  454. /// Create calendar with locale \a l and default timezone
  455. ///
  456. /// \note throws std::bad_cast if loc does not have \ref calendar_facet facet installed
  457. calendar(const std::locale& l);
  458. /// Create calendar with default locale and timezone \a zone
  459. ///
  460. /// \note throws std::bad_cast if global locale does not have \ref calendar_facet facet installed
  461. calendar(const std::string& zone);
  462. /// Create calendar with default locale and timezone
  463. ///
  464. /// \note throws std::bad_cast if global locale does not have \ref calendar_facet facet installed
  465. calendar();
  466. ~calendar();
  467. /// copy calendar
  468. calendar(const calendar& other);
  469. /// assign calendar
  470. calendar& operator=(const calendar& other);
  471. /// Get minimum value for period f, For example for period::day it is 1.
  472. int minimum(period::period_type f) const;
  473. /// Get greatest possible minimum value for period f, For example for period::day it is 1, but may be different
  474. /// for other calendars.
  475. int greatest_minimum(period::period_type f) const;
  476. /// Get maximum value for period f, For example for Gregorian calendar's maximum period::day it is 31.
  477. int maximum(period::period_type f) const;
  478. /// Get least maximum value for period f, For example for Gregorian calendar's maximum period::day it is 28.
  479. int least_maximum(period::period_type f) const;
  480. /// Get first day of week for specific calendar, for example for US it is 1 - Sunday for France it is 2 - Monday
  481. int first_day_of_week() const;
  482. /// get calendar's locale
  483. std::locale get_locale() const;
  484. /// get calendar's time zone
  485. std::string get_time_zone() const;
  486. /// Check if the calendar is Gregorian
  487. bool is_gregorian() const;
  488. /// Compare calendars for equivalence: i.e. calendar types, time zones etc.
  489. bool operator==(const calendar& other) const;
  490. /// Opposite of ==
  491. bool operator!=(const calendar& other) const;
  492. private:
  493. friend class date_time;
  494. std::locale locale_;
  495. std::string tz_;
  496. hold_ptr<abstract_calendar> impl_;
  497. };
  498. /// \brief this class represents a date time and allows to perform various operation according to the
  499. /// locale settings.
  500. ///
  501. /// This class allows to manipulate various aspects of dates and times easily using arithmetic operations with
  502. /// periods.
  503. ///
  504. /// General arithmetic functions:
  505. ///
  506. /// - date_time + date_time_period_set = date_time: move time point forward by specific periods like date_time +
  507. /// month;
  508. /// - date_time - date_time_period_set = date_time: move time point backward by specific periods like date_time -
  509. /// month;
  510. /// - date_time << date_time_period_set = date_time: roll time point forward by specific periods with rolling to
  511. /// begin if overflows: like "2010-01-31" << 2* day == "2010-01-02" instead of "2010-02-02"
  512. /// - date_time >> date_time_period_set = date_time: roll time point backward by specific periods with rolling to
  513. /// end if overflows: like "2010-01-02" >> 2* day == "2010-01-31" instead of "2009-12-30"
  514. /// - date_time / period_type = int - current period value: like "2010-12-21" / month == 12. "2010-12-21" / year =
  515. /// 2010
  516. /// - (date_time - date_time) / period_type = int: distance between dates in period_type. Like ("2010-12-01" -
  517. /// "2008-12-01") / month = 24.
  518. ///
  519. /// You can also assign specific periods using assignment operator like:
  520. /// some_time = year * 1995 that sets the year to 1995.
  521. class BOOST_LOCALE_DECL date_time {
  522. public:
  523. /// Default constructor, uses default calendar initialized date_time object to current time.
  524. ///
  525. /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed
  526. date_time();
  527. /// Copy a date_time
  528. date_time(const date_time& other);
  529. // Move construct a new date_time
  530. date_time(date_time&&) = default;
  531. /// copy date_time and change some fields according to the \a set
  532. date_time(const date_time& other, const date_time_period_set& set);
  533. /// assign the date_time
  534. date_time& operator=(const date_time& other);
  535. // Move assign a date_time
  536. date_time& operator=(date_time&&) = default;
  537. /// Create a date_time object using POSIX time \a time and default calendar
  538. ///
  539. /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed
  540. date_time(double time);
  541. /// Create a date_time object using POSIX time \a time and calendar \a cal
  542. date_time(double time, const calendar& cal);
  543. /// Create a date_time object using calendar \a cal and initializes it to current time.
  544. date_time(const calendar& cal);
  545. /// Create a date_time object using default calendar and define values given in \a set
  546. ///
  547. /// \note throws std::bad_cast if the global locale does not have \ref calendar_facet facet installed
  548. date_time(const date_time_period_set& set);
  549. /// Create a date_time object using calendar \a cal and define values given in \a set
  550. date_time(const date_time_period_set& set, const calendar& cal);
  551. /// assign values to various periods in set \a f
  552. date_time& operator=(const date_time_period_set& f);
  553. /// set specific period \a f value to \a v
  554. void set(period::period_type f, int v);
  555. /// get specific period \a f value
  556. int get(period::period_type f) const;
  557. /// syntactic sugar for get(f)
  558. int operator/(period::period_type f) const { return get(f); }
  559. /// add single period f to the current date_time
  560. date_time operator+(period::period_type f) const { return *this + date_time_period(f); }
  561. /// subtract single period f from the current date_time
  562. date_time operator-(period::period_type f) const { return *this - date_time_period(f); }
  563. /// add single period f to the current date_time
  564. date_time& operator+=(period::period_type f) { return *this += date_time_period(f); }
  565. /// subtract single period f from the current date_time
  566. date_time& operator-=(period::period_type f) { return *this -= date_time_period(f); }
  567. /// roll forward a date by single period f.
  568. date_time operator<<(period::period_type f) const { return *this << date_time_period(f); }
  569. /// roll backward a date by single period f.
  570. date_time operator>>(period::period_type f) const { return *this >> date_time_period(f); }
  571. /// roll forward a date by single period f.
  572. date_time& operator<<=(period::period_type f) { return *this <<= date_time_period(f); }
  573. /// roll backward a date by single period f.
  574. date_time& operator>>=(period::period_type f) { return *this >>= date_time_period(f); }
  575. /// add date_time_period to the current date_time
  576. date_time operator+(const date_time_period& v) const;
  577. /// subtract date_time_period from the current date_time
  578. date_time operator-(const date_time_period& v) const;
  579. /// add date_time_period to the current date_time
  580. date_time& operator+=(const date_time_period& v);
  581. /// subtract date_time_period from the current date_time
  582. date_time& operator-=(const date_time_period& v);
  583. /// roll current date_time forward by date_time_period v
  584. date_time operator<<(const date_time_period& v) const;
  585. /// roll current date_time backward by date_time_period v
  586. date_time operator>>(const date_time_period& v) const;
  587. /// roll current date_time forward by date_time_period v
  588. date_time& operator<<=(const date_time_period& v);
  589. /// roll current date_time backward by date_time_period v
  590. date_time& operator>>=(const date_time_period& v);
  591. /// add date_time_period_set v to the current date_time
  592. date_time operator+(const date_time_period_set& v) const;
  593. /// subtract date_time_period_set v from the current date_time
  594. date_time operator-(const date_time_period_set& v) const;
  595. /// add date_time_period_set v to the current date_time
  596. date_time& operator+=(const date_time_period_set& v);
  597. /// subtract date_time_period_set v from the current date_time
  598. date_time& operator-=(const date_time_period_set& v);
  599. /// roll current date_time forward by date_time_period_set v
  600. date_time operator<<(const date_time_period_set& v) const;
  601. /// roll current date_time backward by date_time_period_set v
  602. date_time operator>>(const date_time_period_set& v) const;
  603. /// roll current date_time forward by date_time_period_set v
  604. date_time& operator<<=(const date_time_period_set& v);
  605. /// roll current date_time backward by date_time_period_set v
  606. date_time& operator>>=(const date_time_period_set& v);
  607. /// Get POSIX time
  608. ///
  609. /// The POSIX time is number of seconds since January 1st, 1970 00:00 UTC, ignoring leap seconds.
  610. double time() const;
  611. /// Set POSIX time
  612. ///
  613. /// The POSIX time is number of seconds since January 1st, 1970 00:00 UTC, ignoring leap seconds.
  614. /// This time can be fetched from Operating system clock using C function time, gettimeofday and others.
  615. void time(double v);
  616. /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
  617. bool operator==(const date_time& other) const;
  618. /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
  619. bool operator!=(const date_time& other) const;
  620. /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
  621. bool operator<(const date_time& other) const;
  622. /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
  623. bool operator>(const date_time& other) const;
  624. /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
  625. bool operator<=(const date_time& other) const;
  626. /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
  627. bool operator>=(const date_time& other) const;
  628. /// swaps two dates - efficient, does not throw
  629. void swap(date_time& other);
  630. /// calculate the distance from this date_time to \a other in terms of periods \a f
  631. int difference(const date_time& other, period::period_type f) const;
  632. /// Get minimal possible value for *this time point for a period \a f.
  633. int minimum(period::period_type f) const;
  634. /// Get minimal possible value for *this time point for a period \a f. For example
  635. /// in February maximum(day) may be 28 or 29, in January maximum(day)==31
  636. int maximum(period::period_type f) const;
  637. /// Check if *this time point is in daylight saving time
  638. bool is_in_daylight_saving_time() const;
  639. private:
  640. hold_ptr<abstract_calendar> impl_;
  641. };
  642. /// Writes date_time \a t to output stream \a out.
  643. ///
  644. /// This function uses locale, calendar and time zone of the target stream \a in.
  645. ///
  646. /// For example:
  647. /// \code
  648. /// date_time now(time(0),hebrew_calendar)
  649. /// std::cout << "Year: " << period::year(now) << " Full Date:" << now;
  650. /// \endcode
  651. ///
  652. /// The output may be Year:5770 Full Date:Jan 1, 2010
  653. template<typename CharType>
  654. std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const date_time& t)
  655. {
  656. double time_point = t.time();
  657. uint64_t display_flags = ios_info::get(out).display_flags();
  658. if(display_flags == flags::date || display_flags == flags::time || display_flags == flags::datetime
  659. || display_flags == flags::strftime)
  660. {
  661. out << time_point;
  662. } else {
  663. ios_info::get(out).display_flags(flags::datetime);
  664. out << time_point;
  665. ios_info::get(out).display_flags(display_flags);
  666. }
  667. return out;
  668. }
  669. /// Reads date_time \a t from output stream \a in
  670. ///
  671. /// This function uses locale, calendar and time zone of the source stream \a in.
  672. template<typename CharType>
  673. std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, date_time& t)
  674. {
  675. double v;
  676. uint64_t display_flags = ios_info::get(in).display_flags();
  677. if(display_flags == flags::date || display_flags == flags::time || display_flags == flags::datetime
  678. || display_flags == flags::strftime)
  679. {
  680. in >> v;
  681. } else {
  682. ios_info::get(in).display_flags(flags::datetime);
  683. in >> v;
  684. ios_info::get(in).display_flags(display_flags);
  685. }
  686. if(!in.fail())
  687. t.time(v);
  688. return in;
  689. }
  690. #ifdef BOOST_MSVC
  691. # pragma warning(push)
  692. # pragma warning(disable : 4512) // assignment operator could not be generated
  693. #endif
  694. /// \brief This class represents a period: a pair of two date_time objects.
  695. ///
  696. /// It is generally used as syntactic sugar to calculate difference between two dates.
  697. ///
  698. /// Note: it stores references to the original objects, so it is not recommended to be used
  699. /// outside of the equation you calculate the difference in.
  700. class date_time_duration {
  701. public:
  702. /// Create an object were \a first represents earlier point on time line and \a second is later
  703. /// point.
  704. date_time_duration(const date_time& first, const date_time& second) : s_(first), e_(second) {}
  705. /// find a difference in terms of period_type \a f
  706. int get(period::period_type f) const { return start().difference(end(), f); }
  707. /// Syntactic sugar for get(f)
  708. int operator/(period::period_type f) const { return start().difference(end(), f); }
  709. /// Get starting point
  710. const date_time& start() const { return s_; }
  711. /// Get ending point
  712. const date_time& end() const { return e_; }
  713. private:
  714. const date_time& s_;
  715. const date_time& e_;
  716. };
  717. #ifdef BOOST_MSVC
  718. # pragma warning(pop)
  719. #endif
  720. /// Calculates the difference between two dates, the left operand is a later point on time line.
  721. /// Returns date_time_duration object.
  722. inline date_time_duration operator-(const date_time& later, const date_time& earlier)
  723. {
  724. return date_time_duration(earlier, later);
  725. }
  726. namespace period {
  727. /// Extract from date_time numerical value of Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
  728. inline int era(const date_time& dt)
  729. {
  730. return dt.get(era());
  731. }
  732. /// Extract from date_time numerical value of Year, it is calendar specific, for example 2011 in Gregorian
  733. /// calendar.
  734. inline int year(const date_time& dt)
  735. {
  736. return dt.get(year());
  737. }
  738. /// Extract from date_time numerical value of Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2
  739. /// BC == -1.
  740. inline int extended_year(const date_time& dt)
  741. {
  742. return dt.get(extended_year());
  743. }
  744. /// Extract from date_time numerical value of The month of year, calendar specific, in Gregorian [0..11]
  745. inline int month(const date_time& dt)
  746. {
  747. return dt.get(month());
  748. }
  749. /// Extract from date_time numerical value of The day of month, calendar specific, in Gregorian [1..31]
  750. inline int day(const date_time& dt)
  751. {
  752. return dt.get(day());
  753. }
  754. /// Extract from date_time numerical value of The number of day in year, starting from 1, in Gregorian [1..366]
  755. inline int day_of_year(const date_time& dt)
  756. {
  757. return dt.get(day_of_year());
  758. }
  759. /// Extract from date_time numerical value of Day of week, Sunday=1, Monday=2,..., Saturday=7.
  760. ///
  761. /// Note that updating this value respects local day of week, so for example,
  762. /// If first day of week is Monday and the current day is Tuesday then setting
  763. /// the value to Sunday (1) would forward the date by 5 days forward and not backward
  764. /// by two days as it could be expected if the numbers were taken as is.
  765. inline int day_of_week(const date_time& dt)
  766. {
  767. return dt.get(day_of_week());
  768. }
  769. /// Extract from date_time numerical value of Original number of the day of the week in month. For example 1st
  770. /// Sunday,
  771. /// 2nd Sunday, etc. in Gregorian [1..5]
  772. inline int day_of_week_in_month(const date_time& dt)
  773. {
  774. return dt.get(day_of_week_in_month());
  775. }
  776. /// Extract from date_time numerical value of Local day of week, for example in France Monday is 1, in US
  777. /// Sunday is 1, [1..7]
  778. inline int day_of_week_local(const date_time& dt)
  779. {
  780. return dt.get(day_of_week_local());
  781. }
  782. /// Extract from date_time numerical value of 24 clock hour [0..23]
  783. inline int hour(const date_time& dt)
  784. {
  785. return dt.get(hour());
  786. }
  787. /// Extract from date_time numerical value of 12 clock hour [0..11]
  788. inline int hour_12(const date_time& dt)
  789. {
  790. return dt.get(hour_12());
  791. }
  792. /// Extract from date_time numerical value of am or pm marker [0..1]
  793. inline int am_pm(const date_time& dt)
  794. {
  795. return dt.get(am_pm());
  796. }
  797. /// Extract from date_time numerical value of minute [0..59]
  798. inline int minute(const date_time& dt)
  799. {
  800. return dt.get(minute());
  801. }
  802. /// Extract from date_time numerical value of second [0..59]
  803. inline int second(const date_time& dt)
  804. {
  805. return dt.get(second());
  806. }
  807. /// Extract from date_time numerical value of The week number in the year
  808. inline int week_of_year(const date_time& dt)
  809. {
  810. return dt.get(week_of_year());
  811. }
  812. /// Extract from date_time numerical value of The week number within current month
  813. inline int week_of_month(const date_time& dt)
  814. {
  815. return dt.get(week_of_month());
  816. }
  817. /// Extract from date_time numerical value of First day of week, constant, for example Sunday in US = 1, Monday
  818. /// in France = 2
  819. inline int first_day_of_week(const date_time& dt)
  820. {
  821. return dt.get(first_day_of_week());
  822. }
  823. /// Extract from date_time_duration numerical value of duration in Era i.e. AC, BC in Gregorian and Julian
  824. /// calendar, range [0,1]
  825. inline int era(const date_time_duration& dt)
  826. {
  827. return dt.get(era());
  828. }
  829. /// Extract from date_time_duration numerical value of duration in years
  830. inline int year(const date_time_duration& dt)
  831. {
  832. return dt.get(year());
  833. }
  834. /// Extract from date_time_duration numerical value of duration in extended years (for Gregorian/Julian
  835. /// calendars, where 1 BC == 0, 2 BC == -1).
  836. inline int extended_year(const date_time_duration& dt)
  837. {
  838. return dt.get(extended_year());
  839. }
  840. /// Extract from date_time_duration numerical value of duration in months
  841. inline int month(const date_time_duration& dt)
  842. {
  843. return dt.get(month());
  844. }
  845. /// Extract from date_time_duration numerical value of duration in days of month
  846. inline int day(const date_time_duration& dt)
  847. {
  848. return dt.get(day());
  849. }
  850. /// Extract from date_time_duration numerical value of duration in days of year
  851. inline int day_of_year(const date_time_duration& dt)
  852. {
  853. return dt.get(day_of_year());
  854. }
  855. /// Extract from date_time_duration numerical value of duration in days of week
  856. inline int day_of_week(const date_time_duration& dt)
  857. {
  858. return dt.get(day_of_week());
  859. }
  860. /// Extract from date_time_duration numerical value of duration in original number of the day of the week in
  861. /// month
  862. inline int day_of_week_in_month(const date_time_duration& dt)
  863. {
  864. return dt.get(day_of_week_in_month());
  865. }
  866. /// Extract from date_time_duration numerical value of duration in local day of week
  867. inline int day_of_week_local(const date_time_duration& dt)
  868. {
  869. return dt.get(day_of_week_local());
  870. }
  871. /// Extract from date_time_duration numerical value of duration in hours
  872. inline int hour(const date_time_duration& dt)
  873. {
  874. return dt.get(hour());
  875. }
  876. /// Extract from date_time_duration numerical value of duration in 12 clock hours
  877. inline int hour_12(const date_time_duration& dt)
  878. {
  879. return dt.get(hour_12());
  880. }
  881. /// Extract from date_time_duration numerical value of duration in am or pm markers
  882. inline int am_pm(const date_time_duration& dt)
  883. {
  884. return dt.get(am_pm());
  885. }
  886. /// Extract from date_time_duration numerical value of duration in minutes
  887. inline int minute(const date_time_duration& dt)
  888. {
  889. return dt.get(minute());
  890. }
  891. /// Extract from date_time_duration numerical value of duration in seconds
  892. inline int second(const date_time_duration& dt)
  893. {
  894. return dt.get(second());
  895. }
  896. /// Extract from date_time_duration numerical value of duration in the week number in the year
  897. inline int week_of_year(const date_time_duration& dt)
  898. {
  899. return dt.get(week_of_year());
  900. }
  901. /// Extract from date_time_duration numerical value of duration in The week number within current month
  902. inline int week_of_month(const date_time_duration& dt)
  903. {
  904. return dt.get(week_of_month());
  905. }
  906. /// Extract from date_time_duration numerical value of duration in the first day of week
  907. inline int first_day_of_week(const date_time_duration& dt)
  908. {
  909. return dt.get(first_day_of_week());
  910. }
  911. } // namespace period
  912. /// @}
  913. }} // namespace boost::locale
  914. #ifdef BOOST_MSVC
  915. # pragma warning(pop)
  916. #endif
  917. ///
  918. /// \example calendar.cpp
  919. ///
  920. /// Example of using date_time functions for generating calendar for current year.
  921. ///
  922. #endif