RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 00007 #include "periodic_utils.h" 00008 #include "jml/utils/parse_context.h" 00009 #include <boost/tuple/tuple.hpp> 00010 00011 using namespace std; 00012 00013 00014 namespace Datacratic { 00015 00016 std::pair<TimeGranularity, int> 00017 parsePeriod(const std::string & pattern) 00018 { 00019 TimeGranularity granularity; 00020 int number; 00021 00022 ML::Parse_Context context(pattern, 00023 pattern.c_str(), 00024 pattern.c_str() + pattern.length()); 00025 00026 number = context.expect_int(); 00027 00028 if (number <= 0) 00029 context.exception("invalid time number: must be > 0"); 00030 00031 if (context.match_literal('x')) 00032 granularity = MILLISECONDS; 00033 else if (context.match_literal('s')) 00034 granularity = SECONDS; 00035 else if (context.match_literal('m')) 00036 granularity = MINUTES; 00037 else if (context.match_literal('h')) 00038 granularity = HOURS; 00039 else if (context.match_literal('d')) 00040 granularity = DAYS; 00041 else if (context.match_literal('w')) 00042 granularity = WEEKS; 00043 else if (context.match_literal('M')) 00044 granularity = MONTHS; 00045 else if (context.match_literal('y')) 00046 granularity = YEARS; 00047 else context.exception("excepted h, m, s, d, w, M, y or x"); 00048 00049 context.expect_eof(); 00050 00051 return make_pair(granularity, number); 00052 } 00053 00054 std::pair<Date, double> 00055 findPeriod(Date current, const std::string & period) 00056 { 00057 TimeGranularity p; 00058 int n; 00059 boost::tie(p, n) = parsePeriod(period); 00060 return findPeriod(current, p, n); 00061 } 00062 00063 std::pair<Date, double> 00064 findPeriod(Date current, TimeGranularity granularity, int number) 00065 { 00066 // Find where the current period starts 00067 00068 tm t = current.toTm(); 00069 00070 // Remove fractional seconds 00071 Date result = current; 00072 int64_t seconds = result.secondsSinceEpoch(); 00073 result = Date::fromSecondsSinceEpoch(seconds); 00074 00075 //Date unadjusted = result; 00076 00077 double interval; 00078 00079 switch (granularity) { 00080 case DAYS: 00081 if (number != 1) 00082 throw ML::Exception("only 1d is supported for days"); 00083 // Go to the start of the day 00084 result.addSeconds(-(3600 * t.tm_hour + 60 * t.tm_min + t.tm_sec)); 00085 00086 // Go to day 00087 interval = 3600 * 24 * number; 00088 00089 break; 00090 case HOURS: 00091 // Go to the start of the hour 00092 result.addSeconds(-(60 * t.tm_min + t.tm_sec)); 00093 00094 // Go to hour number n of the day 00095 result.addSeconds(-3600 * (t.tm_hour % number)); 00096 00097 interval = 3600 * number; 00098 00099 break; 00100 00101 case MINUTES: 00102 // Go to the start of the minute 00103 result.addSeconds(-t.tm_sec); 00104 00105 // Go to the next multiple of minutes 00106 result.addSeconds(-60 * (t.tm_min % number)); 00107 00108 interval = 60 * number; 00109 00110 break; 00111 00112 case SECONDS: 00113 //cerr << "seconds: t.tm_sec = " << t.tm_sec 00114 // << " number = " << number << " before = " 00115 // << result; 00116 result.addSeconds(-(t.tm_sec % number)); 00117 //cerr <<" after = " << result << " current = " 00118 // << current << endl; 00119 00120 interval = number; 00121 break; 00122 00123 case MILLISECONDS: 00124 interval = number / 1000.0; 00125 00126 result = current.quantized(interval); 00127 if (result > current) 00128 result.addSeconds(-interval); 00129 00130 break; 00131 00132 default: 00133 throw ML::Exception("that granualrity is not supported"); 00134 } 00135 00136 return make_pair(result, interval); 00137 } 00138 00139 std::string 00140 filenameFor(const Date & date, const std::string & pattern) 00141 { 00142 return date.print(pattern); 00143 } 00144 00145 } // namespace Datacratic