123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- #ifndef _DATE_TIME_POSIX_TIME_ZONE__
- #define _DATE_TIME_POSIX_TIME_ZONE__
- #include <string>
- #include <sstream>
- #include <stdexcept>
- #include <boost/tokenizer.hpp>
- #include <boost/throw_exception.hpp>
- #include <boost/date_time/compiler_config.hpp>
- #include <boost/date_time/gregorian/gregorian.hpp>
- #include <boost/date_time/time_zone_names.hpp>
- #include <boost/date_time/time_zone_base.hpp>
- #include <boost/date_time/local_time/dst_transition_day_rules.hpp>
- #include <boost/date_time/posix_time/posix_time.hpp>
- #include <boost/date_time/string_convert.hpp>
- #include <boost/date_time/time_parsing.hpp>
- namespace boost{
- namespace local_time{
-
- struct BOOST_SYMBOL_VISIBLE bad_offset : public std::out_of_range
- {
- bad_offset(std::string const& msg = std::string()) :
- std::out_of_range(std::string("Offset out of range: " + msg)) {}
- };
-
- struct BOOST_SYMBOL_VISIBLE bad_adjustment : public std::out_of_range
- {
- bad_adjustment(std::string const& msg = std::string()) :
- std::out_of_range(std::string("Adjustment out of range: " + msg)) {}
- };
- typedef boost::date_time::dst_adjustment_offsets<boost::posix_time::time_duration> dst_adjustment_offsets;
-
-
- template<class CharT>
- class BOOST_SYMBOL_VISIBLE posix_time_zone_base : public date_time::time_zone_base<posix_time::ptime,CharT> {
- public:
- typedef boost::posix_time::time_duration time_duration_type;
- typedef date_time::time_zone_names_base<CharT> time_zone_names;
- typedef date_time::time_zone_base<posix_time::ptime,CharT> base_type;
- typedef typename base_type::string_type string_type;
- typedef CharT char_type;
- typedef typename base_type::stringstream_type stringstream_type;
- typedef boost::char_separator<char_type, std::char_traits<char_type> > char_separator_type;
- typedef boost::tokenizer<char_separator_type,
- typename string_type::const_iterator,
- string_type> tokenizer_type;
- typedef typename tokenizer_type::iterator tokenizer_iterator_type;
-
- posix_time_zone_base(const string_type& s) :
-
- zone_names_(),
- has_dst_(false),
- base_utc_offset_(posix_time::hours(0)),
- dst_offsets_(posix_time::hours(0),posix_time::hours(0),posix_time::hours(0)),
- dst_calc_rules_()
- {
- #ifdef __HP_aCC
-
-
- const char_type sep_chars[2] = {',',0};
- #else
- const char_type sep_chars[2] = {','};
- #endif
- char_separator_type sep(sep_chars);
- tokenizer_type tokens(s, sep);
- tokenizer_iterator_type it = tokens.begin(), end = tokens.end();
- if (it == end)
- BOOST_THROW_EXCEPTION(std::invalid_argument("Could not parse time zone name"));
- calc_zone(*it++);
- if(has_dst_)
- {
- if (it == end)
- BOOST_THROW_EXCEPTION(std::invalid_argument("Could not parse DST begin time"));
- string_type dst_begin = *it++;
- if (it == end)
- BOOST_THROW_EXCEPTION(std::invalid_argument("Could not parse DST end time"));
- string_type dst_end = *it;
- calc_rules(dst_begin, dst_end);
- }
- }
- virtual ~posix_time_zone_base() {}
-
- virtual string_type std_zone_abbrev()const
- {
- return zone_names_.std_zone_abbrev();
- }
-
-
- virtual string_type dst_zone_abbrev() const
- {
- return zone_names_.dst_zone_abbrev();
- }
-
-
- virtual string_type std_zone_name()const
- {
- return zone_names_.std_zone_name();
- }
-
-
- virtual string_type dst_zone_name()const
- {
- return zone_names_.dst_zone_name();
- }
-
- virtual bool has_dst()const
- {
- return has_dst_;
- }
-
- virtual posix_time::ptime dst_local_start_time(gregorian::greg_year y)const
- {
- gregorian::date d(gregorian::not_a_date_time);
- if(has_dst_)
- {
- d = dst_calc_rules_->start_day(y);
- }
- return posix_time::ptime(d, dst_offsets_.dst_start_offset_);
- }
-
- virtual posix_time::ptime dst_local_end_time(gregorian::greg_year y)const
- {
- gregorian::date d(gregorian::not_a_date_time);
- if(has_dst_)
- {
- d = dst_calc_rules_->end_day(y);
- }
- return posix_time::ptime(d, dst_offsets_.dst_end_offset_);
- }
-
- virtual time_duration_type base_utc_offset()const
- {
- return base_utc_offset_;
- }
-
- virtual time_duration_type dst_offset()const
- {
- return dst_offsets_.dst_adjust_;
- }
-
- virtual string_type to_posix_string() const
- {
-
- stringstream_type ss;
- ss.fill('0');
- boost::shared_ptr<dst_calc_rule> no_rules;
-
- ss << std_zone_abbrev();
-
- if(base_utc_offset().is_negative()) {
-
- ss << '-' << std::setw(2) << base_utc_offset().invert_sign().hours();
- }
- else {
- ss << '+' << std::setw(2) << base_utc_offset().hours();
- }
- if(base_utc_offset().minutes() != 0 || base_utc_offset().seconds() != 0) {
- ss << ':' << std::setw(2) << base_utc_offset().minutes();
- if(base_utc_offset().seconds() != 0) {
- ss << ':' << std::setw(2) << base_utc_offset().seconds();
- }
- }
- if(dst_calc_rules_ != no_rules) {
-
- ss << dst_zone_abbrev();
-
- if(dst_offset().is_negative()) {
-
- ss << '-' << std::setw(2) << dst_offset().invert_sign().hours();
- }
- else {
- ss << '+' << std::setw(2) << dst_offset().hours();
- }
- if(dst_offset().minutes() != 0 || dst_offset().seconds() != 0) {
- ss << ':' << std::setw(2) << dst_offset().minutes();
- if(dst_offset().seconds() != 0) {
- ss << ':' << std::setw(2) << dst_offset().seconds();
- }
- }
-
- ss << ',' << date_time::convert_string_type<char, char_type>(dst_calc_rules_->start_rule_as_string()) << '/'
- << std::setw(2) << dst_offsets_.dst_start_offset_.hours() << ':'
- << std::setw(2) << dst_offsets_.dst_start_offset_.minutes();
- if(dst_offsets_.dst_start_offset_.seconds() != 0) {
- ss << ':' << std::setw(2) << dst_offsets_.dst_start_offset_.seconds();
- }
-
- ss << ',' << date_time::convert_string_type<char, char_type>(dst_calc_rules_->end_rule_as_string()) << '/'
- << std::setw(2) << dst_offsets_.dst_end_offset_.hours() << ':'
- << std::setw(2) << dst_offsets_.dst_end_offset_.minutes();
- if(dst_offsets_.dst_end_offset_.seconds() != 0) {
- ss << ':' << std::setw(2) << dst_offsets_.dst_end_offset_.seconds();
- }
- }
- return ss.str();
- }
- private:
- time_zone_names zone_names_;
- bool has_dst_;
- time_duration_type base_utc_offset_;
- dst_adjustment_offsets dst_offsets_;
- boost::shared_ptr<dst_calc_rule> dst_calc_rules_;
-
- void calc_zone(const string_type& obj){
- const char_type empty_string[2] = {'\0'};
- stringstream_type ss(empty_string);
- typename string_type::const_pointer sit = obj.c_str(), obj_end = sit + obj.size();
- string_type l_std_zone_abbrev, l_dst_zone_abbrev;
-
- while(std::isalpha(*sit)){
- ss << *sit++;
- }
- l_std_zone_abbrev = ss.str();
- ss.str(empty_string);
-
- if(sit != obj_end){
-
- while(sit != obj_end && !std::isalpha(*sit)){
- ss << *sit++;
- }
- base_utc_offset_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(ss.str());
- ss.str(empty_string);
-
- if(base_utc_offset_ < time_duration_type(-12,0,0) ||
- base_utc_offset_ > time_duration_type(14,0,0))
- {
- boost::throw_exception(bad_offset(posix_time::to_simple_string(base_utc_offset_)));
- }
- }
-
- if(sit != obj_end){
- has_dst_ = true;
-
- while(sit != obj_end && std::isalpha(*sit)){
- ss << *sit++;
- }
- l_dst_zone_abbrev = ss.str();
- ss.str(empty_string);
-
- if(sit != obj_end){
-
- while(sit != obj_end && !std::isalpha(*sit)){
- ss << *sit++;
- }
- dst_offsets_.dst_adjust_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(ss.str());
- ss.str(empty_string);
- }
- else{
- dst_offsets_.dst_adjust_ = posix_time::hours(1);
- }
-
- if(dst_offsets_.dst_adjust_ <= time_duration_type(-24,0,0) ||
- dst_offsets_.dst_adjust_ >= time_duration_type(24,0,0))
- {
- boost::throw_exception(bad_adjustment(posix_time::to_simple_string(dst_offsets_.dst_adjust_)));
- }
- }
-
- zone_names_ = time_zone_names(l_std_zone_abbrev, l_std_zone_abbrev, l_dst_zone_abbrev, l_dst_zone_abbrev);
- }
- void calc_rules(const string_type& start, const string_type& end){
- #ifdef __HP_aCC
-
-
- const char_type sep_chars[2] = {'/',0};
- #else
- const char_type sep_chars[2] = {'/'};
- #endif
- char_separator_type sep(sep_chars);
- tokenizer_type st_tok(start, sep);
- tokenizer_type et_tok(end, sep);
- tokenizer_iterator_type sit = st_tok.begin();
- tokenizer_iterator_type eit = et_tok.begin();
-
- char_type x = string_type(*sit).at(0);
- if(x == 'M'){
- M_func(*sit, *eit);
- }
- else if(x == 'J'){
- julian_no_leap(*sit, *eit);
- }
- else{
- julian_day(*sit, *eit);
- }
- ++sit;
- ++eit;
-
-
- if(sit != st_tok.end()){
- dst_offsets_.dst_start_offset_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(*sit);
- }
- else{
-
- dst_offsets_.dst_start_offset_ = posix_time::hours(2);
- }
-
- if(dst_offsets_.dst_start_offset_ < time_duration_type(0,0,0) ||
- dst_offsets_.dst_start_offset_ >= time_duration_type(24,0,0))
- {
- boost::throw_exception(bad_offset(posix_time::to_simple_string(dst_offsets_.dst_start_offset_)));
- }
-
- if(eit != et_tok.end()){
- dst_offsets_.dst_end_offset_ = date_time::str_from_delimited_time_duration<time_duration_type,char_type>(*eit);
- }
- else{
-
- dst_offsets_.dst_end_offset_ = posix_time::hours(2);
- }
-
- if(dst_offsets_.dst_end_offset_ < time_duration_type(0,0,0) ||
- dst_offsets_.dst_end_offset_ >= time_duration_type(24,0,0))
- {
- boost::throw_exception(bad_offset(posix_time::to_simple_string(dst_offsets_.dst_end_offset_)));
- }
- }
-
- void M_func(const string_type& s, const string_type& e){
- typedef gregorian::nth_kday_of_month nkday;
- unsigned short sm=0,sw=0,sd=0,em=0,ew=0,ed=0;
- #ifdef __HP_aCC
-
-
- const char_type sep_chars[3] = {'M','.',0};
- #else
- const char_type sep_chars[3] = {'M','.'};
- #endif
- char_separator_type sep(sep_chars);
- tokenizer_type stok(s, sep), etok(e, sep);
- tokenizer_iterator_type it = stok.begin();
- sm = lexical_cast<unsigned short>(*it++);
- sw = lexical_cast<unsigned short>(*it++);
- sd = lexical_cast<unsigned short>(*it);
- it = etok.begin();
- em = lexical_cast<unsigned short>(*it++);
- ew = lexical_cast<unsigned short>(*it++);
- ed = lexical_cast<unsigned short>(*it);
- dst_calc_rules_ = shared_ptr<dst_calc_rule>(
- new nth_kday_dst_rule(
- nth_last_dst_rule::start_rule(
- static_cast<nkday::week_num>(sw),sd,sm),
- nth_last_dst_rule::start_rule(
- static_cast<nkday::week_num>(ew),ed,em)
- )
- );
- }
-
-
- void julian_no_leap(const string_type& s, const string_type& e){
- typedef gregorian::gregorian_calendar calendar;
- const unsigned short year = 2001;
- unsigned short sm=1;
- int sd=0;
- sd = lexical_cast<int>(s.substr(1));
- while(sd >= calendar::end_of_month_day(year,sm)){
- sd -= calendar::end_of_month_day(year,sm++);
- }
- unsigned short em=1;
- int ed=0;
- ed = lexical_cast<int>(e.substr(1));
- while(ed > calendar::end_of_month_day(year,em)){
- ed -= calendar::end_of_month_day(year,em++);
- }
- dst_calc_rules_ = shared_ptr<dst_calc_rule>(
- new partial_date_dst_rule(
- partial_date_dst_rule::start_rule(
- static_cast<unsigned short>(sd), static_cast<date_time::months_of_year>(sm)),
- partial_date_dst_rule::end_rule(
- static_cast<unsigned short>(ed), static_cast<date_time::months_of_year>(em))
- )
- );
- }
-
-
- void julian_day(const string_type& s, const string_type& e){
- int sd=0, ed=0;
- sd = lexical_cast<int>(s);
- ed = lexical_cast<int>(e);
- dst_calc_rules_ = shared_ptr<dst_calc_rule>(
- new partial_date_dst_rule(
- partial_date_dst_rule::start_rule(++sd),
- partial_date_dst_rule::end_rule(++ed)
- )
- );
- }
-
- static std::string td_as_string(const time_duration_type& td)
- {
- std::string s;
- #if defined(USE_DATE_TIME_PRE_1_33_FACET_IO)
- s = posix_time::to_simple_string(td);
- #else
- std::stringstream ss;
- ss << td;
- s = ss.str();
- #endif
- return s;
- }
- };
- typedef posix_time_zone_base<char> posix_time_zone;
- } }
- #endif
|