Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #ifndef __MTIME_H__
14 : #define __MTIME_H__
15 :
16 : #include "monetdb_config.h"
17 : #include "gdk.h"
18 : #include "gdk_time.h"
19 : #include "mal_interpreter.h"
20 : #include "mal_exception.h"
21 :
22 : /* TODO change dayint again into an int instead of lng */
23 : static inline lng
24 83 : date_diff_imp(const date d1, const date d2)
25 : {
26 83 : int diff = date_diff(d1, d2);
27 83 : return is_int_nil(diff) ? lng_nil : (lng) diff *(lng) (24 * 60 * 60 * 1000);
28 : }
29 :
30 : static inline daytime
31 29 : time_sub_msec_interval(const daytime t, const lng ms)
32 : {
33 29 : if (is_lng_nil(ms))
34 0 : return daytime_nil;
35 29 : return daytime_add_usec_modulo(t, -ms * 1000);
36 : }
37 :
38 : static inline daytime
39 25 : time_add_msec_interval(const daytime t, const lng ms)
40 : {
41 25 : if (is_lng_nil(ms))
42 0 : return daytime_nil;
43 25 : return daytime_add_usec_modulo(t, ms * 1000);
44 : }
45 :
46 : static inline str
47 30 : date_sub_msec_interval(date *ret, date d, lng ms)
48 : {
49 30 : if (is_date_nil(d) || is_lng_nil(ms)) {
50 0 : *ret = date_nil;
51 0 : return MAL_SUCCEED;
52 : }
53 30 : if (is_date_nil((*ret = date_add_day(d, (int) (-ms / (24 * 60 * 60 * 1000))))))
54 0 : throw(MAL, "mtime.date_sub_msec_interval",
55 : SQLSTATE(22003) "overflow in calculation");
56 : return MAL_SUCCEED;
57 : }
58 :
59 : static inline str
60 2316 : date_add_msec_interval(date *ret, date d, lng ms)
61 : {
62 2316 : if (is_date_nil(d) || is_lng_nil(ms)) {
63 0 : *ret = date_nil;
64 0 : return MAL_SUCCEED;
65 : }
66 2316 : if (is_date_nil((*ret = date_add_day(d, (int) (ms / (24 * 60 * 60 * 1000))))))
67 0 : throw(MAL, "mtime.date_add_msec_interval",
68 : SQLSTATE(22003) "overflow in calculation");
69 : return MAL_SUCCEED;
70 : }
71 :
72 : static inline str
73 140 : timestamp_sub_msec_interval(timestamp *ret, timestamp ts, lng ms)
74 : {
75 140 : if (is_timestamp_nil(ts) || is_lng_nil(ms)) {
76 5 : *ret = timestamp_nil;
77 5 : return MAL_SUCCEED;
78 : }
79 135 : if (is_timestamp_nil((*ret = timestamp_add_usec(ts, -ms * 1000))))
80 0 : throw(MAL, "mtime.timestamp_sub_msec_interval",
81 : SQLSTATE(22003) "overflow in calculation");
82 : return MAL_SUCCEED;
83 : }
84 :
85 : static inline str
86 3 : timestamp_sub_month_interval(timestamp *ret, timestamp ts, int m)
87 : {
88 3 : if (is_timestamp_nil(ts) || is_int_nil(m)) {
89 0 : *ret = timestamp_nil;
90 0 : return MAL_SUCCEED;
91 : }
92 3 : if (is_timestamp_nil((*ret = timestamp_add_month(ts, -m))))
93 0 : throw(MAL, "mtime.timestamp_sub_month_interval",
94 : SQLSTATE(22003) "overflow in calculation");
95 : return MAL_SUCCEED;
96 : }
97 :
98 : static inline str
99 8 : timestamp_add_month_interval(timestamp *ret, timestamp ts, int m)
100 : {
101 8 : if (is_timestamp_nil(ts) || is_int_nil(m)) {
102 0 : *ret = timestamp_nil;
103 0 : return MAL_SUCCEED;
104 : }
105 8 : if (is_timestamp_nil((*ret = timestamp_add_month(ts, m))))
106 0 : throw(MAL, "mtime.timestamp_add_month_interval",
107 : SQLSTATE(22003) "overflow in calculation");
108 : return MAL_SUCCEED;
109 : }
110 :
111 : static inline str
112 462 : timestamp_add_msec_interval(timestamp *ret, timestamp ts, lng ms)
113 : {
114 462 : if (is_timestamp_nil(ts) || is_lng_nil(ms)) {
115 18 : *ret = timestamp_nil;
116 18 : return MAL_SUCCEED;
117 : }
118 444 : if (is_timestamp_nil((*ret = timestamp_add_usec(ts, ms * 1000))))
119 0 : throw(MAL, "mtime.timestamp_add_msec_interval",
120 : SQLSTATE(22003) "overflow in calculation");
121 : return MAL_SUCCEED;
122 : }
123 :
124 :
125 : static inline str
126 2 : odbc_timestamp_add_msec_interval_time(timestamp *ret, daytime t, lng ms)
127 : {
128 2 : date today = timestamp_date(timestamp_current());
129 2 : timestamp ts = timestamp_create(today, t);
130 2 : if (is_timestamp_nil((*ret = timestamp_add_usec(ts, ms * 1000))))
131 0 : throw(MAL, "mtime.odbc_timestamp_add_msec_interval_time",
132 : SQLSTATE(22003) "overflow in calculation");
133 : return MAL_SUCCEED;
134 : }
135 :
136 :
137 : static inline str
138 0 : odbc_timestamp_add_month_interval_time(timestamp *ret, daytime t, int m)
139 : {
140 0 : date today = timestamp_date(timestamp_current());
141 0 : timestamp ts = timestamp_create(today, t);
142 0 : if (is_timestamp_nil((*ret = timestamp_add_month(ts, m))))
143 0 : throw(MAL, "mtime.odbc_timestamp_add_month_interval_time",
144 : SQLSTATE(22003) "overflow in calculation");
145 : return MAL_SUCCEED;
146 : }
147 :
148 :
149 : static inline str
150 2 : odbc_timestamp_add_msec_interval_date(timestamp *ret, date d, lng ms)
151 : {
152 2 : timestamp ts = timestamp_fromdate(d);
153 2 : if (is_timestamp_nil((*ret = timestamp_add_usec(ts, ms * 1000))))
154 0 : throw(MAL, "mtime.odbc_timestamp_add_msec_interval_date",
155 : SQLSTATE(22003) "overflow in calculation");
156 : return MAL_SUCCEED;
157 : }
158 :
159 :
160 : static inline str
161 8 : date_submonths(date *ret, date d, int m)
162 : {
163 8 : if (is_date_nil(d) || is_int_nil(m)) {
164 0 : *ret = date_nil;
165 0 : return MAL_SUCCEED;
166 : }
167 8 : if (is_date_nil((*ret = date_add_month(d, -m))))
168 1 : throw(MAL, "mtime.date_submonths",
169 : SQLSTATE(22003) "overflow in calculation");
170 : return MAL_SUCCEED;
171 : }
172 :
173 : static inline str
174 35 : date_addmonths(date *ret, date d, int m)
175 : {
176 35 : if (is_date_nil(d) || is_int_nil(m)) {
177 0 : *ret = date_nil;
178 0 : return MAL_SUCCEED;
179 : }
180 35 : if (is_date_nil((*ret = date_add_month(d, m))))
181 0 : throw(MAL, "mtime.date_addmonths",
182 : SQLSTATE(22003) "overflow in calculation");
183 : return MAL_SUCCEED;
184 : }
185 :
186 : #define date_to_msec_since_epoch(t) is_date_nil(t) ? lng_nil : (timestamp_diff(timestamp_create(t, daytime_create(0, 0, 0, 0)), unixepoch) / 1000)
187 : #define daytime_to_msec_since_epoch(t) daytime_diff(t, daytime_create(0, 0, 0, 0))
188 :
189 : static inline lng
190 135 : TSDIFF(timestamp t1, timestamp t2)
191 : {
192 135 : lng diff = timestamp_diff(t1, t2);
193 135 : if (!is_lng_nil(diff)) {
194 : #ifndef TRUNCATE_NUMBERS
195 131 : if (diff < 0)
196 23 : diff = -((-diff + 500) / 1000);
197 : else
198 108 : diff = (diff + 500) / 1000;
199 : #else
200 : diff /= 1000;
201 : #endif
202 : }
203 135 : return diff;
204 : }
205 :
206 : static inline int
207 19 : timestamp_century(const timestamp t)
208 : {
209 19 : if (is_timestamp_nil(t))
210 2 : return int_nil;
211 17 : int y = date_year(timestamp_date(t));
212 17 : if (y > 0)
213 17 : return (y - 1) / 100 + 1;
214 : else
215 0 : return -((-y - 1) / 100 + 1);
216 : }
217 :
218 : #define timestamp_decade(t) is_timestamp_nil(t) ? int_nil : date_year(timestamp_date(t)) / 10
219 : #define timestamp_year(t) date_year(timestamp_date(t))
220 : #define timestamp_quarter(t) is_timestamp_nil(t) ? bte_nil : (date_month(timestamp_date(t)) - 1) / 3 + 1
221 : #define timestamp_month(t) date_month(timestamp_date(t))
222 : #define timestamp_day(t) date_day(timestamp_date(t))
223 : #define timestamp_hours(t) daytime_hour(timestamp_daytime(t))
224 : #define timestamp_minutes(t) daytime_min(timestamp_daytime(t))
225 : #define timestamp_extract_usecond(ts) daytime_sec_usec(timestamp_daytime(ts))
226 : #define timestamp_to_msec_since_epoch(t) is_timestamp_nil(t) ? lng_nil : (timestamp_diff(t, unixepoch) / 1000)
227 :
228 : #define sql_year(m) is_int_nil(m) ? int_nil : m / 12
229 : #define sql_month(m) is_int_nil(m) ? int_nil : m % 12
230 : #define sql_day(m) is_lng_nil(m) ? lng_nil : m / (24*60*60*1000)
231 : #define sql_hours(m) is_lng_nil(m) ? int_nil : (int) ((m % (24*60*60*1000)) / (60*60*1000))
232 : #define sql_minutes(m) is_lng_nil(m) ? int_nil : (int) ((m % (60*60*1000)) / (60*1000))
233 : #define sql_seconds(m) is_lng_nil(m) ? int_nil : (int) ((m % (60*1000)) / 1000)
234 : #define msec_since_epoch(ts) ts
235 :
236 : #endif /* __MTIME_H__ */
|