CppCMS
booster/locale/date_time.h
00001 //
00002 //  Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
00003 //
00004 //  Distributed under the Boost Software License, Version 1.0. (See
00005 //  accompanying file LICENSE_1_0.txt or copy at
00006 //  http://www.boost.org/LICENSE_1_0.txt)
00007 //
00008 #ifndef BOOSTER_LOCALE_DATE_TIME_H_INCLUDED
00009 #define BOOSTER_LOCALE_DATE_TIME_H_INCLUDED
00010 
00011 #include <booster/config.h>
00012 #ifdef BOOSTER_MSVC
00013 #  pragma warning(push)
00014 #  pragma warning(disable : 4275 4251 4231 4660)
00015 #endif
00016 
00017 #include <booster/locale/hold_ptr.h>
00018 #include <booster/locale/date_time_facet.h>
00019 #include <booster/locale/formatting.h>
00020 #include <booster/locale/time_zone.h>
00021 #include <locale>
00022 #include <vector>
00023 #include <booster/backtrace.h>
00024 
00025 
00026 namespace booster {
00027     namespace locale {
00034 
00035 
00039         class  date_time_error : public booster::runtime_error {
00040         public:
00044             date_time_error(std::string const &e) : booster::runtime_error(e) {}
00045         };
00046 
00047 
00056         struct date_time_period 
00057         {
00058             period::period_type type;   
00059             int value;                  
00060 
00061 
00062 
00063             date_time_period operator+() const { return *this; }
00067             date_time_period operator-() const { return date_time_period(type,-value); }
00068             
00072             date_time_period(period::period_type f=period::period_type(),int v=1) : type(f), value(v) {}
00073         };
00074 
00075         namespace period {
00079             inline period_type invalid(){ return period_type(marks::invalid); }
00083             inline period_type era(){ return period_type(marks::era); }
00087             inline period_type year(){ return period_type(marks::year); }
00091             inline period_type extended_year(){ return period_type(marks::extended_year); }
00095             inline period_type month(){ return period_type(marks::month); }
00099             inline period_type day(){ return period_type(marks::day); }
00103             inline period_type day_of_year(){ return period_type(marks::day_of_year); }
00112             inline period_type day_of_week(){ return period_type(marks::day_of_week); }
00117             inline period_type day_of_week_in_month(){ return period_type(marks::day_of_week_in_month); }
00121             inline period_type day_of_week_local(){ return period_type(marks::day_of_week_local); }
00125             inline period_type hour(){ return period_type(marks::hour); }
00129             inline period_type hour_12(){ return period_type(marks::hour_12); }
00133             inline period_type am_pm(){ return period_type(marks::am_pm); }
00137             inline period_type minute(){ return period_type(marks::minute); }
00141             inline period_type second(){ return period_type(marks::second); }
00145             inline period_type week_of_year(){ return period_type(marks::week_of_year); }
00149             inline period_type week_of_month(){ return period_type(marks::week_of_month); }
00153             inline period_type first_day_of_week(){ return period_type(marks::first_day_of_week); }
00154 
00158             inline date_time_period era(int v) { return date_time_period(era(),v); } 
00162             inline date_time_period year(int v) { return date_time_period(year(),v); } 
00166             inline date_time_period extended_year(int v) { return date_time_period(extended_year(),v); } 
00170             inline date_time_period month(int v) { return date_time_period(month(),v); } 
00174             inline date_time_period day(int v) { return date_time_period(day(),v); } 
00178             inline date_time_period day_of_year(int v) { return date_time_period(day_of_year(),v); } 
00187             inline date_time_period day_of_week(int v) { return date_time_period(day_of_week(),v); } 
00192             inline date_time_period day_of_week_in_month(int v) { return date_time_period(day_of_week_in_month(),v); } 
00196             inline date_time_period day_of_week_local(int v) { return date_time_period(day_of_week_local(),v); } 
00200             inline date_time_period hour(int v) { return date_time_period(hour(),v); } 
00204             inline date_time_period hour_12(int v) { return date_time_period(hour_12(),v); } 
00208             inline date_time_period am_pm(int v) { return date_time_period(am_pm(),v); } 
00212             inline date_time_period minute(int v) { return date_time_period(minute(),v); } 
00216             inline date_time_period second(int v) { return date_time_period(second(),v); } 
00220             inline date_time_period week_of_year(int v) { return date_time_period(week_of_year(),v); } 
00224             inline date_time_period week_of_month(int v) { return date_time_period(week_of_month(),v); } 
00228             inline date_time_period first_day_of_week(int v) { return date_time_period(first_day_of_week(),v); } 
00229 
00233             inline date_time_period january() { return date_time_period(month(),0); }
00237             inline date_time_period february() { return date_time_period(month(),1); }
00241             inline date_time_period march() { return date_time_period(month(),2); }
00245             inline date_time_period april() { return date_time_period(month(),3); }
00249             inline date_time_period may() { return date_time_period(month(),4); }
00253             inline date_time_period june() { return date_time_period(month(),5); }
00257             inline date_time_period july() { return date_time_period(month(),6); }
00261             inline date_time_period august() { return date_time_period(month(),7); }
00265             inline date_time_period september() { return date_time_period(month(),8); }
00269             inline date_time_period october() { return date_time_period(month(),9); }
00273             inline date_time_period november() { return date_time_period(month(),10); }
00277             inline date_time_period december() { return date_time_period(month(),11); }
00278 
00282             inline date_time_period sunday() { return date_time_period(day_of_week(),1); }
00286             inline date_time_period monday() { return date_time_period(day_of_week(),2); }
00290             inline date_time_period tuesday() { return date_time_period(day_of_week(),3); }
00294             inline date_time_period wednesday() { return date_time_period(day_of_week(),4); }
00298             inline date_time_period thursday() { return date_time_period(day_of_week(),5); }
00302             inline date_time_period friday() { return date_time_period(day_of_week(),6); }
00306             inline date_time_period saturday() { return date_time_period(day_of_week(),7); }
00310             inline date_time_period am() { return date_time_period(am_pm(),0); }
00314             inline date_time_period pm() { return date_time_period(am_pm(),1); }
00315 
00319             inline date_time_period operator+(period::period_type f) 
00320             {
00321                 return date_time_period(f);
00322             }
00326             inline date_time_period operator-(period::period_type f)
00327             {
00328                 return date_time_period(f,-1);
00329             }
00330 
00334             template<typename T>
00335             date_time_period operator*(period::period_type f,T v)
00336             {
00337                 return date_time_period(f,v);
00338             }
00339 
00343             template<typename T>
00344             date_time_period operator*(T v,period::period_type f)
00345             {
00346                 return date_time_period(f,v);
00347             }
00351             template<typename T>
00352             date_time_period operator*(T v,date_time_period f)
00353             {
00354                 return date_time_period(f.type,f.value*v);
00355             }
00356 
00360             template<typename T>
00361             date_time_period operator*(date_time_period f,T v)
00362             {
00363                 return date_time_period(f.type,f.value*v);
00364             }
00365 
00366 
00367         } // period
00368 
00369 
00376         class date_time_period_set {
00377         public:
00378             
00382             date_time_period_set()
00383             {
00384             }
00388             date_time_period_set(period::period_type f)
00389             {
00390                 basic_[0]=date_time_period(f);
00391             }
00395             date_time_period_set(date_time_period const &fl)
00396             {
00397                 basic_[0]=fl;
00398             }
00402             void add(date_time_period f)
00403             {
00404                 size_t n=size();
00405                 if(n < 4)
00406                     basic_[n]=f;
00407                 else
00408                     periods_.push_back(f);
00409             }
00413             size_t size() const
00414             {
00415                 if(basic_[0].type == period::period_type())
00416                     return 0;
00417                 if(basic_[1].type == period::period_type())
00418                     return 1;
00419                 if(basic_[2].type == period::period_type())
00420                     return 2;
00421                 if(basic_[3].type == period::period_type())
00422                     return 3;
00423                 return 4+periods_.size();
00424             }
00428             date_time_period const &operator[](size_t n) const 
00429             {
00430                 if(n >= size())
00431                     throw booster::out_of_range("Invalid index to date_time_period");
00432                 if(n < 4)
00433                     return basic_[n];
00434                 else
00435                     return periods_[n-4];
00436             }
00437         private:
00438             date_time_period basic_[4];
00439             std::vector<date_time_period> periods_;
00440         };
00441 
00442         
00446         inline date_time_period_set operator+(date_time_period_set const &a,date_time_period_set const &b)
00447         {
00448             date_time_period_set s(a);
00449             for(unsigned i=0;i<b.size();i++)
00450                 s.add(b[i]);
00451             return s;
00452         }
00453         
00457         inline date_time_period_set operator-(date_time_period_set const &a,date_time_period_set const &b)
00458         {
00459             date_time_period_set s(a);
00460             for(unsigned i=0;i<b.size();i++)
00461                 s.add(-b[i]);
00462             return s;
00463         }
00464 
00465 
00473         class BOOSTER_API calendar {
00474         public:
00475 
00482             calendar(std::ios_base &ios);
00488             calendar(std::locale const &l,std::string const &zone);
00494             calendar(std::locale const &l);
00500             calendar(std::string const &zone);
00506             calendar();
00507             ~calendar();
00508 
00512             calendar(calendar const &other);
00516             calendar const &operator=(calendar const &other);
00517 
00521             int minimum(period::period_type f) const;
00525             int greatest_minimum(period::period_type f) const;
00529             int maximum(period::period_type f) const;
00533             int least_maximum(period::period_type f) const;
00534 
00537             int first_day_of_week() const;
00538 
00542             std::locale get_locale() const;
00546             std::string get_time_zone() const;
00547 
00551             bool is_gregorian() const;
00552 
00556             bool operator==(calendar const &other) const;
00560             bool operator!=(calendar const &other) const;
00561 
00562         private:
00563             friend class date_time;
00564             std::locale locale_;
00565             std::string tz_;
00566             hold_ptr<abstract_calendar> impl_;
00567         };
00568 
00589         
00590         class BOOSTER_API date_time {
00591         public:
00592 
00598             date_time();
00602             date_time(date_time const &other);
00606             date_time(date_time const &other,date_time_period_set const &set);
00610             date_time const &operator=(date_time const &other);
00611             ~date_time();
00612 
00618             date_time(double time);
00622             date_time(double time,calendar const &cal);
00626             date_time(calendar const &cal);
00627             
00633             date_time(date_time_period_set const &set);
00637             date_time(date_time_period_set const &set,calendar const &cal);
00638 
00639            
00643             date_time const &operator=(date_time_period_set const &f);
00644 
00648             void set(period::period_type f,int v);
00652             int get(period::period_type f) const;
00653 
00657             int operator/(period::period_type f) const
00658             {
00659                 return get(f);
00660             }
00661 
00665             date_time operator+(period::period_type f) const
00666             {
00667                 return *this+date_time_period(f);
00668             }
00669 
00673             date_time operator-(period::period_type f) const
00674             {
00675                 return *this-date_time_period(f);
00676             }
00677 
00681             date_time const &operator+=(period::period_type f)
00682             {
00683                 return *this+=date_time_period(f);
00684             }
00688             date_time const &operator-=(period::period_type f)
00689             {
00690                 return *this-=date_time_period(f);
00691             }
00692 
00696             date_time operator<<(period::period_type f) const
00697             {
00698                 return *this<<date_time_period(f);
00699             }
00700 
00704             date_time operator>>(period::period_type f) const
00705             {
00706                 return *this>>date_time_period(f);
00707             }
00708 
00712             date_time const &operator<<=(period::period_type f)
00713             {
00714                 return *this<<=date_time_period(f);
00715             }
00719             date_time const &operator>>=(period::period_type f)
00720             {
00721                 return *this>>=date_time_period(f);
00722             }
00723 
00727             date_time operator+(date_time_period const &v) const;
00731             date_time operator-(date_time_period const &v) const;
00735             date_time const &operator+=(date_time_period const &v);
00739             date_time const &operator-=(date_time_period const &v);
00740 
00744             date_time operator<<(date_time_period const &v) const;
00748             date_time operator>>(date_time_period const &v) const ;
00752             date_time const &operator<<=(date_time_period const &v);
00756             date_time const &operator>>=(date_time_period const &v);
00757 
00761             date_time operator+(date_time_period_set const &v) const;
00765             date_time operator-(date_time_period_set const &v) const;
00769             date_time const &operator+=(date_time_period_set const &v);
00773             date_time const &operator-=(date_time_period_set const &v);
00774 
00778             date_time operator<<(date_time_period_set const &v) const;
00782             date_time operator>>(date_time_period_set const &v) const ;
00786             date_time const &operator<<=(date_time_period_set const &v);
00790             date_time const &operator>>=(date_time_period_set const &v);
00791 
00797             double time() const;
00804             void time(double v);
00805 
00809             bool operator==(date_time const &other) const;
00813             bool operator!=(date_time const &other) const;
00817             bool operator<(date_time const &other) const;
00821             bool operator>(date_time const &other) const;
00825             bool operator<=(date_time const &other) const;
00829             bool operator>=(date_time const &other) const;
00830 
00834             void swap(date_time &other);
00835 
00839             int difference(date_time const &other,period::period_type f) const;
00840 
00844             int minimum(period::period_type f) const;
00849             int maximum(period::period_type f) const;
00850 
00854             bool is_in_daylight_saving_time() const;
00855 
00856         private:
00857             hold_ptr<abstract_calendar> impl_;
00858         };
00859 
00873         template<typename CharType>
00874         std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,date_time const &t)
00875         {
00876             double time_point = t.time();
00877             uint64_t display_flags = ios_info::get(out).display_flags();
00878             if  (
00879                     display_flags == flags::date 
00880                     || display_flags == flags::time 
00881                     || display_flags == flags::datetime 
00882                     || display_flags == flags::strftime
00883                 ) 
00884             {
00885                 out << time_point;
00886             }
00887             else {
00888                 ios_info::get(out).display_flags(flags::datetime);
00889                 out << time_point;
00890                 ios_info::get(out).display_flags(display_flags);
00891             }
00892             return out;
00893         }
00894 
00900         template<typename CharType>
00901         std::basic_istream<CharType> &operator>>(std::basic_istream<CharType> &in,date_time &t)
00902         {
00903             double v;
00904             uint64_t display_flags = ios_info::get(in).display_flags();
00905             if  (
00906                     display_flags == flags::date 
00907                     || display_flags == flags::time 
00908                     || display_flags == flags::datetime 
00909                     || display_flags == flags::strftime
00910                 ) 
00911             {
00912                 in >> v;
00913             }
00914             else {
00915                 ios_info::get(in).display_flags(flags::datetime);
00916                 in >> v;
00917                 ios_info::get(in).display_flags(display_flags);
00918             }
00919             if(!in.fail())
00920                 t.time(v);
00921             return in;
00922         }
00923 
00932         class date_time_duration {
00933         public:
00934 
00939             date_time_duration(date_time const &first,date_time const &second) :
00940                 s_(first),
00941                 e_(second)
00942             {
00943             }
00944             
00948             int get(period::period_type f) const
00949             {
00950                 return start().difference(end(),f);
00951             }
00952 
00956             int operator / (period::period_type f) const
00957             {
00958                 return start().difference(end(),f);
00959             }
00960 
00964             date_time const &start() const { return s_; }
00968             date_time const &end() const { return e_; }
00969         private:
00970             date_time const &s_;
00971             date_time const &e_;
00972         };
00973 
00978         inline date_time_duration operator-(date_time const &later,date_time const &earlier)
00979         {
00980             return date_time_duration(earlier,later);
00981         }
00982 
00983         
00984         namespace period {
00988             inline int era(date_time const &dt) { return dt.get(era()); } 
00992             inline int year(date_time const &dt) { return dt.get(year()); } 
00996             inline int extended_year(date_time const &dt) { return dt.get(extended_year()); } 
01000             inline int month(date_time const &dt) { return dt.get(month()); } 
01004             inline int day(date_time const &dt) { return dt.get(day()); } 
01008             inline int day_of_year(date_time const &dt) { return dt.get(day_of_year()); } 
01017             inline int day_of_week(date_time const &dt) { return dt.get(day_of_week()); } 
01022             inline int day_of_week_in_month(date_time const &dt) { return dt.get(day_of_week_in_month()); } 
01026             inline int day_of_week_local(date_time const &dt) { return dt.get(day_of_week_local()); } 
01030             inline int hour(date_time const &dt) { return dt.get(hour()); } 
01034             inline int hour_12(date_time const &dt) { return dt.get(hour_12()); } 
01038             inline int am_pm(date_time const &dt) { return dt.get(am_pm()); } 
01042             inline int minute(date_time const &dt) { return dt.get(minute()); } 
01046             inline int second(date_time const &dt) { return dt.get(second()); } 
01050             inline int week_of_year(date_time const &dt) { return dt.get(week_of_year()); } 
01054             inline int week_of_month(date_time const &dt) { return dt.get(week_of_month()); } 
01058             inline int first_day_of_week(date_time const &dt) { return dt.get(first_day_of_week()); } 
01059             
01063             inline int era(date_time_duration const &dt) { return dt.get(era()); } 
01067             inline int year(date_time_duration const &dt) { return dt.get(year()); } 
01071             inline int extended_year(date_time_duration const &dt) { return dt.get(extended_year()); } 
01075             inline int month(date_time_duration const &dt) { return dt.get(month()); } 
01079             inline int day(date_time_duration const &dt) { return dt.get(day()); } 
01083             inline int day_of_year(date_time_duration const &dt) { return dt.get(day_of_year()); } 
01087             inline int day_of_week(date_time_duration const &dt) { return dt.get(day_of_week()); } 
01091             inline int day_of_week_in_month(date_time_duration const &dt) { return dt.get(day_of_week_in_month()); } 
01095             inline int day_of_week_local(date_time_duration const &dt) { return dt.get(day_of_week_local()); } 
01099             inline int hour(date_time_duration const &dt) { return dt.get(hour()); } 
01103             inline int hour_12(date_time_duration const &dt) { return dt.get(hour_12()); } 
01107             inline int am_pm(date_time_duration const &dt) { return dt.get(am_pm()); } 
01111             inline int minute(date_time_duration const &dt) { return dt.get(minute()); } 
01115             inline int second(date_time_duration const &dt) { return dt.get(second()); } 
01119             inline int week_of_year(date_time_duration const &dt) { return dt.get(week_of_year()); } 
01123             inline int week_of_month(date_time_duration const &dt) { return dt.get(week_of_month()); } 
01127             inline int first_day_of_week(date_time_duration const &dt) { return dt.get(first_day_of_week()); } 
01128 
01129 
01130         }
01131         
01133 
01134 
01135     } // locale
01136 } // boost
01137 
01138 #ifdef BOOSTER_MSVC
01139 #pragma warning(pop)
01140 #endif
01141 
01142 
01143 #endif
01144 
01145 
01146 
01147 
01148 
01149 
01150 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4