OmniSciDB  085a039ca4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
misc.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // Credits: Howard Hinnant for open source date calculations.
18 
19 #include "misc.h"
20 
21 #include <cstdio>
22 
23 #include "sqltypes.h"
24 
25 namespace shared {
26 
27 size_t formatDate(char* buf, size_t const max, int64_t const unixtime) {
28  DivUMod const div_day = divUMod(unixtime, 24 * 60 * 60);
29  DivUMod const div_era = divUMod(div_day.quot - 11017, 146097);
30  unsigned const doe = static_cast<unsigned>(div_era.rem);
31  unsigned const yoe = (doe - doe / 1460 + doe / 36524 - (doe == 146096)) / 365;
32  unsigned const doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
33  unsigned const moy = (5 * doy + 2) / 153;
34  static_assert(8 <= sizeof(long long)); // long long needed for snprintf()
35  long long const y = 2000 + div_era.quot * 400 + yoe + (9 < moy);
36  unsigned const m = moy + (9 < moy ? -9 : 3);
37  unsigned const d = doy - (153 * moy + 2) / 5 + 1;
38  int const len = snprintf(buf, max, "%04lld-%02u-%02u", y, m, d);
39  if (0 <= len && static_cast<size_t>(len) < max) {
40  return static_cast<size_t>(len);
41  }
42  return 0;
43 }
44 
45 size_t formatDateTime(char* buf,
46  size_t const max,
47  int64_t const timestamp,
48  int const dimension,
49  bool use_iso_format) {
50  constexpr int pow10[10]{
51  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
52  DivUMod const div_hip = divUMod(timestamp, pow10[dimension]);
53  DivUMod const div_day = divUMod(div_hip.quot, 24 * 60 * 60);
54  DivUMod const div_era = divUMod(div_day.quot - 11017, 146097);
55  unsigned const doe = static_cast<unsigned>(div_era.rem);
56  unsigned const yoe = (doe - doe / 1460 + doe / 36524 - (doe == 146096)) / 365;
57  unsigned const doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
58  unsigned const moy = (5 * doy + 2) / 153;
59  static_assert(8 <= sizeof(long long)); // long long needed for snprintf()
60  long long const y = 2000 + div_era.quot * 400 + yoe + (9 < moy);
61  unsigned const m = moy + (9 < moy ? -9 : 3);
62  unsigned const d = doy - (153 * moy + 2) / 5 + 1;
63  unsigned const minutes = static_cast<unsigned>(div_day.rem) / 60;
64  unsigned const ss = div_day.rem % 60;
65  unsigned const hh = minutes / 60;
66  unsigned const mm = minutes % 60;
67  const char* date_time_format;
68  if (use_iso_format) {
69  if (dimension) {
70  date_time_format = "%04lld-%02u-%02uT%02u:%02u:%02u";
71  } else {
72  date_time_format = "%04lld-%02u-%02uT%02u:%02u:%02uZ";
73  }
74  } else {
75  date_time_format = "%04lld-%02u-%02u %02u:%02u:%02u";
76  }
77  int const len = snprintf(buf, max, date_time_format, y, m, d, hh, mm, ss);
78  if (0 <= len && static_cast<size_t>(len) < max) {
79  if (dimension) {
80  auto precision_format = use_iso_format ? ".%0*dZ" : ".%0*d";
81  int const len_frac = snprintf(buf + len,
82  max - len,
83  precision_format,
84  dimension,
85  static_cast<int>(div_hip.rem));
86  if (0 <= len_frac && static_cast<size_t>(len + len_frac) < max) {
87  return static_cast<size_t>(len + len_frac);
88  }
89  } else {
90  return static_cast<size_t>(len);
91  }
92  }
93  return 0;
94 }
95 
96 size_t formatHMS(char* buf, size_t const max, int64_t const unixtime) {
97  unsigned const seconds = static_cast<unsigned>(unsignedMod(unixtime, 24 * 60 * 60));
98  unsigned const minutes = seconds / 60;
99  unsigned const ss = seconds % 60;
100  unsigned const hh = minutes / 60;
101  unsigned const mm = minutes % 60;
102  int const len = snprintf(buf, max, "%02u:%02u:%02u", hh, mm, ss);
103  if (0 <= len && static_cast<size_t>(len) < max) {
104  return static_cast<size_t>(len);
105  }
106  return 0;
107 }
108 
109 std::string convert_temporal_to_iso_format(const SQLTypeInfo& type_info,
110  int64_t unix_time) {
111  std::string iso_str;
112  if (type_info.get_type() == kTIME) {
113  // Set a buffer size that can contain HH:MM:SS
114  iso_str.resize(8);
115  const auto len = shared::formatHMS(iso_str.data(), iso_str.length() + 1, unix_time);
116  CHECK_EQ(len, iso_str.length());
117  } else if (type_info.get_type() == kDATE) {
118  // Set a buffer size that can contain YYYYYYYYYYYY-mm-dd (int64_t can represent up to
119  // 12 digit years)
120  iso_str.resize(18);
121  const size_t len =
122  shared::formatDate(iso_str.data(), iso_str.length() + 1, unix_time);
123  CHECK_GT(len, static_cast<size_t>(0));
124  iso_str.resize(len);
125  } else if (type_info.get_type() == kTIMESTAMP) {
126  auto precision = type_info.get_precision();
127  // Set a buffer size that can contain the specified timestamp precision
128  // YYYYYYYYYYYY-mm-dd(18) T(1) HH:MM:SS(8) .(precision?) nnnnnnnnn(precision) Z(1)
129  // (int64_t can represent up to 12 digit years with seconds precision)
130  iso_str.resize(18 + 1 + 8 + bool(precision) + precision + 1);
131  const size_t len = shared::formatDateTime(
132  iso_str.data(), iso_str.length() + 1, unix_time, precision, true);
133  CHECK_GT(len, static_cast<size_t>(0));
134  iso_str.resize(len);
135  } else {
136  UNREACHABLE() << "Unexpected column type: " << type_info.toString();
137  }
138  return iso_str;
139 }
140 
141 } // namespace shared
#define CHECK_EQ(x, y)
Definition: Logger.h:231
int64_t quot
Definition: misc.h:172
Definition: sqltypes.h:49
std::string convert_temporal_to_iso_format(const SQLTypeInfo &type_info, int64_t unix_time)
Definition: misc.cpp:109
#define UNREACHABLE()
Definition: Logger.h:267
Constants for Builtin SQL Types supported by OmniSci.
HOST DEVICE SQLTypes get_type() const
Definition: sqltypes.h:329
#define CHECK_GT(x, y)
Definition: Logger.h:235
size_t formatHMS(char *buf, size_t const max, int64_t const unixtime)
Definition: misc.cpp:96
std::string toString() const
Definition: sqltypes.h:482
int get_precision() const
Definition: sqltypes.h:332
size_t formatDate(char *buf, size_t const max, int64_t const unixtime)
Definition: misc.cpp:27
Definition: sqltypes.h:53
uint64_t unsignedMod(int64_t num, int64_t den)
Definition: misc.h:187
size_t formatDateTime(char *buf, size_t const max, int64_t const timestamp, int const dimension, bool use_iso_format)
Definition: misc.cpp:45
int64_t rem
Definition: misc.h:173
DivUMod divUMod(int64_t num, int64_t den)
Definition: misc.h:177