OmniSciDB  04ee39c94c
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

◆ DatetruncField

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

◆ DateTruncate()

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:

◆ DateTruncateAlterPrecisionScaleDown()

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

Definition at line 347 of file DateTruncate.cpp.

References DEVICE.

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:

◆ DateTruncateAlterPrecisionScaleUp()

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

Definition at line 332 of file DateTruncate.cpp.

References DEVICE.

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:

◆ DateTruncateHighPrecisionToDate()

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

Definition at line 316 of file DateTruncate.cpp.

References DEVICE, and 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: