From b682900d0817df3c8fc48b36cb156c17e6c53e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Thu, 9 Jun 2011 20:18:09 +0200 Subject: Added boost/local_time. diff --git a/3rdParty/Boost/src/boost/date_time/dst_transition_generators.hpp b/3rdParty/Boost/src/boost/date_time/dst_transition_generators.hpp new file mode 100644 index 0000000..6c4da1c --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/dst_transition_generators.hpp @@ -0,0 +1,75 @@ +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + */ +#ifndef DATE_TIME_DATE_DST_TRANSITION_DAY_GEN_HPP__ +#define DATE_TIME_DATE_DST_TRANSITION_DAY_GEN_HPP__ + + + +namespace boost { +namespace date_time { + + //! Defines base interface for calculating start and end date of daylight savings + template + class dst_day_calc_rule + { + public: + typedef typename date_type::year_type year_type; + virtual ~dst_day_calc_rule() {}; + virtual date_type start_day(year_type y) const=0; + virtual std::string start_rule_as_string() const=0; + virtual date_type end_day(year_type y) const=0; + virtual std::string end_rule_as_string() const=0; + + }; + + //! Canonical form for a class that provides day rule calculation + /*! This class is used to generate specific sets of dst rules + * + *@param spec Provides a specifiction of the function object types used + * to generate start and end days of daylight savings as well + * as the date type. + */ + template + class day_calc_dst_rule : public dst_day_calc_rule + { + public: + typedef typename spec::date_type date_type; + typedef typename date_type::year_type year_type; + typedef typename spec::start_rule start_rule; + typedef typename spec::end_rule end_rule; + day_calc_dst_rule(start_rule dst_start, + end_rule dst_end) : + dst_start_(dst_start), + dst_end_(dst_end) + {} + virtual date_type start_day(year_type y) const + { + return dst_start_.get_date(y); + } + virtual std::string start_rule_as_string() const + { + return dst_start_.to_string(); + } + virtual date_type end_day(year_type y) const + { + return dst_end_.get_date(y); + } + virtual std::string end_rule_as_string() const + { + return dst_end_.to_string(); + } + private: + start_rule dst_start_; + end_rule dst_end_; + }; + + +} }//namespace + + + +#endif diff --git a/3rdParty/Boost/src/boost/date_time/local_time/conversion.hpp b/3rdParty/Boost/src/boost/date_time/local_time/conversion.hpp new file mode 100644 index 0000000..13e4d3e --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/conversion.hpp @@ -0,0 +1,34 @@ +#ifndef DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ +#define DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2009-06-04 04:24:49 -0400 (Thu, 04 Jun 2009) $ + */ + + +#include "boost/date_time/posix_time/conversion.hpp" +#include "boost/date_time/c_time.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" + +namespace boost { +namespace local_time { + +//! Function that creates a tm struct from a local_date_time +inline +std::tm to_tm(const local_date_time& lt) { + std::tm lt_tm = posix_time::to_tm(lt.local_time()); + if(lt.is_dst()){ + lt_tm.tm_isdst = 1; + } + else{ + lt_tm.tm_isdst = 0; + } + return lt_tm; +} + + +}} // namespaces +#endif // DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ diff --git a/3rdParty/Boost/src/boost/date_time/local_time/custom_time_zone.hpp b/3rdParty/Boost/src/boost/date_time/local_time/custom_time_zone.hpp new file mode 100644 index 0000000..a6c1d42 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/custom_time_zone.hpp @@ -0,0 +1,169 @@ +#ifndef LOCAL_TIME_CUSTOM_TIME_ZONE_HPP__ +#define LOCAL_TIME_CUSTOM_TIME_ZONE_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/time_zone_base.hpp" +#include "boost/date_time/time_zone_names.hpp" +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/local_time/dst_transition_day_rules.hpp" +#include "boost/date_time/string_convert.hpp" +//#include "boost/date_time/special_defs.hpp" +#include "boost/shared_ptr.hpp" + +namespace boost { +namespace local_time { + + //typedef boost::date_time::time_zone_names time_zone_names; + typedef boost::date_time::dst_adjustment_offsets dst_adjustment_offsets; + //typedef boost::date_time::time_zone_base time_zone; + typedef boost::shared_ptr dst_calc_rule_ptr; + + //! A real time zone + template + class custom_time_zone_base : public date_time::time_zone_base { + public: + typedef boost::posix_time::time_duration time_duration_type; + typedef date_time::time_zone_base base_type; + typedef typename base_type::string_type string_type; + typedef typename base_type::stringstream_type stringstream_type; + typedef date_time::time_zone_names_base time_zone_names; + typedef CharT char_type; + + custom_time_zone_base(const time_zone_names& zone_names, + const time_duration_type& utc_offset, + const dst_adjustment_offsets& dst_shift, + boost::shared_ptr calc_rule) : + zone_names_(zone_names), + base_utc_offset_(utc_offset), + dst_offsets_(dst_shift), + dst_calc_rules_(calc_rule) + {}; + virtual ~custom_time_zone_base() {}; + virtual string_type dst_zone_abbrev() const + { + return zone_names_.dst_zone_abbrev(); + } + virtual string_type std_zone_abbrev() const + { + return zone_names_.std_zone_abbrev(); + } + virtual string_type dst_zone_name() const + { + return zone_names_.dst_zone_name(); + } + virtual string_type std_zone_name() const + { + return zone_names_.std_zone_name(); + } + //! True if zone uses daylight savings adjustments + virtual bool has_dst() const + { + return (dst_calc_rules_); //if calc_rule is set the tz has dst + } + //! Local time that DST starts -- NADT if has_dst is false + virtual posix_time::ptime dst_local_start_time(gregorian::greg_year y) const + { + gregorian::date d(gregorian::not_a_date_time); + if (dst_calc_rules_) { + d = dst_calc_rules_->start_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_start_offset_); + } + //! Local time that DST ends -- NADT if has_dst is false + virtual posix_time::ptime dst_local_end_time(gregorian::greg_year y) const + { + gregorian::date d(gregorian::not_a_date_time); + if (dst_calc_rules_) { + d = dst_calc_rules_->end_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_end_offset_); + } + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset() const + { + return base_utc_offset_; + } + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset() const + { + return dst_offsets_.dst_adjust_; + } + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const + { + // std offset dst [offset],start[/time],end[/time] - w/o spaces + stringstream_type ss; + ss.fill('0'); + boost::shared_ptr no_rules; + // std + ss << std_zone_abbrev(); + // offset + if(base_utc_offset().is_negative()) { + // inverting the sign guarantees we get two digits + 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) { + // dst + ss << dst_zone_abbrev(); + // dst offset + if(dst_offset().is_negative()) { + // inverting the sign guarantees we get two digits + 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(); + } + } + // start/time + ss << ',' << date_time::convert_string_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(); + } + // end/time + ss << ',' << date_time::convert_string_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_rules_; + }; + + typedef custom_time_zone_base custom_time_zone; + +} }//namespace + + + +#endif diff --git a/3rdParty/Boost/src/boost/date_time/local_time/date_duration_operators.hpp b/3rdParty/Boost/src/boost/date_time/local_time/date_duration_operators.hpp new file mode 100644 index 0000000..ee87022 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/date_duration_operators.hpp @@ -0,0 +1,115 @@ +#ifndef LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ +#define LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/greg_duration_types.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" + +namespace boost { +namespace local_time { + + /*!@file date_duration_operators.hpp Operators for local_date_time and + * optional gregorian types. Operators use snap-to-end-of-month behavior. + * Further details on this behavior can be found in reference for + * date_time/date_duration_types.hpp and documentation for + * month and year iterators. + */ + + + /*! Adds a months object and a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator+(const local_date_time& t, const boost::gregorian::months& m) + { + return t + m.get_offset(t.utc_time().date()); + } + + /*! Adds a months object to a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator+=(local_date_time& t, const boost::gregorian::months& m) + { + return t += m.get_offset(t.utc_time().date()); + } + + /*! Subtracts a months object and a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator-(const local_date_time& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t + m.get_neg_offset(t.utc_time().date()); + } + + /*! Subtracts a months object from a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator-=(local_date_time& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t += m.get_neg_offset(t.utc_time().date()); + } + + // local_date_time & years + + /*! Adds a years object and a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator+(const local_date_time& t, const boost::gregorian::years& y) + { + return t + y.get_offset(t.utc_time().date()); + } + + /*! Adds a years object to a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator+=(local_date_time& t, const boost::gregorian::years& y) + { + return t += y.get_offset(t.utc_time().date()); + } + + /*! Subtracts a years object and a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator-(const local_date_time& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t + y.get_neg_offset(t.utc_time().date()); + } + + /*! Subtracts a years object from a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator-=(local_date_time& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t += y.get_neg_offset(t.utc_time().date()); + } + + +}} // namespaces + +#endif // LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ diff --git a/3rdParty/Boost/src/boost/date_time/local_time/dst_transition_day_rules.hpp b/3rdParty/Boost/src/boost/date_time/local_time/dst_transition_day_rules.hpp new file mode 100644 index 0000000..3d6cfba --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/dst_transition_day_rules.hpp @@ -0,0 +1,77 @@ +#ifndef LOCAL_TIME_DST_TRANSITION_DAY_RULES_HPP__ +#define LOCAL_TIME_DST_TRANSITION_DAY_RULES_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/dst_transition_generators.hpp" + +namespace boost { +namespace local_time { + + //! Provides rule of the form starting Apr 30 ending Oct 21 + typedef date_time::dst_day_calc_rule dst_calc_rule; + + struct partial_date_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::partial_date start_rule; + typedef gregorian::partial_date end_rule; + }; + + //! Provides rule of the form first Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule partial_date_dst_rule; + + struct first_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::first_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule of the form first Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule first_last_dst_rule; + + struct last_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::last_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule of the form last Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule last_last_dst_rule; + + struct nth_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::nth_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April, last Sunday in Oct + typedef date_time::day_calc_dst_rule nth_last_dst_rule; + + struct nth_kday_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::nth_kday_of_month start_rule; + typedef gregorian::nth_kday_of_month end_rule; + }; + + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April/October + typedef date_time::day_calc_dst_rule nth_kday_dst_rule; + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April/October + typedef date_time::day_calc_dst_rule nth_day_of_the_week_in_month_dst_rule; + + +} }//namespace + + +#endif diff --git a/3rdParty/Boost/src/boost/date_time/local_time/local_date_time.hpp b/3rdParty/Boost/src/boost/date_time/local_time/local_date_time.hpp new file mode 100644 index 0000000..9c9f623 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/local_date_time.hpp @@ -0,0 +1,528 @@ +#ifndef LOCAL_TIME_LOCAL_DATE_TIME_HPP__ +#define LOCAL_TIME_LOCAL_DATE_TIME_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2010-01-10 14:17:23 -0500 (Sun, 10 Jan 2010) $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include //todo remove? +#include +#include +#include +#include // absolute_value + +namespace boost { +namespace local_time { + + //! simple exception for reporting when STD or DST cannot be determined + struct ambiguous_result : public std::logic_error + { + ambiguous_result (std::string const& msg = std::string()) : + std::logic_error(std::string("Daylight Savings Results are ambiguous: " + msg)) {} + }; + //! simple exception for when time label given cannot exist + struct time_label_invalid : public std::logic_error + { + time_label_invalid (std::string const& msg = std::string()) : + std::logic_error(std::string("Time label given is invalid: " + msg)) {} + }; + struct dst_not_valid: public std::logic_error + { + dst_not_valid(std::string const& msg = std::string()) : + std::logic_error(std::string("is_dst flag does not match resulting dst for time label given: " + msg)) {} + }; + + //TODO: I think these should be in local_date_time_base and not + // necessarily brought into the namespace + using date_time::time_is_dst_result; + using date_time::is_in_dst; + using date_time::is_not_in_dst; + using date_time::ambiguous; + using date_time::invalid_time_label; + + //! Representation of "wall-clock" time in a particular time zone + /*! Representation of "wall-clock" time in a particular time zone + * Local_date_time_base holds a time value (date and time offset from 00:00) + * along with a time zone. The time value is stored as UTC and conversions + * to wall clock time are made as needed. This approach allows for + * operations between wall-clock times in different time zones, and + * daylight savings time considerations, to be made. Time zones are + * required to be in the form of a boost::shared_ptr. + */ + template > + class local_date_time_base : public date_time::base_time { + public: + typedef utc_time_ utc_time_type; + typedef typename utc_time_type::time_duration_type time_duration_type; + typedef typename utc_time_type::date_type date_type; + typedef typename date_type::duration_type date_duration_type; + typedef typename utc_time_type::time_system_type time_system_type; + /*! This constructor interprets the passed time as a UTC time. + * So, for example, if the passed timezone is UTC-5 then the + * time will be adjusted back 5 hours. The time zone allows for + * automatic calculation of whether the particular time is adjusted for + * daylight savings, etc. + * If the time zone shared pointer is null then time stays unadjusted. + *@param t A UTC time + *@param tz Timezone for to adjust the UTC time to. + */ + local_date_time_base(utc_time_type t, + boost::shared_ptr tz) : + date_time::base_time(t), + zone_(tz) + { + // param was already utc so nothing more to do + } + + /*! This constructs a local time -- the passed time information + * understood to be in the passed tz. The DST flag must be passed + * to indicate whether the time is in daylight savings or not. + * @throws -- time_label_invalid if the time passed does not exist in + * the given locale. The non-existent case occurs typically + * during the shift-back from daylight savings time. When + * the clock is shifted forward a range of times + * (2 am to 3 am in the US) is skipped and hence is invalid. + * @throws -- dst_not_valid if the DST flag is passed for a period + * where DST is not active. + */ + local_date_time_base(date_type d, + time_duration_type td, + boost::shared_ptr tz, + bool dst_flag) : //necessary for constr_adj() + date_time::base_time(construction_adjustment(utc_time_type(d, td), tz, dst_flag)), + zone_(tz) + { + if(tz != boost::shared_ptr() && tz->has_dst()){ + + // d & td are already local so we use them + time_is_dst_result result = check_dst(d, td, tz); + bool in_dst = (result == is_in_dst); // less processing than is_dst() + + // ambig occurs at end, invalid at start + if(result == invalid_time_label){ + // Ex: 2:15am local on trans-in day in nyc, dst_flag irrelevant + std::ostringstream ss; + ss << "time given: " << d << ' ' << td; + boost::throw_exception(time_label_invalid(ss.str())); + } + else if(result != ambiguous && in_dst != dst_flag){ + // is dst_flag accurate? + // Ex: false flag in NYC in June + std::ostringstream ss; + ss.setf(std::ios_base::boolalpha); + ss << "flag given: dst=" << dst_flag << ", dst calculated: dst=" << in_dst; + boost::throw_exception(dst_not_valid(ss.str())); + } + + // everything checks out and conversion to utc already done + } + } + + //TODO maybe not the right set...Ignore the last 2 for now... + enum DST_CALC_OPTIONS { EXCEPTION_ON_ERROR, NOT_DATE_TIME_ON_ERROR }; + //ASSUME_DST_ON_ERROR, ASSUME_NOT_DST_ON_ERROR }; + + /*! This constructs a local time -- the passed time information + * understood to be in the passed tz. The DST flag is calculated + * according to the specified rule. + */ + local_date_time_base(date_type d, + time_duration_type td, + boost::shared_ptr tz, + DST_CALC_OPTIONS calc_option) : + // dummy value - time_ is set in constructor code + date_time::base_time(utc_time_type(d,td)), + zone_(tz) + { + time_is_dst_result result = check_dst(d, td, tz); + if(result == ambiguous) { + if(calc_option == EXCEPTION_ON_ERROR){ + std::ostringstream ss; + ss << "time given: " << d << ' ' << td; + boost::throw_exception(ambiguous_result(ss.str())); + } + else{ // NADT on error + this->time_ = posix_time::posix_time_system::get_time_rep(date_type(date_time::not_a_date_time), time_duration_type(date_time::not_a_date_time)); + } + } + else if(result == invalid_time_label){ + if(calc_option == EXCEPTION_ON_ERROR){ + std::ostringstream ss; + ss << "time given: " << d << ' ' << td; + boost::throw_exception(time_label_invalid(ss.str())); + } + else{ // NADT on error + this->time_ = posix_time::posix_time_system::get_time_rep(date_type(date_time::not_a_date_time), time_duration_type(date_time::not_a_date_time)); + } + } + else if(result == is_in_dst){ + utc_time_type t = + construction_adjustment(utc_time_type(d, td), tz, true); + this->time_ = posix_time::posix_time_system::get_time_rep(t.date(), + t.time_of_day()); + } + else{ + utc_time_type t = + construction_adjustment(utc_time_type(d, td), tz, false); + this->time_ = posix_time::posix_time_system::get_time_rep(t.date(), + t.time_of_day()); + } + } + + + //! Determines if given time label is in daylight savings for given zone + /*! Determines if given time label is in daylight savings for given zone. + * Takes a date and time_duration representing a local time, along + * with time zone, and returns a time_is_dst_result object as result. + */ + static time_is_dst_result check_dst(date_type d, + time_duration_type td, + boost::shared_ptr tz) + { + if(tz != boost::shared_ptr() && tz->has_dst()) { + typedef typename date_time::dst_calculator dst_calculator; + return dst_calculator::local_is_dst( + d, td, + tz->dst_local_start_time(d.year()).date(), + tz->dst_local_start_time(d.year()).time_of_day(), + tz->dst_local_end_time(d.year()).date(), + tz->dst_local_end_time(d.year()).time_of_day(), + tz->dst_offset() + ); + } + else{ + return is_not_in_dst; + } + } + + //! Simple destructor, releases time zone if last referrer + ~local_date_time_base() {}; + + //! Copy constructor + local_date_time_base(const local_date_time_base& rhs) : + date_time::base_time(rhs), + zone_(rhs.zone_) + {} + + //! Special values constructor + explicit local_date_time_base(const boost::date_time::special_values sv, + boost::shared_ptr tz = boost::shared_ptr()) : + date_time::base_time(utc_time_type(sv)), + zone_(tz) + {} + + //! returns time zone associated with calling instance + boost::shared_ptr zone() const + { + return zone_; + } + //! returns false is time_zone is NULL and if time value is a special_value + bool is_dst() const + { + if(zone_ != boost::shared_ptr() && zone_->has_dst() && !this->is_special()) { + // check_dst takes a local time, *this is utc + utc_time_type lt(this->time_); + lt += zone_->base_utc_offset(); + // dst_offset only needs to be considered with ambiguous time labels + // make that adjustment there + + switch(check_dst(lt.date(), lt.time_of_day(), zone_)){ + case is_not_in_dst: + return false; + case is_in_dst: + return true; + case ambiguous: + if(lt + zone_->dst_offset() < zone_->dst_local_end_time(lt.date().year())) { + return true; + } + break; + case invalid_time_label: + if(lt >= zone_->dst_local_start_time(lt.date().year())) { + return true; + } + break; + } + } + return false; + } + //! Returns object's time value as a utc representation + utc_time_type utc_time() const + { + return utc_time_type(this->time_); + } + //! Returns object's time value as a local representation + utc_time_type local_time() const + { + if(zone_ != boost::shared_ptr()){ + utc_time_type lt = this->utc_time() + zone_->base_utc_offset(); + if (is_dst()) { + lt += zone_->dst_offset(); + } + return lt; + } + return utc_time_type(this->time_); + } + //! Returns string in the form "2003-Aug-20 05:00:00 EDT" + /*! Returns string in the form "2003-Aug-20 05:00:00 EDT". If + * time_zone is NULL the time zone abbreviation will be "UTC". The time + * zone abbrev will not be included if calling object is a special_value*/ + std::string to_string() const + { + //TODO is this a temporary function ??? + std::ostringstream ss; + if(this->is_special()){ + ss << utc_time(); + return ss.str(); + } + if(zone_ == boost::shared_ptr()) { + ss << utc_time() << " UTC"; + return ss.str(); + } + bool is_dst_ = is_dst(); + utc_time_type lt = this->utc_time() + zone_->base_utc_offset(); + if (is_dst_) { + lt += zone_->dst_offset(); + } + ss << local_time() << " "; + if (is_dst()) { + ss << zone_->dst_zone_abbrev(); + } + else { + ss << zone_->std_zone_abbrev(); + } + return ss.str(); + } + /*! returns a local_date_time_base in the given time zone with the + * optional time_duration added. */ + local_date_time_base local_time_in(boost::shared_ptr new_tz, + time_duration_type td=time_duration_type(0,0,0)) const + { + return local_date_time_base(utc_time_type(this->time_) + td, new_tz); + } + + //! Returns name of associated time zone or "Coordinated Universal Time". + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00" extended iso format). Empty string is returned for + * classes that do not use a time_zone */ + std::string zone_name(bool as_offset=false) const + { + if(zone_ == boost::shared_ptr()) { + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("Coordinated Universal Time"); + } + } + if (is_dst()) { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->dst_zone_name(); + } + } + else { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->std_zone_name(); + } + } + } + //! Returns abbreviation of associated time zone or "UTC". + /*! Optional bool parameter will return time zone as an offset + * (ie "+0700" iso format). Empty string is returned for classes + * that do not use a time_zone */ + std::string zone_abbrev(bool as_offset=false) const + { + if(zone_ == boost::shared_ptr()) { + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("UTC"); + } + } + if (is_dst()) { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->dst_zone_abbrev(); + } + } + else { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->std_zone_abbrev(); + } + } + } + + //! returns a posix_time_zone string for the associated time_zone. If no time_zone, "UTC+00" is returned. + std::string zone_as_posix_string() const + { + if(zone_ == shared_ptr()) { + return std::string("UTC+00"); + } + return zone_->to_posix_string(); + } + + //! Equality comparison operator + /*bool operator==(const date_time::base_time& rhs) const + { // fails due to rhs.time_ being protected + return date_time::base_time::operator==(rhs); + //return this->time_ == rhs.time_; + }*/ + //! Equality comparison operator + bool operator==(const local_date_time_base& rhs) const + { + return time_system_type::is_equal(this->time_, rhs.time_); + } + //! Non-Equality comparison operator + bool operator!=(const local_date_time_base& rhs) const + { + return !(*this == rhs); + } + //! Less than comparison operator + bool operator<(const local_date_time_base& rhs) const + { + return time_system_type::is_less(this->time_, rhs.time_); + } + //! Less than or equal to comparison operator + bool operator<=(const local_date_time_base& rhs) const + { + return (*this < rhs || *this == rhs); + } + //! Greater than comparison operator + bool operator>(const local_date_time_base& rhs) const + { + return !(*this <= rhs); + } + //! Greater than or equal to comparison operator + bool operator>=(const local_date_time_base& rhs) const + { + return (*this > rhs || *this == rhs); + } + + //! Local_date_time + date_duration + local_date_time_base operator+(const date_duration_type& dd) const + { + return local_date_time_base(time_system_type::add_days(this->time_,dd), zone_); + } + //! Local_date_time += date_duration + local_date_time_base operator+=(const date_duration_type& dd) + { + this->time_ = time_system_type::add_days(this->time_,dd); + return *this; + } + //! Local_date_time - date_duration + local_date_time_base operator-(const date_duration_type& dd) const + { + return local_date_time_base(time_system_type::subtract_days(this->time_,dd), zone_); + } + //! Local_date_time -= date_duration + local_date_time_base operator-=(const date_duration_type& dd) + { + this->time_ = time_system_type::subtract_days(this->time_,dd); + return *this; + } + //! Local_date_time + time_duration + local_date_time_base operator+(const time_duration_type& td) const + { + return local_date_time_base(time_system_type::add_time_duration(this->time_,td), zone_); + } + //! Local_date_time += time_duration + local_date_time_base operator+=(const time_duration_type& td) + { + this->time_ = time_system_type::add_time_duration(this->time_,td); + return *this; + } + //! Local_date_time - time_duration + local_date_time_base operator-(const time_duration_type& td) const + { + return local_date_time_base(time_system_type::subtract_time_duration(this->time_,td), zone_); + } + //! Local_date_time -= time_duration + local_date_time_base operator-=(const time_duration_type& td) + { + this->time_ = time_system_type::subtract_time_duration(this->time_,td); + return *this; + } + //! local_date_time -= local_date_time --> time_duration_type + time_duration_type operator-(const local_date_time_base& rhs) const + { + return utc_time_type(this->time_) - utc_time_type(rhs.time_); + } + private: + boost::shared_ptr zone_; + //bool is_dst_; + + /*! Adjust the passed in time to UTC? + */ + utc_time_type construction_adjustment(utc_time_type t, + boost::shared_ptr z, + bool dst_flag) + { + if(z != boost::shared_ptr()) { + if(dst_flag && z->has_dst()) { + t -= z->dst_offset(); + } // else no adjust + t -= z->base_utc_offset(); + } + return t; + } + + /*! Simple formatting code -- todo remove this? + */ + std::string zone_as_offset(const time_duration_type& td, + const std::string& separator) const + { + std::ostringstream ss; + if(td.is_negative()) { + // a negative duration is represented as "-[h]h:mm" + // we require two digits for the hour. A positive duration + // with the %H flag will always give two digits + ss << "-"; + } + else { + ss << "+"; + } + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.hours()) + << separator + << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.minutes()); + return ss.str(); + } + }; + + //!Use the default parameters to define local_date_time + typedef local_date_time_base<> local_date_time; + +} } + + +#endif diff --git a/3rdParty/Boost/src/boost/date_time/local_time/local_time.hpp b/3rdParty/Boost/src/boost/date_time/local_time/local_time.hpp new file mode 100644 index 0000000..f7d4cc6 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/local_time.hpp @@ -0,0 +1,24 @@ +#ifndef LOCAL_TIME_LOCAL_TIME_HPP__ +#define LOCAL_TIME_LOCAL_TIME_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" +#include "boost/date_time/local_time/local_time_types.hpp" +#if !defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/local_time/local_time_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO +#include "boost/date_time/local_time/posix_time_zone.hpp" +#include "boost/date_time/local_time/custom_time_zone.hpp" +#include "boost/date_time/local_time/tz_database.hpp" +#include "boost/date_time/local_time/conversion.hpp" +#include "boost/date_time/time_zone_base.hpp" + + +#endif diff --git a/3rdParty/Boost/src/boost/date_time/local_time/local_time_io.hpp b/3rdParty/Boost/src/boost/date_time/local_time/local_time_io.hpp new file mode 100644 index 0000000..c161ff7 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/local_time_io.hpp @@ -0,0 +1,186 @@ +#ifndef BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ +#define BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-13 14:05:31 -0500 (Thu, 13 Nov 2008) $ + */ + +#include +#include +#include // i/ostreambuf_iterator +#include +#include +#include +#include +#include +#include // to_tm will be needed in the facets + +namespace boost { +namespace local_time { + + typedef boost::date_time::time_facet wlocal_time_facet; + typedef boost::date_time::time_facet local_time_facet; + + typedef boost::date_time::time_input_facet wlocal_time_input_facet; + typedef boost::date_time::time_input_facet local_time_input_facet; + + //! operator<< for local_date_time - see local_time docs for formatting details + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const local_date_time& ldt) + { + boost::io::ios_flags_saver iflags(os); + typedef local_date_time time_type;//::utc_time_type typename + typedef date_time::time_facet custom_time_facet; + typedef std::time_put std_time_facet; + std::ostreambuf_iterator oitr(os); + + if(std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(oitr, + os, + os.fill(), + ldt); + } + else { + custom_time_facet* f = new custom_time_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), ldt); + } + + return os; + } + + + //! input operator for local_date_time + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, local_date_time& ldt) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename local_date_time::utc_time_type utc_time_type; + typedef typename date_time::time_input_facet time_input_facet; + + // intermediate objects + std::basic_string tz_str; + utc_time_type pt(not_a_date_time); + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get_local_time(sit, str_end, is, pt, tz_str); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get_local_time(sit, str_end, is, pt, tz_str); + } + if(tz_str.empty()) { + time_zone_ptr null_ptr; + // a null time_zone_ptr creates a local_date_time that is UTC + ldt = local_date_time(pt, null_ptr); + } + else { + time_zone_ptr tz_ptr(new posix_time_zone(date_time::convert_string_type(tz_str))); + // the "date & time" constructor expects the time label to *not* be utc. + // a posix_tz_string also expects the time label to *not* be utc. + ldt = local_date_time(pt.date(), pt.time_of_day(), tz_ptr, local_date_time::EXCEPTION_ON_ERROR); + } + } + catch(...) { + // mask tells us what exceptions are turned on + std::ios_base::iostate exception_mask = is.exceptions(); + // if the user wants exceptions on failbit, we'll rethrow our + // date_time exception & set the failbit + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} // ignore this one + throw; // rethrow original exception + } + else { + // if the user want's to fail quietly, we simply set the failbit + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + //! output operator for local_time_period + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const boost::local_time::local_time_period& p) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet custom_facet; + typedef std::time_put std_time_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(oitr, os, os.fill(), p); + } + else { + //instantiate a custom facet for dealing with periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues as some later point. + custom_facet* f = new custom_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + //! input operator for local_time_period + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, boost::local_time::local_time_period& tp) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet time_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, tp); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, tp); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + +} } // namespaces + +#endif // BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ diff --git a/3rdParty/Boost/src/boost/date_time/local_time/local_time_types.hpp b/3rdParty/Boost/src/boost/date_time/local_time/local_time_types.hpp new file mode 100644 index 0000000..ed58b80 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/local_time_types.hpp @@ -0,0 +1,52 @@ +#ifndef LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ +#define LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/local_time/local_date_time.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/time_iterator.hpp" +#include "boost/date_time/compiler_config.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/local_time/date_duration_operators.hpp" +#endif //BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES +#include "boost/date_time/local_time/custom_time_zone.hpp" + +namespace boost { +namespace local_time { + + typedef boost::date_time::period local_time_period; + + typedef date_time::time_itr local_time_iterator; + + typedef date_time::second_clock local_sec_clock; + typedef date_time::microsec_clock local_microsec_clock; + + typedef date_time::time_zone_base time_zone; + typedef date_time::time_zone_base wtime_zone; + + //! Shared Pointer for custom_time_zone and posix_time_zone objects + typedef boost::shared_ptr time_zone_ptr; + typedef boost::shared_ptr wtime_zone_ptr; + + typedef date_time::time_zone_names_base time_zone_names; + typedef date_time::time_zone_names_base wtime_zone_names; + + //bring special enum values into the namespace + using date_time::special_values; + using date_time::not_special; + using date_time::neg_infin; + using date_time::pos_infin; + using date_time::not_a_date_time; + using date_time::max_date_time; + using date_time::min_date_time; + +}} // namespaces + +#endif // LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ diff --git a/3rdParty/Boost/src/boost/date_time/local_time/posix_time_zone.hpp b/3rdParty/Boost/src/boost/date_time/local_time/posix_time_zone.hpp new file mode 100644 index 0000000..2a0199f --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/posix_time_zone.hpp @@ -0,0 +1,474 @@ +#ifndef _DATE_TIME_POSIX_TIME_ZONE__ +#define _DATE_TIME_POSIX_TIME_ZONE__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2010-06-10 13:24:38 -0400 (Thu, 10 Jun 2010) $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +namespace local_time{ + + //! simple exception for UTC and Daylight savings start/end offsets + struct 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)) {} + }; + //! simple exception for UTC daylight savings adjustment + struct 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 dst_adjustment_offsets; + + //! A time zone class constructed from a POSIX time zone string + /*! A POSIX time zone string takes the form of:
+ * "std offset dst [offset],start[/time],end[/time]" (w/no spaces) + * 'std' specifies the abbrev of the time zone.
+ * 'offset' is the offset from UTC.
+ * 'dst' specifies the abbrev of the time zone during daylight savings time.
+ * The second offset is how many hours changed during DST. Default=1
+ * 'start' and'end' are the dates when DST goes into (and out of) effect.
+ * 'offset' takes the form of: [+|-]hh[:mm[:ss]] {h=0-23, m/s=0-59}
+ * 'time' and 'offset' take the same form. Time defaults=02:00:00
+ * 'start' and 'end' can be one of three forms:
+ * Mm.w.d {month=1-12, week=1-5 (5 is always last), day=0-6}
+ * Jn {n=1-365 Feb29 is never counted}
+ * n {n=0-365 Feb29 is counted in leap years}
+ * Example "PST-5PDT01:00:00,M4.1.0/02:00:00,M10.1.0/02:00:00" + *
+ * Exceptions will be thrown under these conditions:
+ * An invalid date spec (see date class)
+ * A boost::local_time::bad_offset exception will be thrown for:
+ * A DST start or end offset that is negative or more than 24 hours
+ * A UTC zone that is greater than +14 or less than -12 hours
+ * A boost::local_time::bad_adjustment exception will be thrown for:
+ * A DST adjustment that is 24 hours or more (positive or negative)
+ * + * Note that UTC zone offsets can be greater than +12: + * http://www.worldtimezone.com/utc/utc+1200.html + */ + template + class posix_time_zone_base : public date_time::time_zone_base { + public: + typedef boost::posix_time::time_duration time_duration_type; + typedef date_time::time_zone_names_base time_zone_names; + typedef date_time::time_zone_base 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_separator_type; + typedef boost::tokenizer tokenizer_type; + typedef typename tokenizer_type::iterator tokenizer_iterator_type; + + //! Construct from a POSIX time zone string + posix_time_zone_base(const string_type& s) : + //zone_names_("std_name","std_abbrev","no-dst","no-dst"), + 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 + // Work around bug in aC++ compiler: see QXCR1000880488 in the + // HP bug tracking system + 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() {}; + //!String for the zone when not in daylight savings (eg: EST) + virtual string_type std_zone_abbrev()const + { + return zone_names_.std_zone_abbrev(); + } + //!String for the timezone when in daylight savings (eg: EDT) + /*! For those time zones that have no DST, an empty string is used */ + virtual string_type dst_zone_abbrev() const + { + return zone_names_.dst_zone_abbrev(); + } + //!String for the zone when not in daylight savings (eg: Eastern Standard Time) + /*! The full STD name is not extracted from the posix time zone string. + * Therefore, the STD abbreviation is used in it's place */ + virtual string_type std_zone_name()const + { + return zone_names_.std_zone_name(); + } + //!String for the timezone when in daylight savings (eg: Eastern Daylight Time) + /*! The full DST name is not extracted from the posix time zone string. + * Therefore, the STD abbreviation is used in it's place. For time zones + * that have no DST, an empty string is used */ + virtual string_type dst_zone_name()const + { + return zone_names_.dst_zone_name(); + } + //! True if zone uses daylight savings adjustments otherwise false + virtual bool has_dst()const + { + return has_dst_; + } + //! Local time that DST starts -- NADT if has_dst is false + 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_); + } + //! Local time that DST ends -- NADT if has_dst is false + 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_); + } + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset()const + { + return base_utc_offset_; + } + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset()const + { + return dst_offsets_.dst_adjust_; + } + + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const + { + // std offset dst [offset],start[/time],end[/time] - w/o spaces + stringstream_type ss; + ss.fill('0'); + boost::shared_ptr no_rules; + // std + ss << std_zone_abbrev(); + // offset + if(base_utc_offset().is_negative()) { + // inverting the sign guarantees we get two digits + 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) { + // dst + ss << dst_zone_abbrev(); + // dst offset + if(dst_offset().is_negative()) { + // inverting the sign guarantees we get two digits + 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(); + } + } + // start/time + ss << ',' << date_time::convert_string_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(); + } + // end/time + ss << ',' << date_time::convert_string_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_rules_; + + /*! Extract time zone abbreviations for STD & DST as well + * as the offsets for the time shift that occurs and how + * much of a shift. At this time full time zone names are + * NOT extracted so the abbreviations are used in their place */ + 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; + + // get 'std' name/abbrev + while(std::isalpha(*sit)){ + ss << *sit++; + } + l_std_zone_abbrev = ss.str(); + ss.str(empty_string); + + // get UTC offset + if(sit != obj_end){ + // get duration + while(sit != obj_end && !std::isalpha(*sit)){ + ss << *sit++; + } + base_utc_offset_ = date_time::str_from_delimited_time_duration(ss.str()); + ss.str(empty_string); + + // base offset must be within range of -12 hours to +14 hours + 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_))); + } + } + + // get DST data if given + if(sit != obj_end){ + has_dst_ = true; + + // get 'dst' name/abbrev + while(sit != obj_end && std::isalpha(*sit)){ + ss << *sit++; + } + l_dst_zone_abbrev = ss.str(); + ss.str(empty_string); + + // get DST offset if given + if(sit != obj_end){ + // get duration + while(sit != obj_end && !std::isalpha(*sit)){ + ss << *sit++; + } + dst_offsets_.dst_adjust_ = date_time::str_from_delimited_time_duration(ss.str()); + ss.str(empty_string); + } + else{ // default DST offset + dst_offsets_.dst_adjust_ = posix_time::hours(1); + } + + // adjustment must be within +|- 1 day + 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_))); + } + } + // full names not extracted so abbrevs used in their place + 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 + // Work around bug in aC++ compiler: see QXCR1000880488 in the + // HP bug tracking system + 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(); + + // generate date spec + 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; + // generate durations + // starting offset + if(sit != st_tok.end()){ + dst_offsets_.dst_start_offset_ = date_time::str_from_delimited_time_duration(*sit); + } + else{ + // default + dst_offsets_.dst_start_offset_ = posix_time::hours(2); + } + // start/end offsets must fall on given date + 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_))); + } + + // ending offset + if(eit != et_tok.end()){ + dst_offsets_.dst_end_offset_ = date_time::str_from_delimited_time_duration(*eit); + } + else{ + // default + dst_offsets_.dst_end_offset_ = posix_time::hours(2); + } + // start/end offsets must fall on given date + 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_))); + } + } + + /* Parses out a start/end date spec from a posix time zone string. + * Date specs come in three possible formats, this function handles + * the 'M' spec. Ex "M2.2.4" => 2nd month, 2nd week, 4th day . + */ + 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; // start/end month,week,day +#ifdef __HP_aCC + // Work around bug in aC++ compiler: see QXCR1000880488 in the + // HP bug tracking system + 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(*it++); + sw = lexical_cast(*it++); + sd = lexical_cast(*it); + + it = etok.begin(); + em = lexical_cast(*it++); + ew = lexical_cast(*it++); + ed = lexical_cast(*it); + + dst_calc_rules_ = shared_ptr( + new nth_kday_dst_rule( + nth_last_dst_rule::start_rule( + static_cast(sw),sd,sm), + nth_last_dst_rule::start_rule( + static_cast(ew),ed,em) + ) + ); + } + + //! Julian day. Feb29 is never counted, even in leap years + // expects range of 1-365 + void julian_no_leap(const string_type& s, const string_type& e){ + typedef gregorian::gregorian_calendar calendar; + const unsigned short year = 2001; // Non-leap year + unsigned short sm=1; + int sd=0; + sd = lexical_cast(s.substr(1)); // skip 'J' + 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(e.substr(1)); // skip 'J' + while(ed > calendar::end_of_month_day(year,em)){ + ed -= calendar::end_of_month_day(year,em++); + } + + dst_calc_rules_ = shared_ptr( + new partial_date_dst_rule( + partial_date_dst_rule::start_rule( + sd, static_cast(sm)), + partial_date_dst_rule::end_rule( + ed, static_cast(em)) + ) + ); + } + + //! Julian day. Feb29 is always counted, but exception thrown in non-leap years + // expects range of 0-365 + void julian_day(const string_type& s, const string_type& e){ + int sd=0, ed=0; + sd = lexical_cast(s); + ed = lexical_cast(e); + dst_calc_rules_ = shared_ptr( + new partial_date_dst_rule( + partial_date_dst_rule::start_rule(++sd),// args are 0-365 + partial_date_dst_rule::end_rule(++ed) // pd expects 1-366 + ) + ); + } + + //! helper function used when throwing exceptions + 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 posix_time_zone; + +} } // namespace boost::local_time + + +#endif // _DATE_TIME_POSIX_TIME_ZONE__ diff --git a/3rdParty/Boost/src/boost/date_time/local_time/tz_database.hpp b/3rdParty/Boost/src/boost/date_time/local_time/tz_database.hpp new file mode 100644 index 0000000..4cfca45 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/local_time/tz_database.hpp @@ -0,0 +1,32 @@ +#ifndef BOOST_DATE_TIME_TZ_DATABASE_HPP__ +#define BOOST_DATE_TIME_TZ_DATABASE_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include "boost/date_time/local_time/custom_time_zone.hpp" +#include "boost/date_time/local_time/dst_transition_day_rules.hpp" +#include "boost/date_time/tz_db_base.hpp" + + +namespace boost { +namespace local_time { + + using date_time::data_not_accessible; + using date_time::bad_field_count; + + //! Object populated with boost::shared_ptr objects + /*! Object populated with boost::shared_ptr objects + * Database is populated from specs stored in external csv file. See + * date_time::tz_db_base for greater detail */ + typedef date_time::tz_db_base tz_database; + +}} // namespace + +#endif // BOOST_DATE_TIME_TZ_DATABASE_HPP__ + diff --git a/3rdParty/Boost/src/boost/date_time/time_zone_base.hpp b/3rdParty/Boost/src/boost/date_time/time_zone_base.hpp new file mode 100644 index 0000000..0d3cb90 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/time_zone_base.hpp @@ -0,0 +1,99 @@ +#ifndef _DATE_TIME_TIME_ZONE_BASE__ +#define _DATE_TIME_TIME_ZONE_BASE__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include +#include + +namespace boost { +namespace date_time { + + + + //! Interface class for dynamic time zones. + /*! This class represents the base interface for all timezone + * representations. Subclasses may provide different systems + * for identifying a particular zone. For example some may + * provide a geographical based zone construction while others + * may specify the offset from GMT. Another possible implementation + * would be to convert from POSIX timezone strings. Regardless of + * the construction technique, this is the interface that these + * time zone types must provide. + * + * Note that this class is intended to be used as a shared + * resource (hence the derivation from boost::counted_base. + */ + template + class time_zone_base { + public: + typedef CharT char_type; + typedef std::basic_string string_type; + typedef std::basic_ostringstream stringstream_type; + typedef typename time_type::date_type::year_type year_type; + typedef typename time_type::time_duration_type time_duration_type; + + time_zone_base() {}; + virtual ~time_zone_base() {}; + //!String for the timezone when in daylight savings (eg: EDT) + virtual string_type dst_zone_abbrev() const=0; + //!String for the zone when not in daylight savings (eg: EST) + virtual string_type std_zone_abbrev() const=0; + //!String for the timezone when in daylight savings (eg: Eastern Daylight Time) + virtual string_type dst_zone_name() const=0; + //!String for the zone when not in daylight savings (eg: Eastern Standard Time) + virtual string_type std_zone_name() const=0; + //! True if zone uses daylight savings adjustments otherwise false + virtual bool has_dst() const=0; + //! Local time that DST starts -- undefined if has_dst is false + virtual time_type dst_local_start_time(year_type y) const=0; + //! Local time that DST ends -- undefined if has_dst is false + virtual time_type dst_local_end_time(year_type y) const=0; + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset() const=0; + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset() const=0; + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const =0; + + private: + + }; + + + //! Structure which holds the time offsets associated with daylight savings time + /*! + *@param time_duration_type A type used to represent the offset + */ + template + class dst_adjustment_offsets + { + public: + dst_adjustment_offsets(const time_duration_type& dst_adjust, + const time_duration_type& dst_start_offset, + const time_duration_type& dst_end_offset) : + dst_adjust_(dst_adjust), + dst_start_offset_(dst_start_offset), + dst_end_offset_(dst_end_offset) + {} + + //! Amount DST adjusts the clock eg: plus one hour + time_duration_type dst_adjust_; + //! Time past midnight on start transition day that dst starts + time_duration_type dst_start_offset_; + //! Time past midnight on end transition day that dst ends + time_duration_type dst_end_offset_; + }; + + +} } //namespace date_time + + + +#endif diff --git a/3rdParty/Boost/src/boost/date_time/time_zone_names.hpp b/3rdParty/Boost/src/boost/date_time/time_zone_names.hpp new file mode 100644 index 0000000..05260c7 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/time_zone_names.hpp @@ -0,0 +1,98 @@ +#ifndef DATE_TIME_TIME_ZONE_NAMES_HPP__ +#define DATE_TIME_TIME_ZONE_NAMES_HPP__ + +/* Copyright (c) 2002-2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include + +namespace boost { +namespace date_time { + + template + struct default_zone_names { + public: + typedef CharT char_type; + static const char_type standard_name[9]; + static const char_type standard_abbrev[11]; + static const char_type non_dst_identifier[7]; + }; + template + const typename default_zone_names::char_type + default_zone_names::standard_name[9] = + {'s','t','d','_','n','a','m','e'}; + + template + const typename default_zone_names::char_type + default_zone_names::standard_abbrev[11] = + {'s','t','d','_','a','b','b','r','e','v'}; + + template + const typename default_zone_names::char_type + default_zone_names::non_dst_identifier[7] = + {'n','o','-','d','s','t'}; + + //! Base type that holds various string names for timezone output. + /*! Class that holds various types of strings used for timezones. + * For example, for the western United States there is the full + * name: Pacific Standard Time and the abbreviated name: PST. + * During daylight savings there are additional names: + * Pacific Daylight Time and PDT. + *@parm CharT Allows class to support different character types + */ + template + class time_zone_names_base + { + public: + typedef std::basic_string string_type; + time_zone_names_base() : + std_zone_name_(default_zone_names::standard_name), + std_zone_abbrev_(default_zone_names::standard_abbrev), + dst_zone_name_(default_zone_names::non_dst_identifier), + dst_zone_abbrev_(default_zone_names::non_dst_identifier) + {} + time_zone_names_base(const string_type& std_zone_name_str, + const string_type& std_zone_abbrev_str, + const string_type& dst_zone_name_str, + const string_type& dst_zone_abbrev_str) : + std_zone_name_(std_zone_name_str), + std_zone_abbrev_(std_zone_abbrev_str), + dst_zone_name_(dst_zone_name_str), + dst_zone_abbrev_(dst_zone_abbrev_str) + {} + string_type dst_zone_abbrev() const + { + return dst_zone_abbrev_; + } + string_type std_zone_abbrev() const + { + return std_zone_abbrev_; + } + string_type dst_zone_name() const + { + return dst_zone_name_; + } + string_type std_zone_name() const + { + return std_zone_name_; + } + private: + string_type std_zone_name_; + string_type std_zone_abbrev_; + string_type dst_zone_name_; + string_type dst_zone_abbrev_; + + }; + + //! Specialization of timezone names for standard char. + //typedef time_zone_names_base time_zone_names; + +} } //namespace + + +#endif diff --git a/3rdParty/Boost/src/boost/date_time/tz_db_base.hpp b/3rdParty/Boost/src/boost/date_time/tz_db_base.hpp new file mode 100644 index 0000000..2440115 --- /dev/null +++ b/3rdParty/Boost/src/boost/date_time/tz_db_base.hpp @@ -0,0 +1,378 @@ +#ifndef DATE_TIME_TZ_DB_BASE_HPP__ +#define DATE_TIME_TZ_DB_BASE_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-11-12 14:37:53 -0500 (Wed, 12 Nov 2008) $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace date_time { + + //! Exception thrown when tz database cannot locate requested data file + class data_not_accessible : public std::logic_error + { + public: + data_not_accessible() : + std::logic_error(std::string("Unable to locate or access the required datafile.")) + {} + data_not_accessible(const std::string& filespec) : + std::logic_error(std::string("Unable to locate or access the required datafile. Filespec: " + filespec)) + {} + }; + + //! Exception thrown when tz database locates incorrect field structure in data file + class bad_field_count : public std::out_of_range + { + public: + bad_field_count(const std::string& s) : + std::out_of_range(s) + {} + }; + + //! Creates a database of time_zones from csv datafile + /*! The csv file containing the zone_specs used by the + * tz_db_base is intended to be customized by the + * library user. When customizing this file (or creating your own) the + * file must follow a specific format. + * + * This first line is expected to contain column headings and is therefore + * not processed by the tz_db_base. + * + * Each record (line) must have eleven fields. Some of those fields can + * be empty. Every field (even empty ones) must be enclosed in + * double-quotes. + * Ex: + * @code + * "America/Phoenix" <- string enclosed in quotes + * "" <- empty field + * @endcode + * + * Some fields represent a length of time. The format of these fields + * must be: + * @code + * "{+|-}hh:mm[:ss]" <- length-of-time format + * @endcode + * Where the plus or minus is mandatory and the seconds are optional. + * + * Since some time zones do not use daylight savings it is not always + * necessary for every field in a zone_spec to contain a value. All + * zone_specs must have at least ID and GMT offset. Zones that use + * daylight savings must have all fields filled except: + * STD ABBR, STD NAME, DST NAME. You should take note + * that DST ABBR is mandatory for zones that use daylight savings + * (see field descriptions for further details). + * + * ******* Fields and their description/details ********* + * + * ID: + * Contains the identifying string for the zone_spec. Any string will + * do as long as it's unique. No two ID's can be the same. + * + * STD ABBR: + * STD NAME: + * DST ABBR: + * DST NAME: + * These four are all the names and abbreviations used by the time + * zone being described. While any string will do in these fields, + * care should be taken. These fields hold the strings that will be + * used in the output of many of the local_time classes. + * Ex: + * @code + * time_zone nyc = tz_db.time_zone_from_region("America/New_York"); + * local_time ny_time(date(2004, Aug, 30), IS_DST, nyc); + * cout << ny_time.to_long_string() << endl; + * // 2004-Aug-30 00:00:00 Eastern Daylight Time + * cout << ny_time.to_short_string() << endl; + * // 2004-Aug-30 00:00:00 EDT + * @endcode + * + * NOTE: The exact format/function names may vary - see local_time + * documentation for further details. + * + * GMT offset: + * This is the number of hours added to utc to get the local time + * before any daylight savings adjustments are made. Some examples + * are: America/New_York offset -5 hours, & Africa/Cairo offset +2 hours. + * The format must follow the length-of-time format described above. + * + * DST adjustment: + * The amount of time added to gmt_offset when daylight savings is in + * effect. The format must follow the length-of-time format described + * above. + * + * DST Start Date rule: + * This is a specially formatted string that describes the day of year + * in which the transition take place. It holds three fields of it's own, + * separated by semicolons. + * The first field indicates the "nth" weekday of the month. The possible + * values are: 1 (first), 2 (second), 3 (third), 4 (fourth), 5 (fifth), + * and -1 (last). + * The second field indicates the day-of-week from 0-6 (Sun=0). + * The third field indicates the month from 1-12 (Jan=1). + * + * Examples are: "-1;5;9"="Last Friday of September", + * "2;1;3"="Second Monday of March" + * + * Start time: + * Start time is the number of hours past midnight, on the day of the + * start transition, the transition takes place. More simply put, the + * time of day the transition is made (in 24 hours format). The format + * must follow the length-of-time format described above with the + * exception that it must always be positive. + * + * DST End date rule: + * See DST Start date rule. The difference here is this is the day + * daylight savings ends (transition to STD). + * + * End time: + * Same as Start time. + */ + template + class tz_db_base { + public: + /* Having CharT as a template parameter created problems + * with posix_time::duration_from_string. Templatizing + * duration_from_string was not possible at this time, however, + * it should be possible in the future (when poor compilers get + * fixed or stop being used). + * Since this class was designed to use CharT as a parameter it + * is simply typedef'd here to ease converting in back to a + * parameter the future */ + typedef char char_type; + + typedef typename time_zone_type::base_type time_zone_base_type; + typedef typename time_zone_type::time_duration_type time_duration_type; + typedef time_zone_names_base time_zone_names; + typedef boost::date_time::dst_adjustment_offsets dst_adjustment_offsets; + typedef std::basic_string string_type; + + //! Constructs an empty database + tz_db_base() {} + + //! Process csv data file, may throw exceptions + /*! May throw data_not_accessible, or bad_field_count exceptions */ + void load_from_file(const std::string& pathspec) + { + string_type in_str; + std::string buff; + + std::ifstream ifs(pathspec.c_str()); + if(!ifs){ + boost::throw_exception(data_not_accessible(pathspec)); + } + std::getline(ifs, buff); // first line is column headings + + while( std::getline(ifs, buff)) { + parse_string(buff); + } + } + + //! returns true if record successfully added to map + /*! Takes a region name in the form of "America/Phoenix", and a + * time_zone object for that region. The id string must be a unique + * name that does not already exist in the database. */ + bool add_record(const string_type& region, + boost::shared_ptr tz) + { + typename map_type::value_type p(region, tz); + return (m_zone_map.insert(p)).second; + } + + //! Returns a time_zone object built from the specs for the given region + /*! Returns a time_zone object built from the specs for the given + * region. If region does not exist a local_time::record_not_found + * exception will be thrown */ + boost::shared_ptr + time_zone_from_region(const string_type& region) const + { + // get the record + typename map_type::const_iterator record = m_zone_map.find(region); + if(record == m_zone_map.end()){ + return boost::shared_ptr(); //null pointer + } + return record->second; + } + + //! Returns a vector of strings holding the time zone regions in the database + std::vector region_list() const + { + typedef std::vector vector_type; + vector_type regions; + typename map_type::const_iterator itr = m_zone_map.begin(); + while(itr != m_zone_map.end()) { + regions.push_back(itr->first); + ++itr; + } + return regions; + } + + private: + typedef std::map > map_type; + map_type m_zone_map; + + // start and end rule are of the same type + typedef typename rule_type::start_rule::week_num week_num; + + /* TODO: mechanisms need to be put in place to handle different + * types of rule specs. parse_rules() only handles nth_kday + * rule types. */ + + //! parses rule specs for transition day rules + rule_type* parse_rules(const string_type& sr, const string_type& er) const + { + using namespace gregorian; + // start and end rule are of the same type, + // both are included here for readability + typedef typename rule_type::start_rule start_rule; + typedef typename rule_type::end_rule end_rule; + + // these are: [start|end] nth, day, month + int s_nth = 0, s_d = 0, s_m = 0; + int e_nth = 0, e_d = 0, e_m = 0; + split_rule_spec(s_nth, s_d, s_m, sr); + split_rule_spec(e_nth, e_d, e_m, er); + + typename start_rule::week_num s_wn, e_wn; + s_wn = get_week_num(s_nth); + e_wn = get_week_num(e_nth); + + + return new rule_type(start_rule(s_wn, s_d, s_m), + end_rule(e_wn, e_d, e_m)); + } + //! helper function for parse_rules() + week_num get_week_num(int nth) const + { + typedef typename rule_type::start_rule start_rule; + switch(nth){ + case 1: + return start_rule::first; + case 2: + return start_rule::second; + case 3: + return start_rule::third; + case 4: + return start_rule::fourth; + case 5: + case -1: + return start_rule::fifth; + default: + // shouldn't get here - add error handling later + break; + } + return start_rule::fifth; // silence warnings + } + + //! splits the [start|end]_date_rule string into 3 ints + void split_rule_spec(int& nth, int& d, int& m, string_type rule) const + { + typedef boost::char_separator > char_separator_type; + typedef boost::tokenizer::const_iterator, + std::basic_string > tokenizer; + typedef boost::tokenizer::const_iterator, + std::basic_string >::iterator tokenizer_iterator; + + const char_type sep_char[] = { ';', '\0'}; + char_separator_type sep(sep_char); + tokenizer tokens(rule, sep); // 3 fields + + tokenizer_iterator tok_iter = tokens.begin(); + nth = std::atoi(tok_iter->c_str()); ++tok_iter; + d = std::atoi(tok_iter->c_str()); ++tok_iter; + m = std::atoi(tok_iter->c_str()); + } + + + //! Take a line from the csv, turn it into a time_zone_type. + /*! Take a line from the csv, turn it into a time_zone_type, + * and add it to the map. Zone_specs in csv file are expected to + * have eleven fields that describe the time zone. Returns true if + * zone_spec successfully added to database */ + bool parse_string(string_type& s) + { + std::vector result; + typedef boost::token_iterator_generator, string_type::const_iterator, string_type >::type token_iter_type; + + token_iter_type i = boost::make_token_iterator(s.begin(), s.end(),boost::escaped_list_separator()); + + token_iter_type end; + while (i != end) { + result.push_back(*i); + i++; + } + + enum db_fields { ID, STDABBR, STDNAME, DSTABBR, DSTNAME, GMTOFFSET, + DSTADJUST, START_DATE_RULE, START_TIME, END_DATE_RULE, + END_TIME, FIELD_COUNT }; + + //take a shot at fixing gcc 4.x error + const unsigned int expected_fields = static_cast(FIELD_COUNT); + if (result.size() != expected_fields) { + std::ostringstream msg; + msg << "Expecting " << FIELD_COUNT << " fields, got " + << result.size() << " fields in line: " << s; + boost::throw_exception(bad_field_count(msg.str())); + BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return false); // should never reach + } + + // initializations + bool has_dst = true; + if(result[DSTABBR] == std::string()){ + has_dst = false; + } + + + // start building components of a time_zone + time_zone_names names(result[STDNAME], result[STDABBR], + result[DSTNAME], result[DSTABBR]); + + time_duration_type utc_offset = + str_from_delimited_time_duration(result[GMTOFFSET]); + + dst_adjustment_offsets adjust(time_duration_type(0,0,0), + time_duration_type(0,0,0), + time_duration_type(0,0,0)); + + boost::shared_ptr rules; + + if(has_dst){ + adjust = dst_adjustment_offsets( + str_from_delimited_time_duration(result[DSTADJUST]), + str_from_delimited_time_duration(result[START_TIME]), + str_from_delimited_time_duration(result[END_TIME]) + ); + + rules = + boost::shared_ptr(parse_rules(result[START_DATE_RULE], + result[END_DATE_RULE])); + } + string_type id(result[ID]); + boost::shared_ptr zone(new time_zone_type(names, utc_offset, adjust, rules)); + return (add_record(id, zone)); + + } + + }; + +} } // namespace + +#endif // DATE_TIME_TZ_DB_BASE_HPP__ -- cgit v0.10.2-6-g49f6