RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* date.h -*- C++ -*- 00002 Jeremy Barnes, 18 July 2010 00003 Copyright (c) 2010 Datacratic. All rights reserved. 00004 00005 Basic class that holds and manipulates a date. Not designed for ultimate 00006 accuracy, but shouldn't be too bad. 00007 */ 00008 00009 #pragma once 00010 00011 #include <string> 00012 #include <iostream> 00013 #include <boost/date_time/gregorian/gregorian.hpp> 00014 #include <boost/date_time/posix_time/posix_time.hpp> 00015 #include "jml/db/persistent_fwd.h" 00016 #include <chrono> 00017 00018 00019 struct ACE_Time_Value; 00020 00021 namespace Json { 00022 00023 struct Value; 00024 00025 } // namespace Json 00026 00027 namespace ML { 00028 struct Parse_Context; 00029 } // namespace ML 00030 00031 namespace Datacratic { 00032 00033 using boost::posix_time::ptime; 00034 struct Opaque; 00035 00036 namespace JS { 00037 struct JSValue; 00038 } // namespace JS 00039 00040 /*****************************************************************************/ 00041 /* DATE */ 00042 /*****************************************************************************/ 00043 00044 struct Date { 00045 00046 Date() 00047 : secondsSinceEpoch_(0.0) 00048 { 00049 } 00050 00051 explicit Date(const ptime & date); 00052 explicit Date(const Opaque & value); 00053 Date(int year, int month, int day, 00054 int hour = 0, int minute = 0, int second = 0, 00055 double fraction = 0.0); 00056 explicit Date(JS::JSValue & value); 00057 explicit Date(const Json::Value & value); 00058 explicit Date(const ACE_Time_Value & time); 00059 00060 static Date fromSecondsSinceEpoch(double numSeconds) 00061 { 00062 Date result; 00063 result.secondsSinceEpoch_ = numSeconds; 00064 return result; 00065 } 00066 00067 static Date parseSecondsSinceEpoch(const std::string & date); 00068 00069 static Date parseDefaultUtc(const std::string & date); 00070 static Date parseIso8601(const std::string & date); 00071 00072 static Date notADate(); 00073 static Date positiveInfinity(); 00074 static Date negativeInfinity(); 00075 static Date now(); 00076 static Date nowOld(); 00077 00078 bool isADate() const; 00079 00080 double secondsSinceEpoch() const 00081 { 00082 return secondsSinceEpoch_; 00083 } 00084 00085 std::string print(unsigned seconds_digits = 0) const; 00086 std::string print(const std::string & format) const; 00087 std::string printRfc2616() const; 00088 std::string printClassic() const; 00089 00090 bool operator == (const Date & other) const 00091 { 00092 return secondsSinceEpoch_ == other.secondsSinceEpoch_; 00093 } 00094 00095 bool operator != (const Date & other) const 00096 { 00097 return ! operator == (other); 00098 } 00099 00100 bool operator < (const Date & other) const 00101 { 00102 return secondsSinceEpoch_ < other.secondsSinceEpoch_; 00103 } 00104 00105 bool operator <= (const Date & other) const 00106 { 00107 return secondsSinceEpoch_ <= other.secondsSinceEpoch_; 00108 } 00109 00110 bool operator > (const Date & other) const 00111 { 00112 return secondsSinceEpoch_ > other.secondsSinceEpoch_; 00113 } 00114 00115 bool operator >= (const Date & other) const 00116 { 00117 return secondsSinceEpoch_ >= other.secondsSinceEpoch_; 00118 } 00119 00120 double operator - (const Date & other) const 00121 { 00122 return secondsSinceEpoch_ - other.secondsSinceEpoch_; 00123 } 00124 00125 Date & setMin(Date other) 00126 { 00127 secondsSinceEpoch_ = std::min(secondsSinceEpoch_, 00128 other.secondsSinceEpoch_); 00129 return *this; 00130 } 00131 00132 Date & setMax(Date other) 00133 { 00134 secondsSinceEpoch_ = std::max(secondsSinceEpoch_, 00135 other.secondsSinceEpoch_); 00136 return *this; 00137 } 00138 00142 Date quantized(double fraction) const; 00143 Date & quantize(double fraction); 00144 00145 void addSeconds(double interval) 00146 { 00147 secondsSinceEpoch_ += interval; 00148 } 00149 00150 void addMinutes(double interval) 00151 { 00152 secondsSinceEpoch_ += interval * 60.0; 00153 } 00154 00155 void addHours(double interval) 00156 { 00157 secondsSinceEpoch_ += interval * 3600.0; 00158 } 00159 00160 void addDays(double interval) 00161 { 00162 secondsSinceEpoch_ += interval * 3600.0 * 24.0; 00163 } 00164 00165 Date plusSeconds(double interval) const 00166 { 00167 Date result = *this; 00168 result.addSeconds(interval); 00169 return result; 00170 } 00171 00172 Date plusMinutes(double interval) const 00173 { 00174 Date result = *this; 00175 result.addSeconds(interval * 60.0); 00176 return result; 00177 } 00178 00179 Date plusHours(double interval) const 00180 { 00181 Date result = *this; 00182 result.addSeconds(interval * 3600.0); 00183 return result; 00184 } 00185 00186 Date plusDays(double interval) const 00187 { 00188 Date result = *this; 00189 result.addSeconds(interval * 3600.0 * 24.0); 00190 return result; 00191 } 00192 00193 double secondsUntil(const Date & other) const 00194 { 00195 return other.secondsSinceEpoch_ - secondsSinceEpoch_; 00196 } 00197 00198 double minutesUntil(const Date & other) const 00199 { 00200 static const double factor = 1.0 / 60.0; 00201 return secondsUntil(other) * factor; 00202 } 00203 00204 double hoursUntil(const Date & other) const 00205 { 00206 static const double factor = 1.0 / 3600.0; 00207 return secondsUntil(other) * factor; 00208 } 00209 00210 double daysUntil(const Date & other) const 00211 { 00212 static const double factor = 1.0 / 24.0 / 3600.0; 00213 return secondsUntil(other) * factor; 00214 } 00215 00216 double secondsSince(const Date & other) const 00217 { 00218 return -secondsUntil(other); 00219 } 00220 00221 double minutesSince(const Date & other) const 00222 { 00223 return -minutesUntil(other); 00224 } 00225 00226 double hoursSince(const Date & other) const 00227 { 00228 return -hoursUntil(other); 00229 } 00230 00231 double daysSince(const Date & other) const 00232 { 00233 return -daysUntil(other); 00234 } 00235 00236 bool sameDay(const Date & other) const 00237 { 00238 return dayStart() == other.dayStart(); 00239 } 00240 00241 Date dayStart() const 00242 { 00243 static const double secPerDay = 24.0 * 3600.0; 00244 double day = secondsSinceEpoch_ / secPerDay; 00245 double startOfDay = floor(day); 00246 return fromSecondsSinceEpoch(startOfDay * secPerDay); 00247 } 00248 00249 int hour() const; 00250 int minute() const; 00251 int second() const; 00252 int weekday() const; 00253 int dayOfMonth() const; 00254 int monthOfYear() const; 00255 int year() const; 00256 00257 int hourOfWeek() const; 00258 00259 double fractionalSeconds() const 00260 { 00261 double whole_seconds; 00262 return modf(secondsSinceEpoch_, &whole_seconds); 00263 } 00264 00265 long long wholeSecondsSinceEpoch() const 00266 { 00267 double whole_seconds; 00268 modf(secondsSinceEpoch_, &whole_seconds); 00269 return whole_seconds; 00270 } 00271 00272 std::string printMonth() const; 00273 std::string printWeekday() const; 00274 std::string printYearAndMonth() const; 00275 00276 static const boost::posix_time::ptime epoch; 00277 00278 static Date expect_date(ML::Parse_Context & context, 00279 const std::string & format); 00280 static bool match_date(ML::Parse_Context & context, Date & date, 00281 const std::string & format); 00282 00283 static double expect_time(ML::Parse_Context & context, 00284 const std::string & format); 00285 static bool match_time(ML::Parse_Context & context, 00286 double & time, 00287 const std::string & format); 00288 00289 static Date expect_date_time(ML::Parse_Context & context, 00290 const std::string & date_format, 00291 const std::string & time_format); 00292 00293 static bool match_date_time(ML::Parse_Context & context, 00294 Date & result, 00295 const std::string & date_format, 00296 const std::string & time_format); 00297 00298 static Date parse_date_time(const std::string & date_time, 00299 const std::string & date_format, 00300 const std::string & time_format); 00301 00302 size_t hash() const 00303 { 00304 return std::hash<double>() (secondsSinceEpoch_); 00305 } 00306 00308 ACE_Time_Value toAce() const; 00309 00311 boost::posix_time::ptime toBoost() const 00312 { 00313 return boost::posix_time::from_time_t(toTimeT()) 00314 + boost::posix_time::microseconds 00315 (1000000 * fractionalSeconds()); 00316 } 00317 00321 std::chrono::time_point<std::chrono::system_clock> 00322 toStd() const 00323 { 00324 return std::chrono::system_clock::from_time_t(toTimeT()) 00325 + std::chrono::microseconds(static_cast<long>(1000000 * fractionalSeconds())); 00326 } 00327 00331 time_t toTimeT() const 00332 { 00333 return secondsSinceEpoch(); 00334 } 00335 00337 static Date fromTimeT(const time_t & time) 00338 { 00339 return Date::fromSecondsSinceEpoch(time); 00340 } 00341 00343 tm toTm() const; 00344 00346 static Date fromTm(const tm & t); 00347 00349 void addFromString(std::string); 00350 00351 private: 00352 double secondsSinceEpoch_; 00353 Date(double); 00354 }; 00355 00356 std::ostream & operator << (std::ostream & stream, const Date & date); 00357 std::istream & operator >> (std::istream & stream, Date & date); 00358 00359 ML::DB::Store_Writer & operator << (ML::DB::Store_Writer & store, Date date); 00360 ML::DB::Store_Reader & operator >> (ML::DB::Store_Reader & store, Date & date); 00361 00362 namespace JS { 00363 00364 void to_js(JSValue & jsval, Date value); 00365 Date from_js(const JSValue & val, Date *); 00366 00367 } // namespace JS 00368 00369 } // namespace Datacratic 00370 00371 namespace std { 00372 00373 template<> 00374 struct hash<Datacratic::Date> { 00375 size_t operator () (const Datacratic::Date & date) const 00376 { 00377 return date.hash(); 00378 } 00379 }; 00380 00381 } // namespace std