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

source code of boost/libs/locale/include/boost/locale/date_time.hpp