RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/types/localdate.cc
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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator