Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:16

0001 //
0002 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // https://www.boost.org/LICENSE_1_0.txt
0006 
0007 #ifndef BOOST_LOCALE_DATE_TIME_HPP_INCLUDED
0008 #define BOOST_LOCALE_DATE_TIME_HPP_INCLUDED
0009 
0010 #include <boost/locale/date_time_facet.hpp>
0011 #include <boost/locale/formatting.hpp>
0012 #include <boost/locale/hold_ptr.hpp>
0013 #include <boost/locale/time_zone.hpp>
0014 #include <array>
0015 #include <locale>
0016 #include <stdexcept>
0017 #include <vector>
0018 
0019 #ifdef BOOST_MSVC
0020 #    pragma warning(push)
0021 #    pragma warning(disable : 4275 4251 4231 4660)
0022 #endif
0023 
0024 namespace boost { namespace locale {
0025     /// \defgroup date_time Date, Time, Timezone and Calendar manipulations
0026     ///
0027     /// This module provides various calendar, timezone and date time services
0028     /// @{
0029 
0030     /// \brief This error is thrown in case of invalid state that occurred
0031     class BOOST_SYMBOL_VISIBLE date_time_error : public std::runtime_error {
0032     public:
0033         /// Constructor of date_time_error class
0034         date_time_error(const std::string& e) : std::runtime_error(e) {}
0035     };
0036 
0037     /// \brief This class represents a pair of period_type and the integer
0038     /// values that describes its amount. For example 3 days or 4 years.
0039     ///
0040     /// Usually obtained as product of period_type and integer or
0041     /// my calling a representative functions
0042     /// For example day()*3 == date_time_period(day(),3) == day(3)
0043     struct date_time_period {
0044         period::period_type type; ///< The type of period, i.e. era, year, day etc.
0045         int value;                ///< The value the actual number of \a periods
0046         /// Operator + returns copy of itself
0047         date_time_period operator+() const { return *this; }
0048         /// Operator -, switches the sign of period
0049         date_time_period operator-() const { return date_time_period(type, -value); }
0050 
0051         /// Constructor that creates date_time_period from period_type \a f and a value \a v -- default 1.
0052         date_time_period(period::period_type f = period::period_type(), int v = 1) : type(f), value(v) {}
0053     };
0054 
0055     namespace period {
0056         ///  Get period_type for: special invalid value, should not be used directly
0057         inline period_type invalid()
0058         {
0059             return period_type(marks::invalid);
0060         }
0061         ///  Get period_type for: Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
0062         inline period_type era()
0063         {
0064             return period_type(marks::era);
0065         }
0066         ///  Get period_type for: Year, it is calendar specific, for example 2011 in Gregorian calendar.
0067         inline period_type year()
0068         {
0069             return period_type(marks::year);
0070         }
0071         ///  Get period_type for: Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
0072         inline period_type extended_year()
0073         {
0074             return period_type(marks::extended_year);
0075         }
0076         ///  Get period_type for: The month of year, calendar specific, in Gregorian [0..11]
0077         inline period_type month()
0078         {
0079             return period_type(marks::month);
0080         }
0081         ///  Get period_type for: The day of month, calendar specific, in Gregorian [1..31]
0082         inline period_type day()
0083         {
0084             return period_type(marks::day);
0085         }
0086         ///  Get period_type for: The number of day in year, starting from 1, in Gregorian  [1..366]
0087         inline period_type day_of_year()
0088         {
0089             return period_type(marks::day_of_year);
0090         }
0091         /// Get period_type for: Day of week, Sunday=1, Monday=2,..., Saturday=7.
0092         ///
0093         /// Note that updating this value respects local day of week, so for example,
0094         /// If first day of week is Monday and the current day is Tuesday then setting
0095         /// the value to Sunday (1) would forward the date by 5 days forward and not backward
0096         /// by two days as it could be expected if the numbers were taken as is.
0097         inline period_type day_of_week()
0098         {
0099             return period_type(marks::day_of_week);
0100         }
0101         ///  Get period_type for: Original number of the day of the week in month. For example 1st Sunday,
0102         /// 2nd Sunday, etc. in Gregorian [1..5]
0103         inline period_type day_of_week_in_month()
0104         {
0105             return period_type(marks::day_of_week_in_month);
0106         }
0107         ///  Get period_type for: Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
0108         inline period_type day_of_week_local()
0109         {
0110             return period_type(marks::day_of_week_local);
0111         }
0112         ///  Get period_type for: 24 clock hour [0..23]
0113         inline period_type hour()
0114         {
0115             return period_type(marks::hour);
0116         }
0117         ///  Get period_type for: 12 clock hour [0..11]
0118         inline period_type hour_12()
0119         {
0120             return period_type(marks::hour_12);
0121         }
0122         ///  Get period_type for: am or pm marker [0..1]
0123         inline period_type am_pm()
0124         {
0125             return period_type(marks::am_pm);
0126         }
0127         ///  Get period_type for: minute [0..59]
0128         inline period_type minute()
0129         {
0130             return period_type(marks::minute);
0131         }
0132         ///  Get period_type for: second [0..59]
0133         inline period_type second()
0134         {
0135             return period_type(marks::second);
0136         }
0137         ///  Get period_type for: The week number in the year
0138         inline period_type week_of_year()
0139         {
0140             return period_type(marks::week_of_year);
0141         }
0142         ///  Get period_type for: The week number within current month
0143         inline period_type week_of_month()
0144         {
0145             return period_type(marks::week_of_month);
0146         }
0147         ///  Get period_type for: First day of week, constant, for example Sunday in US = 1, Monday in France = 2
0148         inline period_type first_day_of_week()
0149         {
0150             return period_type(marks::first_day_of_week);
0151         }
0152 
0153         ///  Get date_time_period for: Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
0154         inline date_time_period era(int v)
0155         {
0156             return date_time_period(era(), v);
0157         }
0158         ///  Get date_time_period for: Year, it is calendar specific, for example 2011 in Gregorian calendar.
0159         inline date_time_period year(int v)
0160         {
0161             return date_time_period(year(), v);
0162         }
0163         ///  Get date_time_period for: Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
0164         inline date_time_period extended_year(int v)
0165         {
0166             return date_time_period(extended_year(), v);
0167         }
0168         ///  Get date_time_period for: The month of year, calendar specific, in Gregorian [0..11]
0169         inline date_time_period month(int v)
0170         {
0171             return date_time_period(month(), v);
0172         }
0173         ///  Get date_time_period for: The day of month, calendar specific, in Gregorian [1..31]
0174         inline date_time_period day(int v)
0175         {
0176             return date_time_period(day(), v);
0177         }
0178         ///  Get date_time_period for: The number of day in year, starting from 1, in Gregorian  [1..366]
0179         inline date_time_period day_of_year(int v)
0180         {
0181             return date_time_period(day_of_year(), v);
0182         }
0183         ///  Get date_time_period for: Day of week, Sunday=1, Monday=2,..., Saturday=7.
0184         ///
0185         /// Note that updating this value respects local day of week, so for example,
0186         /// If first day of week is Monday and the current day is Tuesday then setting
0187         /// the value to Sunday (1) would forward the date by 5 days forward and not backward
0188         /// by two days as it could be expected if the numbers were taken as is.
0189         inline date_time_period day_of_week(int v)
0190         {
0191             return date_time_period(day_of_week(), v);
0192         }
0193         ///  Get date_time_period for: Original number of the day of the week in month. For example 1st Sunday,
0194         /// 2nd Sunday, etc. in Gregorian [1..5]
0195         inline date_time_period day_of_week_in_month(int v)
0196         {
0197             return date_time_period(day_of_week_in_month(), v);
0198         }
0199         ///  Get date_time_period for: Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
0200         inline date_time_period day_of_week_local(int v)
0201         {
0202             return date_time_period(day_of_week_local(), v);
0203         }
0204         ///  Get date_time_period for: 24 clock hour [0..23]
0205         inline date_time_period hour(int v)
0206         {
0207             return date_time_period(hour(), v);
0208         }
0209         ///  Get date_time_period for: 12 clock hour [0..11]
0210         inline date_time_period hour_12(int v)
0211         {
0212             return date_time_period(hour_12(), v);
0213         }
0214         ///  Get date_time_period for: am or pm marker [0..1]
0215         inline date_time_period am_pm(int v)
0216         {
0217             return date_time_period(am_pm(), v);
0218         }
0219         ///  Get date_time_period for: minute [0..59]
0220         inline date_time_period minute(int v)
0221         {
0222             return date_time_period(minute(), v);
0223         }
0224         ///  Get date_time_period for: second [0..59]
0225         inline date_time_period second(int v)
0226         {
0227             return date_time_period(second(), v);
0228         }
0229         ///  Get date_time_period for: The week number in the year
0230         inline date_time_period week_of_year(int v)
0231         {
0232             return date_time_period(week_of_year(), v);
0233         }
0234         ///  Get date_time_period for: The week number within current month
0235         inline date_time_period week_of_month(int v)
0236         {
0237             return date_time_period(week_of_month(), v);
0238         }
0239         ///  Get date_time_period for: First day of week, constant, for example Sunday in US = 1, Monday in France = 2
0240         inline date_time_period first_day_of_week(int v)
0241         {
0242             return date_time_period(first_day_of_week(), v);
0243         }
0244 
0245         /// Get predefined constant for January
0246         inline date_time_period january()
0247         {
0248             return date_time_period(month(), 0);
0249         }
0250         /// Get predefined constant for February
0251         inline date_time_period february()
0252         {
0253             return date_time_period(month(), 1);
0254         }
0255         /// Get predefined constant for March
0256         inline date_time_period march()
0257         {
0258             return date_time_period(month(), 2);
0259         }
0260         /// Get predefined constant for April
0261         inline date_time_period april()
0262         {
0263             return date_time_period(month(), 3);
0264         }
0265         /// Get predefined constant for May
0266         inline date_time_period may()
0267         {
0268             return date_time_period(month(), 4);
0269         }
0270         /// Get predefined constant for June
0271         inline date_time_period june()
0272         {
0273             return date_time_period(month(), 5);
0274         }
0275         /// Get predefined constant for July
0276         inline date_time_period july()
0277         {
0278             return date_time_period(month(), 6);
0279         }
0280         /// Get predefined constant for August
0281         inline date_time_period august()
0282         {
0283             return date_time_period(month(), 7);
0284         }
0285         /// Get predefined constant for September
0286         inline date_time_period september()
0287         {
0288             return date_time_period(month(), 8);
0289         }
0290         /// Get predefined constant for October
0291         inline date_time_period october()
0292         {
0293             return date_time_period(month(), 9);
0294         }
0295         /// Get predefined constant for November
0296         inline date_time_period november()
0297         {
0298             return date_time_period(month(), 10);
0299         }
0300         /// Get predefined constant for December
0301         inline date_time_period december()
0302         {
0303             return date_time_period(month(), 11);
0304         }
0305 
0306         /// Get predefined constant for Sunday
0307         inline date_time_period sunday()
0308         {
0309             return date_time_period(day_of_week(), 1);
0310         }
0311         /// Get predefined constant for Monday
0312         inline date_time_period monday()
0313         {
0314             return date_time_period(day_of_week(), 2);
0315         }
0316         /// Get predefined constant for Tuesday
0317         inline date_time_period tuesday()
0318         {
0319             return date_time_period(day_of_week(), 3);
0320         }
0321         /// Get predefined constant for Wednesday
0322         inline date_time_period wednesday()
0323         {
0324             return date_time_period(day_of_week(), 4);
0325         }
0326         /// Get predefined constant for Thursday
0327         inline date_time_period thursday()
0328         {
0329             return date_time_period(day_of_week(), 5);
0330         }
0331         /// Get predefined constant for Friday
0332         inline date_time_period friday()
0333         {
0334             return date_time_period(day_of_week(), 6);
0335         }
0336         /// Get predefined constant for Saturday
0337         inline date_time_period saturday()
0338         {
0339             return date_time_period(day_of_week(), 7);
0340         }
0341         /// Get predefined constant for AM (Ante Meridiem)
0342         inline date_time_period am()
0343         {
0344             return date_time_period(am_pm(), 0);
0345         }
0346         /// Get predefined constant for PM (Post Meridiem)
0347         inline date_time_period pm()
0348         {
0349             return date_time_period(am_pm(), 1);
0350         }
0351 
0352         /// convert period_type to date_time_period(f,1)
0353         inline date_time_period operator+(period::period_type f)
0354         {
0355             return date_time_period(f);
0356         }
0357         /// convert period_type to date_time_period(f,-1)
0358         inline date_time_period operator-(period::period_type f)
0359         {
0360             return date_time_period(f, -1);
0361         }
0362 
0363         /// Create date_time_period of type \a f with value \a v.
0364         template<typename T>
0365         date_time_period operator*(period::period_type f, T v)
0366         {
0367             return date_time_period(f, v);
0368         }
0369 
0370         /// Create date_time_period of type \a f with value \a v.
0371         template<typename T>
0372         date_time_period operator*(T v, period::period_type f)
0373         {
0374             return date_time_period(f, v);
0375         }
0376         /// Create date_time_period of type \a f with value \a v.
0377         template<typename T>
0378         date_time_period operator*(T v, date_time_period f)
0379         {
0380             return date_time_period(f.type, f.value * v);
0381         }
0382 
0383         /// Create date_time_period of type \a f with value \a v.
0384         template<typename T>
0385         date_time_period operator*(date_time_period f, T v)
0386         {
0387             return date_time_period(f.type, f.value * v);
0388         }
0389 
0390     } // namespace period
0391 
0392     /// \brief This class represents a set of periods.
0393     ///
0394     /// It is generally created by operations on periods:
0395     /// 1995*year + 3*month + 1*day. Note: operations are not commutative.
0396     class date_time_period_set {
0397     public:
0398         /// Default constructor - empty set
0399         date_time_period_set() = default;
0400 
0401         /// Create a set of single period with value 1
0402         date_time_period_set(period::period_type f) { basic_[0] = date_time_period(f); }
0403 
0404         /// Create a set of single period \a fl
0405         date_time_period_set(const date_time_period& fl) { basic_[0] = fl; }
0406 
0407         /// Append date_time_period \a f to the set
0408         void add(date_time_period f)
0409         {
0410             const size_t n = size();
0411             if(n < basic_.size())
0412                 basic_[n] = f;
0413             else
0414                 periods_.push_back(f);
0415         }
0416 
0417         /// Get number of items in list
0418         size_t size() const
0419         {
0420             for(size_t i = 0; i < basic_.size(); ++i) {
0421                 if(basic_[i].type == period::period_type())
0422                     return i;
0423             }
0424             return basic_.size() + periods_.size();
0425         }
0426 
0427         /// Get item at position \a n the set, n should be in range [0,size)
0428         const date_time_period& operator[](size_t n) const
0429         {
0430             if(n >= size())
0431                 throw std::out_of_range("Invalid index to date_time_period");
0432             if(n < basic_.size())
0433                 return basic_[n];
0434             else
0435                 return periods_[n - basic_.size()];
0436         }
0437 
0438     private:
0439         std::array<date_time_period, 4> basic_;
0440         std::vector<date_time_period> periods_;
0441     };
0442 
0443     /// Append two periods sets. Note this operator is not commutative
0444     inline date_time_period_set operator+(const date_time_period_set& a, const date_time_period_set& b)
0445     {
0446         date_time_period_set s(a);
0447         for(unsigned i = 0; i < b.size(); i++)
0448             s.add(b[i]);
0449         return s;
0450     }
0451 
0452     /// Append two period sets when all periods of set \b change their sign
0453     inline date_time_period_set operator-(const date_time_period_set& a, const date_time_period_set& b)
0454     {
0455         date_time_period_set s(a);
0456         for(unsigned i = 0; i < b.size(); i++)
0457             s.add(-b[i]);
0458         return s;
0459     }
0460 
0461     /// \brief this class provides an access to general calendar information.
0462     ///
0463     /// This information is not connected to specific date but generic to locale, and timezone.
0464     /// It is used in obtaining general information about calendar and is essential for creation of
0465     /// date_time objects.
0466     class BOOST_LOCALE_DECL calendar {
0467     public:
0468         /// Create calendar taking locale and timezone information from ios_base instance.
0469         ///
0470         /// \throws std::bad_cast: \a ios does not have a locale with installed \ref calendar_facet
0471         /// facet installed
0472         calendar(std::ios_base& ios);
0473 
0474         /// Create calendar with locale \a l and time_zone \a zone
0475         ///
0476         /// \throws std::bad_cast: \a l does not have \ref calendar_facet facet installed
0477         calendar(const std::locale& l, const std::string& zone);
0478 
0479         /// Create calendar with locale \a l and default timezone
0480         ///
0481         /// \throws std::bad_cast: \a l does not have \ref calendar_facet facet installed
0482         calendar(const std::locale& l);
0483 
0484         /// Create calendar with default locale and timezone \a zone
0485         ///
0486         /// \throws std::bad_cast: global locale does not have \ref calendar_facet facet installed
0487 
0488         calendar(const std::string& zone);
0489 
0490         /// Create calendar with default locale and timezone
0491         ///
0492         /// \throws std::bad_cast: global locale does not have \ref calendar_facet facet installed
0493         calendar();
0494         ~calendar();
0495 
0496         /// copy calendar
0497         calendar(const calendar& other);
0498         /// assign calendar
0499         calendar& operator=(const calendar& other);
0500 
0501         /// Get minimum value for period f, For example for period::day it is 1.
0502         int minimum(period::period_type f) const;
0503         /// Get greatest possible minimum value for period f, For example for period::day it is 1, but may be different
0504         /// for other calendars.
0505         int greatest_minimum(period::period_type f) const;
0506         /// Get maximum value for period f, For example for Gregorian calendar's maximum period::day it is 31.
0507         int maximum(period::period_type f) const;
0508         /// Get least maximum value for period f, For example for Gregorian calendar's maximum period::day it is 28.
0509         int least_maximum(period::period_type f) const;
0510 
0511         /// Get first day of week for specific calendar, for example for US it is 1 - Sunday for France it is 2 - Monday
0512         int first_day_of_week() const;
0513 
0514         /// get calendar's locale
0515         const std::locale& get_locale() const;
0516         /// get calendar's time zone
0517         const std::string& get_time_zone() const;
0518 
0519         /// Check if the calendar is Gregorian
0520         bool is_gregorian() const;
0521 
0522         /// Compare calendars for equivalence: i.e. calendar types, time zones etc.
0523         bool operator==(const calendar& other) const;
0524         /// Opposite of ==
0525         bool operator!=(const calendar& other) const;
0526 
0527     private:
0528         friend class date_time;
0529         std::locale locale_;
0530         std::string tz_;
0531         hold_ptr<abstract_calendar> impl_;
0532     };
0533 
0534     /// \brief this class represents a date time and allows to perform various operation according to the
0535     /// locale settings.
0536     ///
0537     /// This class allows to manipulate various aspects of dates and times easily using arithmetic operations with
0538     /// periods.
0539     ///
0540     /// General arithmetic functions:
0541     ///
0542     /// - date_time + date_time_period_set = date_time: move time point forward by specific periods like date_time +
0543     /// month;
0544     /// - date_time - date_time_period_set = date_time: move time point backward by specific periods like date_time -
0545     /// month;
0546     /// - date_time << date_time_period_set  = date_time: roll time point forward by specific periods with rolling to
0547     /// begin if overflows: like "2010-01-31" << 2* day == "2010-01-02" instead of "2010-02-02"
0548     /// - date_time >> date_time_period_set  = date_time: roll time point backward by specific periods with rolling to
0549     /// end if overflows: like "2010-01-02" >> 2* day == "2010-01-31" instead of "2009-12-30"
0550     /// - date_time / period_type = int - current period value: like "2010-12-21" / month == 12. "2010-12-21" / year =
0551     /// 2010
0552     /// - (date_time - date_time) / period_type = int: distance between dates in period_type. Like ("2010-12-01" -
0553     /// "2008-12-01") / month = 24.
0554     ///
0555     /// You can also assign specific periods using assignment operator like:
0556     /// some_time = year * 1995 that sets the year to 1995.
0557 
0558     class BOOST_LOCALE_DECL date_time {
0559     public:
0560         /// Default constructor, uses default calendar initialized date_time object to current time.
0561         ///
0562         /// \throws std::bad_cast: Global locale does not have \ref calendar_facet facet installed
0563         date_time();
0564 
0565         /// Copy a date_time
0566         date_time(const date_time& other);
0567         // Move construct a date_time
0568         date_time(date_time&&) noexcept = default;
0569 
0570         /// copy date_time and change some fields according to the \a set
0571         date_time(const date_time& other, const date_time_period_set& set);
0572 
0573         /// assign the date_time
0574         date_time& operator=(const date_time& other);
0575         // Move assign a date_time
0576         date_time& operator=(date_time&&) noexcept = default;
0577 
0578         /// Create a date_time object using POSIX time \a time and default calendar
0579         ///
0580         /// \throws std::bad_cast: Global locale does not have \ref calendar_facet facet installed
0581         date_time(double time);
0582 
0583         /// Create a date_time object using POSIX time \a time and calendar \a cal
0584         date_time(double time, const calendar& cal);
0585 
0586         /// Create a date_time object using calendar \a cal and initializes it to current time.
0587         date_time(const calendar& cal);
0588 
0589         /// Create a date_time object using default calendar and define values given in \a set
0590         ///
0591         /// \throws std::bad_cast: Global locale does not have \ref calendar_facet facet installed
0592         date_time(const date_time_period_set& set);
0593 
0594         /// Create a date_time object using calendar \a cal and define values given in \a set
0595         date_time(const date_time_period_set& set, const calendar& cal);
0596 
0597         /// assign values to various periods in set \a f
0598         date_time& operator=(const date_time_period_set& f);
0599 
0600         /// set specific period \a f value to \a v
0601         void set(period::period_type f, int v);
0602 
0603         /// get specific period \a f value
0604         int get(period::period_type f) const;
0605         /// syntactic sugar for get(f)
0606         int operator/(period::period_type f) const { return get(f); }
0607 
0608         /// add single period f to the current date_time
0609         date_time operator+(period::period_type f) const { return *this + date_time_period(f); }
0610         /// subtract single period f from the current date_time
0611         date_time operator-(period::period_type f) const { return *this - date_time_period(f); }
0612         /// add single period f to the current date_time
0613         date_time& operator+=(period::period_type f) { return *this += date_time_period(f); }
0614         /// subtract single period f from the current date_time
0615         date_time& operator-=(period::period_type f) { return *this -= date_time_period(f); }
0616 
0617         /// roll forward a date by single period f.
0618         date_time operator<<(period::period_type f) const { return *this << date_time_period(f); }
0619         /// roll backward a date by single period f.
0620         date_time operator>>(period::period_type f) const { return *this >> date_time_period(f); }
0621         /// roll forward a date by single period f.
0622         date_time& operator<<=(period::period_type f) { return *this <<= date_time_period(f); }
0623         /// roll backward a date by single period f.
0624         date_time& operator>>=(period::period_type f) { return *this >>= date_time_period(f); }
0625 
0626         /// add date_time_period to the current date_time
0627         date_time operator+(const date_time_period& v) const;
0628         /// subtract date_time_period from the current date_time
0629         date_time operator-(const date_time_period& v) const;
0630         /// add date_time_period to the current date_time
0631         date_time& operator+=(const date_time_period& v);
0632         /// subtract date_time_period from the current date_time
0633         date_time& operator-=(const date_time_period& v);
0634 
0635         /// roll current date_time forward by date_time_period v
0636         date_time operator<<(const date_time_period& v) const;
0637         /// roll current date_time backward by date_time_period v
0638         date_time operator>>(const date_time_period& v) const;
0639         /// roll current date_time forward by date_time_period v
0640         date_time& operator<<=(const date_time_period& v);
0641         /// roll current date_time backward by date_time_period v
0642         date_time& operator>>=(const date_time_period& v);
0643 
0644         /// add date_time_period_set v to the current date_time
0645         date_time operator+(const date_time_period_set& v) const;
0646         /// subtract date_time_period_set v from the current date_time
0647         date_time operator-(const date_time_period_set& v) const;
0648         /// add date_time_period_set v to the current date_time
0649         date_time& operator+=(const date_time_period_set& v);
0650         /// subtract date_time_period_set v from the current date_time
0651         date_time& operator-=(const date_time_period_set& v);
0652 
0653         /// roll current date_time forward by date_time_period_set v
0654         date_time operator<<(const date_time_period_set& v) const;
0655         /// roll current date_time backward by date_time_period_set v
0656         date_time operator>>(const date_time_period_set& v) const;
0657         /// roll current date_time forward by date_time_period_set v
0658         date_time& operator<<=(const date_time_period_set& v);
0659         /// roll current date_time backward by date_time_period_set v
0660         date_time& operator>>=(const date_time_period_set& v);
0661 
0662         /// Get POSIX time
0663         ///
0664         /// The POSIX time is number of seconds since January 1st, 1970 00:00 UTC, ignoring leap seconds.
0665         double time() const;
0666         /// Set POSIX time
0667         ///
0668         /// The POSIX time is number of seconds since January 1st, 1970 00:00 UTC, ignoring leap seconds.
0669         /// This time can be fetched from Operating system clock using C function time, gettimeofday and others.
0670         void time(double v);
0671 
0672         /// Get the name of the associated timezone
0673         std::string timezone() const;
0674 
0675         /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
0676         bool operator==(const date_time& other) const;
0677         /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
0678         bool operator!=(const date_time& other) const;
0679         /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
0680         bool operator<(const date_time& other) const;
0681         /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
0682         bool operator>(const date_time& other) const;
0683         /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
0684         bool operator<=(const date_time& other) const;
0685         /// compare date_time in the timeline (ignores difference in calendar, timezone etc)
0686         bool operator>=(const date_time& other) const;
0687 
0688         /// swaps two dates - efficient, does not throw
0689         void swap(date_time& other) noexcept;
0690 
0691         /// calculate the distance from this date_time to \a other in terms of periods \a f
0692         int difference(const date_time& other, period::period_type f) const;
0693 
0694         /// Get minimal possible value for *this time point for a period \a f.
0695         int minimum(period::period_type f) const;
0696         /// Get minimal possible value for *this time point for a period \a f. For example
0697         /// in February maximum(day) may be 28 or 29, in January maximum(day)==31
0698         int maximum(period::period_type f) const;
0699 
0700         /// Check if *this time point is in daylight saving time
0701         bool is_in_daylight_saving_time() const;
0702 
0703     private:
0704         hold_ptr<abstract_calendar> impl_;
0705     };
0706 
0707     inline void swap(date_time& left, date_time& right) noexcept
0708     {
0709         left.swap(right);
0710     }
0711 
0712     /// Writes date_time \a t to output stream \a out.
0713     ///
0714     /// This function uses locale, calendar and time zone of the target stream \a in.
0715     ///
0716     /// For example:
0717     /// \code
0718     ///  date_time now(time(nullptr),hebrew_calendar)
0719     ///  std::cout << "Year: " << period::year(now) << " Full Date:" << now;
0720     /// \endcode
0721     ///
0722     /// The output may be Year:5770 Full Date:Jan 1, 2010
0723     template<typename CharType>
0724     std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const date_time& t)
0725     {
0726         const double time_point = t.time();
0727         ios_info& info = ios_info::get(out);
0728         const uint64_t display_flags = info.display_flags();
0729         if(as::detail::is_datetime_display_flags(display_flags)) {
0730             out << time_point;
0731         } else {
0732             info.display_flags(flags::datetime);
0733             out << time_point;
0734             info.display_flags(display_flags);
0735         }
0736         return out;
0737     }
0738 
0739     /// Reads date_time \a t from output stream \a in
0740     ///
0741     /// This function uses locale, calendar and time zone of the source stream \a in.
0742     template<typename CharType>
0743     std::basic_istream<CharType>& operator>>(std::basic_istream<CharType>& in, date_time& t)
0744     {
0745         double v;
0746         const uint64_t display_flags = ios_info::get(in).display_flags();
0747         if(as::detail::is_datetime_display_flags(display_flags)) {
0748             in >> v;
0749         } else {
0750             ios_info::get(in).display_flags(flags::datetime);
0751             in >> v;
0752             ios_info::get(in).display_flags(display_flags);
0753         }
0754         if(!in.fail())
0755             t.time(v);
0756         return in;
0757     }
0758 
0759 #ifdef BOOST_MSVC
0760 #    pragma warning(push)
0761 #    pragma warning(disable : 4512) // assignment operator could not be generated
0762 #endif
0763 
0764     /// \brief This class represents a period: a pair of two date_time objects.
0765     ///
0766     /// It is generally used as syntactic sugar to calculate difference between two dates.
0767     ///
0768     /// Note: it stores references to the original objects, so it is not recommended to be used
0769     /// outside of the equation you calculate the difference in.
0770     class date_time_duration {
0771     public:
0772         /// Create an object were \a first represents earlier point on time line and \a second is later
0773         /// point.
0774         date_time_duration(const date_time& first, const date_time& second) : s_(first), e_(second) {}
0775 
0776         /// find a difference in terms of period_type \a f
0777         int get(period::period_type f) const { return start().difference(end(), f); }
0778         /// Syntactic sugar for get(f)
0779         int operator/(period::period_type f) const { return start().difference(end(), f); }
0780 
0781         /// Get starting point
0782         const date_time& start() const { return s_; }
0783         /// Get ending point
0784         const date_time& end() const { return e_; }
0785 
0786     private:
0787         const date_time& s_;
0788         const date_time& e_;
0789     };
0790 #ifdef BOOST_MSVC
0791 #    pragma warning(pop)
0792 #endif
0793 
0794     /// Calculates the difference between two dates, the left operand is a later point on time line.
0795     /// Returns date_time_duration object.
0796     inline date_time_duration operator-(const date_time& later, const date_time& earlier)
0797     {
0798         return date_time_duration(earlier, later);
0799     }
0800 
0801     namespace period {
0802         ///  Extract from date_time numerical value of Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
0803         inline int era(const date_time& dt)
0804         {
0805             return dt.get(era());
0806         }
0807         ///  Extract from date_time numerical value of Year, it is calendar specific, for example 2011 in Gregorian
0808         ///  calendar.
0809         inline int year(const date_time& dt)
0810         {
0811             return dt.get(year());
0812         }
0813         ///  Extract from date_time numerical value of Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2
0814         ///  BC == -1.
0815         inline int extended_year(const date_time& dt)
0816         {
0817             return dt.get(extended_year());
0818         }
0819         ///  Extract from date_time numerical value of The month of year, calendar specific, in Gregorian [0..11]
0820         inline int month(const date_time& dt)
0821         {
0822             return dt.get(month());
0823         }
0824         ///  Extract from date_time numerical value of The day of month, calendar specific, in Gregorian [1..31]
0825         inline int day(const date_time& dt)
0826         {
0827             return dt.get(day());
0828         }
0829         ///  Extract from date_time numerical value of The number of day in year, starting from 1, in Gregorian [1..366]
0830         inline int day_of_year(const date_time& dt)
0831         {
0832             return dt.get(day_of_year());
0833         }
0834         ///  Extract from date_time numerical value of Day of week, Sunday=1, Monday=2,..., Saturday=7.
0835         ///
0836         /// Note that updating this value respects local day of week, so for example,
0837         /// If first day of week is Monday and the current day is Tuesday then setting
0838         /// the value to Sunday (1) would forward the date by 5 days forward and not backward
0839         /// by two days as it could be expected if the numbers were taken as is.
0840         inline int day_of_week(const date_time& dt)
0841         {
0842             return dt.get(day_of_week());
0843         }
0844         ///  Extract from date_time numerical value of Original number of the day of the week in month. For example 1st
0845         ///  Sunday,
0846         /// 2nd Sunday, etc. in Gregorian [1..5]
0847         inline int day_of_week_in_month(const date_time& dt)
0848         {
0849             return dt.get(day_of_week_in_month());
0850         }
0851         ///  Extract from date_time numerical value of Local day of week, for example in France Monday is 1, in US
0852         ///  Sunday is 1, [1..7]
0853         inline int day_of_week_local(const date_time& dt)
0854         {
0855             return dt.get(day_of_week_local());
0856         }
0857         ///  Extract from date_time numerical value of 24 clock hour [0..23]
0858         inline int hour(const date_time& dt)
0859         {
0860             return dt.get(hour());
0861         }
0862         ///  Extract from date_time numerical value of 12 clock hour [0..11]
0863         inline int hour_12(const date_time& dt)
0864         {
0865             return dt.get(hour_12());
0866         }
0867         ///  Extract from date_time numerical value of am or pm marker [0..1]
0868         inline int am_pm(const date_time& dt)
0869         {
0870             return dt.get(am_pm());
0871         }
0872         ///  Extract from date_time numerical value of minute [0..59]
0873         inline int minute(const date_time& dt)
0874         {
0875             return dt.get(minute());
0876         }
0877         ///  Extract from date_time numerical value of second [0..59]
0878         inline int second(const date_time& dt)
0879         {
0880             return dt.get(second());
0881         }
0882         ///  Extract from date_time numerical value of The week number in the year
0883         inline int week_of_year(const date_time& dt)
0884         {
0885             return dt.get(week_of_year());
0886         }
0887         ///  Extract from date_time numerical value of The week number within current month
0888         inline int week_of_month(const date_time& dt)
0889         {
0890             return dt.get(week_of_month());
0891         }
0892         ///  Extract from date_time numerical value of First day of week, constant, for example Sunday in US = 1, Monday
0893         ///  in France = 2
0894         inline int first_day_of_week(const date_time& dt)
0895         {
0896             return dt.get(first_day_of_week());
0897         }
0898 
0899         ///  Extract from date_time_duration numerical value of duration in  Era i.e. AC, BC in Gregorian and Julian
0900         ///  calendar, range [0,1]
0901         inline int era(const date_time_duration& dt)
0902         {
0903             return dt.get(era());
0904         }
0905         ///  Extract from date_time_duration numerical value of duration in years
0906         inline int year(const date_time_duration& dt)
0907         {
0908             return dt.get(year());
0909         }
0910         ///  Extract from date_time_duration numerical value of duration in extended years (for Gregorian/Julian
0911         ///  calendars, where 1 BC == 0, 2 BC == -1).
0912         inline int extended_year(const date_time_duration& dt)
0913         {
0914             return dt.get(extended_year());
0915         }
0916         ///  Extract from date_time_duration numerical value of duration in months
0917         inline int month(const date_time_duration& dt)
0918         {
0919             return dt.get(month());
0920         }
0921         ///  Extract from date_time_duration numerical value of duration in days of month
0922         inline int day(const date_time_duration& dt)
0923         {
0924             return dt.get(day());
0925         }
0926         ///  Extract from date_time_duration numerical value of duration in days of year
0927         inline int day_of_year(const date_time_duration& dt)
0928         {
0929             return dt.get(day_of_year());
0930         }
0931         ///  Extract from date_time_duration numerical value of duration in days of week
0932         inline int day_of_week(const date_time_duration& dt)
0933         {
0934             return dt.get(day_of_week());
0935         }
0936         ///  Extract from date_time_duration numerical value of duration in original number of the day of the week in
0937         ///  month
0938         inline int day_of_week_in_month(const date_time_duration& dt)
0939         {
0940             return dt.get(day_of_week_in_month());
0941         }
0942         ///  Extract from date_time_duration numerical value of duration in local day of week
0943         inline int day_of_week_local(const date_time_duration& dt)
0944         {
0945             return dt.get(day_of_week_local());
0946         }
0947         ///  Extract from date_time_duration numerical value of duration in hours
0948         inline int hour(const date_time_duration& dt)
0949         {
0950             return dt.get(hour());
0951         }
0952         ///  Extract from date_time_duration numerical value of duration in  12 clock hours
0953         inline int hour_12(const date_time_duration& dt)
0954         {
0955             return dt.get(hour_12());
0956         }
0957         ///  Extract from date_time_duration numerical value of duration in  am or pm markers
0958         inline int am_pm(const date_time_duration& dt)
0959         {
0960             return dt.get(am_pm());
0961         }
0962         ///  Extract from date_time_duration numerical value of duration in  minutes
0963         inline int minute(const date_time_duration& dt)
0964         {
0965             return dt.get(minute());
0966         }
0967         ///  Extract from date_time_duration numerical value of duration in  seconds
0968         inline int second(const date_time_duration& dt)
0969         {
0970             return dt.get(second());
0971         }
0972         ///  Extract from date_time_duration numerical value of duration in the week number in the year
0973         inline int week_of_year(const date_time_duration& dt)
0974         {
0975             return dt.get(week_of_year());
0976         }
0977         ///  Extract from date_time_duration numerical value of duration in  The week number within current month
0978         inline int week_of_month(const date_time_duration& dt)
0979         {
0980             return dt.get(week_of_month());
0981         }
0982         ///  Extract from date_time_duration numerical value of duration in the first day of week
0983         inline int first_day_of_week(const date_time_duration& dt)
0984         {
0985             return dt.get(first_day_of_week());
0986         }
0987 
0988     } // namespace period
0989 
0990     /// @}
0991 
0992 }} // namespace boost::locale
0993 
0994 #ifdef BOOST_MSVC
0995 #    pragma warning(pop)
0996 #endif
0997 
0998 ///
0999 /// \example calendar.cpp
1000 ///
1001 /// Example of using date_time functions for generating calendar for current year.
1002 ///
1003 
1004 #endif