📄 posix_time_zone.hpp
字号:
/*! Extract time zone abbreviations for STD & DST as well
* as the offsets for the time the shift 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 std::string& obj){
std::stringstream ss("");
std::string::const_iterator sit = obj.begin();
std::string std_zone_abbrev("std_abbrev"), dst_zone_abbrev("");
// get 'std' name/abbrev
while(std::isalpha(*sit)){
ss << *sit++;
}
std_zone_abbrev = ss.str();
ss.str("");
// get UTC offset
if(sit != obj.end()){
// get duration
while(sit != obj.end() && !std::isalpha(*sit)){
ss << *sit++;
}
base_utc_offset_ = posix_time::duration_from_string(ss.str());
ss.str("");
// base offset must be within range of -12 hours to +12 hours
if(base_utc_offset_ < time_duration_type(-12,0,0) ||
base_utc_offset_ > time_duration_type(12,0,0))
{
throw 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++;
}
dst_zone_abbrev = ss.str();
ss.str("");
// get DST offset if given
if(sit != obj.end()){
// get duration
while(sit != obj.end() && !std::isalpha(*sit)){
ss << *sit++;
}
dst_offsets_.dst_adjust_ =
posix_time::duration_from_string(ss.str());
ss.str("");
}
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))
{
throw 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(std_zone_abbrev, std_zone_abbrev, dst_zone_abbrev, dst_zone_abbrev);
}
void calc_rules(const std::string& start, const std::string& end){
boost::char_separator<char> sep("/");
tokenizer st_tok(start, sep);
tokenizer et_tok(end, sep);
tokenizer::iterator sit = st_tok.begin();
tokenizer::iterator eit = et_tok.begin();
// generate date spec
char x = std::string(*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_ = posix_time::duration_from_string(*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))
{
throw bad_offset(posix_time::to_simple_string(dst_offsets_.dst_start_offset_));
}
// ending offset
if(eit != et_tok.end()){
dst_offsets_.dst_end_offset_ = posix_time::duration_from_string(*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))
{
throw 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 std::string& s, const std::string& 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
char_separator<char> sep("M.");
tokenizer stok(s, sep), etok(e, sep);
tokenizer::iterator 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)
)
);
}
//! Julian day. Feb29 is never counted, even in leap years
// expects range of 1-365
void julian_no_leap(const std::string& s, const std::string& e){
typedef gregorian::gregorian_calendar calendar;
const unsigned short year = 2001; // Non-leap year
unsigned short sm=1;
int sd=0;
sd = lexical_cast<int>(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<int>(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<dst_calc_rule>(
new partial_date_dst_rule(
partial_date_dst_rule::start_rule(
sd, static_cast<date_time::months_of_year>(sm)),
partial_date_dst_rule::end_rule(
ed, static_cast<date_time::months_of_year>(em))
)
);
}
//! Julian day. Feb29 is always counted, but exception thrown in non-leap years
// expects range of 0-365
void julian_day(const std::string& s, const std::string& 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),// 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;
}
};
} } // namespace boost::local_time
#endif // _DATE_TIME_POSIX_TIME_ZONE__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -