OmniSciDB  72180abbfe
 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)
 

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 71 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().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 318 of file DateTruncate.cpp.

References kSecsPerDay.

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

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

+ Here is the caller graph for this function: