OmniSciDB  a47db9e897
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DateTruncate.h File Reference
#include <cstdint>
#include "../Shared/funcannotations.h"
#include "ExtractFromTime.h"
+ Include dependency graph for DateTruncate.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  DatetruncField {
  dtYEAR, dtQUARTER, dtMONTH, dtDAY,
  dtHOUR, dtMINUTE, dtSECOND, dtMILLENNIUM,
  dtCENTURY, dtDECADE, dtMILLISECOND, dtMICROSECOND,
  dtNANOSECOND, dtWEEK, dtQUARTERDAY, dtINVALID
}
 

Functions

NEVER_INLINE DEVICE int64_t DateTruncate (DatetruncField field, const int64_t timeval)
 
DEVICE int64_t DateTruncateHighPrecisionToDate (const int64_t timeval, const int64_t scale)
 
DEVICE int64_t DateTruncateAlterPrecisionScaleUp (const int64_t timeval, const int64_t scale)
 
DEVICE int64_t DateTruncateAlterPrecisionScaleDown (const int64_t timeval, const int64_t scale)
 

Enumeration Type Documentation

Enumerator
dtYEAR 
dtQUARTER 
dtMONTH 
dtDAY 
dtHOUR 
dtMINUTE 
dtSECOND 
dtMILLENNIUM 
dtCENTURY 
dtDECADE 
dtMILLISECOND 
dtMICROSECOND 
dtNANOSECOND 
dtWEEK 
dtQUARTERDAY 
dtINVALID 

Definition at line 42 of file DateTruncate.h.

Function Documentation

NEVER_INLINE DEVICE int64_t DateTruncate ( DatetruncField  field,
const int64_t  timeval 
)

Definition at line 70 of file DateTruncate.cpp.

References create_epoch(), dtCENTURY, dtDAY, dtDECADE, dtHOUR, dtMICROSECOND, dtMILLENNIUM, dtMILLISECOND, dtMINUTE, dtMONTH, dtNANOSECOND, dtQUARTER, dtQUARTERDAY, dtSECOND, dtWEEK, dtYEAR, extract_dow(), gmtime_r_newlib(), kEpochOffsetYear1900, kMonsPerYear, kSecondsPer4YearCycle, kSecondsPerNonLeapYear, kSecPerHour, kSecsJanToMar1900, kSecsPerDay, kSecsPerMin, kSecsPerQuarterDay, kUSecsPerDay, kYearBase, and STATIC_QUAL.

Referenced by DateDiff(), DateTruncateNullable(), Analyzer::Constant::do_cast(), anonymous_namespace{ExpressionRange.cpp}::getDateTimePrecisionCastRange(), and DateTimeTranslator::getDateTruncConstantValue().

71  {
72  STATIC_QUAL const int32_t month_lengths[2][kMonsPerYear] = {
73  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
74  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
75 
76  STATIC_QUAL const uint32_t cumulative_month_epoch_starts[kMonsPerYear] = {0,
77  2678400,
78  5270400,
79  7948800,
80  10540800,
81  13219200,
82  15897600,
83  18489600,
84  21168000,
85  23760000,
86  26438400,
87  29116800};
88  STATIC_QUAL const uint32_t cumulative_quarter_epoch_starts[4] = {
89  0, 7776000, 15638400, 23587200};
90  STATIC_QUAL const uint32_t cumulative_quarter_epoch_starts_leap_year[4] = {
91  0, 7862400, 15724800, 23673600};
92  switch (field) {
93  case dtNANOSECOND:
94  case dtMICROSECOND:
95  case dtMILLISECOND:
96  case dtSECOND:
97  return timeval;
98  case dtMINUTE: {
99  int64_t ret = (timeval / kSecsPerMin) * kSecsPerMin;
100  // in the case of a negative time we still want to push down so need to push
101  // one
102  // more
103  if (ret < 0) {
104  {
105  ret -= kSecsPerMin;
106  }
107  }
108  return ret;
109  }
110  case dtHOUR: {
111  int64_t ret = (timeval / kSecPerHour) * kSecPerHour;
112  // in the case of a negative time we still want to push down so need to push
113  // one
114  // more
115  if (ret < 0) {
116  {
117  ret -= kSecPerHour;
118  }
119  }
120  return ret;
121  }
122  case dtQUARTERDAY: {
123  int64_t ret = (timeval / kSecsPerQuarterDay) * kSecsPerQuarterDay;
124  // in the case of a negative time we still want to push down so need to push
125  // one
126  // more
127  if (ret < 0) {
128  {
129  ret -= kSecsPerQuarterDay;
130  }
131  }
132  return ret;
133  }
134  case dtDAY: {
135  int64_t ret = (timeval / kSecsPerDay) * kSecsPerDay;
136  // in the case of a negative time we still want to push down so need to push
137  // one
138  // more
139  if (ret < 0) {
140  {
141  ret -= kSecsPerDay;
142  }
143  }
144  return ret;
145  }
146  case dtWEEK: {
147  int64_t day = (timeval / kSecsPerDay) * kSecsPerDay;
148  if (day < 0) {
149  {
150  day -= kSecsPerDay;
151  }
152  }
153  int32_t dow = extract_dow(day);
154  return day - (dow * kSecsPerDay);
155  }
156  case dtMONTH: {
157  if (timeval >= 0L && timeval <= UINT32_MAX - (kEpochOffsetYear1900)) {
158  uint32_t seconds_march_1900 = timeval + kEpochOffsetYear1900 - kSecsJanToMar1900;
159  uint32_t seconds_past_4year_period = seconds_march_1900 % kSecondsPer4YearCycle;
160  uint32_t four_year_period_seconds =
161  (seconds_march_1900 / kSecondsPer4YearCycle) * kSecondsPer4YearCycle;
162  uint32_t year_seconds_past_4year_period =
163  (seconds_past_4year_period / kSecondsPerNonLeapYear) * kSecondsPerNonLeapYear;
164  if (seconds_past_4year_period >=
165  kSecondsPer4YearCycle - kUSecsPerDay) { // if we are in Feb 29th
166  year_seconds_past_4year_period -= kSecondsPerNonLeapYear;
167  }
168  uint32_t seconds_past_march =
169  seconds_past_4year_period - year_seconds_past_4year_period;
170  uint32_t month = seconds_past_march /
171  (30 * kUSecsPerDay); // Will make the correct month either be
172  // the guessed month or month before
173  month = month <= 11 ? month : 11;
174  if (cumulative_month_epoch_starts[month] > seconds_past_march) {
175  month--;
176  }
177  return (static_cast<int64_t>(four_year_period_seconds) +
178  year_seconds_past_4year_period + cumulative_month_epoch_starts[month] -
180  }
181  break;
182  }
183  case dtQUARTER: {
184  if (timeval >= 0L && timeval <= UINT32_MAX - kEpochOffsetYear1900) {
185  uint32_t seconds_1900 = timeval + kEpochOffsetYear1900;
186  uint32_t leap_years = (seconds_1900 - kSecsJanToMar1900) / kSecondsPer4YearCycle;
187  uint32_t year =
188  (seconds_1900 - leap_years * kUSecsPerDay) / kSecondsPerNonLeapYear;
189  uint32_t base_year_leap_years = (year - 1) / 4;
190  uint32_t base_year_seconds =
191  year * kSecondsPerNonLeapYear + base_year_leap_years * kUSecsPerDay;
192  bool is_leap_year = year % 4 == 0 && year != 0;
193  const uint32_t* quarter_offsets = is_leap_year
194  ? cumulative_quarter_epoch_starts_leap_year
195  : cumulative_quarter_epoch_starts;
196  uint32_t partial_year_seconds = seconds_1900 % base_year_seconds;
197  uint32_t quarter = partial_year_seconds / (90 * kUSecsPerDay);
198  quarter = quarter <= 3 ? quarter : 3;
199  if (quarter_offsets[quarter] > partial_year_seconds) {
200  quarter--;
201  }
202  return (static_cast<int64_t>(base_year_seconds) + quarter_offsets[quarter] -
204  }
205  break;
206  }
207  case dtYEAR: {
208  if (timeval >= 0L && timeval <= UINT32_MAX - kEpochOffsetYear1900) {
209  uint32_t seconds_1900 = static_cast<uint32_t>(timeval) + kEpochOffsetYear1900;
210  uint32_t leap_years = (seconds_1900 - kSecsJanToMar1900) / kSecondsPer4YearCycle;
211  uint32_t year =
212  (seconds_1900 - leap_years * kUSecsPerDay) / kSecondsPerNonLeapYear;
213  uint32_t base_year_leap_years = (year - 1) / 4;
214  return (static_cast<int64_t>(year) * kSecondsPerNonLeapYear +
215  base_year_leap_years * kUSecsPerDay - kEpochOffsetYear1900);
216  }
217  break;
218  }
219  default:
220  break;
221  }
222 
223  // use ExtractFromTime functions where available
224  // have to do some extra work for these ones
225  tm tm_struct;
226  gmtime_r_newlib(timeval, tm_struct);
227  switch (field) {
228  case dtMONTH: {
229  // clear the time
230  int64_t day = (timeval / kSecsPerDay) * kSecsPerDay;
231  if (day < 0) {
232  {
233  day -= kSecsPerDay;
234  }
235  }
236  // calculate the day of month offset
237  int32_t dom = tm_struct.tm_mday;
238  return (day - (static_cast<int64_t>(dom - 1) * kSecsPerDay));
239  }
240  case dtQUARTER: {
241  // clear the time
242  int64_t day = (timeval / kSecsPerDay) * kSecsPerDay;
243  if (day < 0) {
244  {
245  day -= kSecsPerDay;
246  }
247  }
248  // calculate the day of month offset
249  int32_t dom = tm_struct.tm_mday;
250  // go to the start of the current month
251  day = day - ((dom - 1) * kSecsPerDay);
252  // find what month we are
253  int32_t mon = tm_struct.tm_mon;
254  // find start of quarter
255  int32_t start_of_quarter = tm_struct.tm_mon / 3 * 3;
256  int32_t year = tm_struct.tm_year + kYearBase;
257  // are we in a leap year
258  int32_t leap_year = 0;
259  // only matters if month is March so save some mod operations
260  if (mon == 2) {
261  if (((year % 400) == 0) || ((year % 4) == 0 && ((year % 100) != 0))) {
262  leap_year = 1;
263  }
264  }
265  // now walk back until at correct quarter start
266  for (; mon > start_of_quarter; mon--) {
267  day = day - (month_lengths[0 + leap_year][mon - 1] * kSecsPerDay);
268  }
269  return day;
270  }
271  case dtYEAR: {
272  // clear the time
273  int64_t day = (timeval / kSecsPerDay) * kSecsPerDay;
274  if (day < 0) {
275  {
276  day -= kSecsPerDay;
277  }
278  }
279  // calculate the day of year offset
280  int32_t doy = tm_struct.tm_yday;
281  return day - ((doy)*kSecsPerDay);
282  }
283  case dtDECADE: {
284  int32_t year = tm_struct.tm_year + kYearBase;
285  int32_t decade_start = ((year - 1) / 10) * 10 + 1;
286  return create_epoch(decade_start);
287  }
288  case dtCENTURY: {
289  int32_t year = tm_struct.tm_year + kYearBase;
290  int32_t century_start = ((year - 1) / 100) * 100 + 1;
291  return create_epoch(century_start);
292  }
293  case dtMILLENNIUM: {
294  int32_t year = tm_struct.tm_year + kYearBase;
295  int32_t millennium_start = ((year - 1) / 1000) * 1000 + 1;
296  return create_epoch(millennium_start);
297  }
298  default:
299 #ifdef __CUDACC__
300  return -1;
301 #else
302  abort();
303 #endif
304  }
305 }
static constexpr int64_t kSecsPerDay
static constexpr uint32_t kSecsJanToMar1900
static constexpr uint32_t kUSecsPerDay
static constexpr int64_t kSecsPerMin
static constexpr int64_t kSecsPerQuarterDay
#define STATIC_QUAL
static constexpr uint32_t kEpochOffsetYear1900
static constexpr int32_t kYearBase
const rapidjson::Value & field(const rapidjson::Value &obj, const char field[]) noexcept
Definition: JsonAccessors.h:31
DEVICE int32_t extract_dow(const int64_t lcltime)
DEVICE tm gmtime_r_newlib(const int64_t lcltime, tm &res)
static constexpr uint32_t kSecondsPer4YearCycle
static constexpr int64_t kSecPerHour
static constexpr uint32_t kSecondsPerNonLeapYear
NEVER_INLINE DEVICE int64_t create_epoch(int32_t year)
static constexpr int32_t kMonsPerYear

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

DEVICE int64_t DateTruncateAlterPrecisionScaleDown ( const int64_t  timeval,
const int64_t  scale 
)

Definition at line 347 of file DateTruncate.cpp.

Referenced by DateTruncateAlterPrecisionScaleDownNullable(), Analyzer::Constant::do_cast(), and anonymous_namespace{ExpressionRange.cpp}::getDateTimePrecisionCastRange().

348  {
349  return timeval / scale;
350 }

+ Here is the caller graph for this function:

DEVICE int64_t DateTruncateAlterPrecisionScaleUp ( const int64_t  timeval,
const int64_t  scale 
)

Definition at line 332 of file DateTruncate.cpp.

Referenced by DateTruncateAlterPrecisionScaleUpNullable(), Analyzer::Constant::do_cast(), and anonymous_namespace{ExpressionRange.cpp}::getDateTimePrecisionCastRange().

333  {
334  return timeval * scale;
335 }

+ Here is the caller graph for this function:

DEVICE int64_t DateTruncateHighPrecisionToDate ( const int64_t  timeval,
const int64_t  scale 
)

Definition at line 316 of file DateTruncate.cpp.

References kSecsPerDay.

Referenced by DateTruncateHighPrecisionToDateNullable(), and Analyzer::Constant::do_cast().

317  {
318  const int64_t retval = (timeval / (scale * kSecsPerDay)) * kSecsPerDay;
319  return retval < 0 ? retval - kSecsPerDay : retval;
320 }
static constexpr int64_t kSecsPerDay

+ Here is the caller graph for this function: