RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* localdate.cc 00002 Wolfgang Sourdeau, 10 December 2012 00003 Copyright (c) 2012 Datacratic. All rights reserved. 00004 00005 */ 00006 00007 00008 #include <time.h> 00009 #include <mutex> 00010 #include <boost/date_time/local_time/tz_database.hpp> 00011 #include <boost/date_time/local_time/local_time.hpp> 00012 #include <jml/arch/exception.h> 00013 00014 #include "date.h" 00015 00016 #include "localdate.h" 00017 00018 using namespace boost::local_time; 00019 using namespace boost::posix_time; 00020 using namespace std; 00021 // using namespace ML; 00022 00023 namespace 00024 { 00025 static tz_database tz_db; 00026 std::once_flag once ; 00027 } 00028 00029 namespace Datacratic { 00030 00031 /*****************************************************************************/ 00032 /* DATE */ 00033 /*****************************************************************************/ 00034 00035 LocalDate:: 00036 LocalDate(double secondsSinceEpoch, const std::string & tzName) 00037 : secondsSinceEpoch_(secondsSinceEpoch), tzName_(tzName), tzOffset_(0) 00038 { 00039 recomputeTZOffset(); 00040 } 00041 00042 double 00043 LocalDate:: 00044 secondsSinceEpoch() const 00045 { 00046 return secondsSinceEpoch_; 00047 } 00048 00049 const string 00050 LocalDate:: 00051 timezone() const 00052 { 00053 return tzName_; 00054 } 00055 00056 int 00057 LocalDate:: 00058 tzOffset() const 00059 { 00060 return tzOffset_; 00061 } 00062 00063 void 00064 LocalDate:: 00065 fillTM(struct tm & time) const 00066 { 00067 time_t t = secondsSinceEpoch_ + tzOffset_; 00068 00069 if (!gmtime_r(&t, &time)) 00070 throw ML::Exception("problem with gmtime_r"); 00071 } 00072 00073 int 00074 LocalDate:: 00075 hour() const 00076 { 00077 tm time; 00078 00079 fillTM(time); 00080 00081 return time.tm_hour; 00082 } 00083 00084 int 00085 LocalDate:: 00086 dayOfMonth() const 00087 { 00088 tm time; 00089 00090 fillTM(time); 00091 00092 return time.tm_mday; 00093 } 00094 00095 int 00096 LocalDate:: 00097 dayOfWeek() const 00098 { 00099 tm time; 00100 00101 fillTM(time); 00102 00103 return time.tm_wday; 00104 } 00105 00106 int 00107 LocalDate:: 00108 year() const 00109 { 00110 tm time; 00111 00112 fillTM(time); 00113 00114 return time.tm_year + 1900; 00115 } 00116 00117 void 00118 LocalDate:: 00119 recomputeTZOffset() 00120 { 00121 if (tzName_ == "UTC") { 00122 tzOffset_ = 0; 00123 // dstOffset_= 0; 00124 } 00125 else { 00126 call_once(once, [&] { 00127 string zoneSpecFile = BOOST_TIMEZONES_DIR "/date_timezone_spec.csv"; 00128 tz_db.load_from_file(zoneSpecFile); 00129 }); 00130 00131 time_zone_ptr tz = tz_db.time_zone_from_region(tzName_); 00132 if (tz == 0) { 00133 throw ML::Exception("time zone named '" + tzName_ + "' is not known"); 00134 } 00135 time_duration offset = tz->base_utc_offset(); 00136 tzOffset_ = offset.total_seconds(); 00137 00138 if (tz->has_dst()) { 00139 int yearOfLocalDate = year(); 00140 int dst_start((tz->dst_local_start_time(yearOfLocalDate) - Date::epoch) 00141 .total_seconds()); 00142 int dst_end((tz->dst_local_end_time(yearOfLocalDate) - Date::epoch) 00143 .total_seconds()); 00144 00145 // the southern areas of the world have their DST during northern 00146 // winter 00147 if (dst_start < dst_end) { 00148 if (secondsSinceEpoch_ >= dst_start 00149 && dst_end > secondsSinceEpoch_) 00150 tzOffset_ += tz->dst_offset().total_seconds(); 00151 } 00152 else { 00153 if (secondsSinceEpoch_ >= dst_end 00154 && dst_start > secondsSinceEpoch_) 00155 tzOffset_ += tz->dst_offset().total_seconds(); 00156 } 00157 } 00158 } 00159 00160 // cerr << "timezone: " << tzName_ 00161 // << "; seconds: " << secondsSinceEpoch_ 00162 // << "; offset: " << tzOffset_ 00163 // << "; dst offset: " << dstOffset_ 00164 // << endl; 00165 } 00166 00167 } // namespace Datacratic