MySQL 9.5.0
Source Code Documentation
my_temporal.h
Go to the documentation of this file.
1#ifndef MY_TEMPORAL_H
2#define MY_TEMPORAL_H
3
4/* Copyright (c) 2025, Oracle and/or its affiliates.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is designed to work with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have either included with
16 the program or referenced in the documentation.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License, version 2.0, for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
26
27/**
28 @ingroup MY_TEMPORAL
29 @{
30
31 @file include/my_temporal.h
32
33 Server classes for temporal handling (DATE, TIME, DATETIME)
34*/
35
36#include <stdint.h> // for uint32_t, uint64_t, int64_t, int32_t, uint8_t
37#include <stdlib.h> // for abs, size_t
38#include <cassert> // for assert
39#include <string> // for string
40
41#include "my_time.h" // for SECS_PER_MIN, SECS_PER_HOUR, Interval (ptr o...
42#include "mysql_time.h" // for MYSQL_TIME, enum_mysql_timestamp_type
43
44/**
45 Time_val is a temporal type that represents only time.
46 It has constructors for creating time values from time components
47 (hour, minute, second and microseconds), and from seconds and microseconds.
48 It also has a constructor to create a value from a MYSQL_TIME value.
49
50 The range of values supported is from -838:59:59 to +838:59:59.
51 The negative values, and the values from 24:00:00 and up are dedicated
52 for use as a small-range interval type and should not be taken as a time
53 within a day.
54*/
55class Time_val {
56 public:
58
59 Time_val(bool negative, uint32_t hour, uint32_t minute, uint32_t second,
60 uint32_t microsecond) {
61 assert(hour <= TIME_MAX_HOUR && minute <= TIME_MAX_MINUTE &&
63 m_value = (static_cast<uint64_t>(hour) << TIME_SHIFT_HOUR) |
64 (static_cast<uint64_t>(minute) << TIME_SHIFT_MINUTE) |
65 (static_cast<uint64_t>(second) << TIME_SHIFT_SECOND) |
67 if (negative) {
68 assert(hour != 0 || minute != 0 || second != 0 || microsecond != 0);
69 // Stored as one's complement, negate value and subtract one
70 m_value = (static_cast<uint64_t>(-static_cast<int64_t>(m_value)) &
72 1;
73 } else {
75 }
76 assert(is_valid());
77 }
78
79 Time_val(bool negative, uint32_t second, uint32_t microsecond)
80 : Time_val(negative, second / SECS_PER_HOUR,
82 microsecond) {}
83
84 explicit Time_val(const MYSQL_TIME &mtime)
85 : Time_val(mtime.neg, mtime.hour, mtime.minute, mtime.second,
86 mtime.second_part) {
87 assert(mtime.time_type == MYSQL_TIMESTAMP_TIME);
88 }
89
90 bool is_negative() const { return (m_value & BITS_SIGN) == 0; }
91 uint32_t hour() const {
92 return is_negative() ? 2047U - ((m_value & BITS_HOUR) >> TIME_SHIFT_HOUR)
94 }
95 uint32_t minute() const {
96 return is_negative() ? 63U - ((m_value & BITS_MINUTE) >> TIME_SHIFT_MINUTE)
98 }
99 uint32_t second() const {
100 return is_negative() ? 63U - ((m_value & BITS_SECOND) >> TIME_SHIFT_SECOND)
102 }
103 uint32_t microsecond() const {
106 }
107
108 /**
109 @returns whether the value is less than, equal to or greater than
110 the argument value.
111 */
112 int compare(const Time_val arg) const {
113 return m_value < arg.m_value ? -1 : m_value > arg.m_value ? 1 : 0;
114 }
115 /// @returns an integer value for comparison purposes
116 int64_t for_comparison() const { return m_value; }
117
118 /// Check against extreme values
119 bool is_extreme_value(bool positive) const {
120 return m_value == (positive ? MAX_TIME_VALUE : MIN_TIME_VALUE);
121 }
122
123 /// Set zero time
125
126 /// Set extreme value
127 void set_extreme_value(bool negative) {
129 }
130
131 bool operator==(const Time_val rhs) const { return m_value == rhs.m_value; }
132
133 bool operator<(const Time_val rhs) const { return m_value < rhs.m_value; }
134 /**
135 Add a time value to another time value, or subtract it
136
137 @param tv Time value to add or subtract
138 @param subtract If true, subtract the time value, otherwise add it.
139
140 @returns false if result is within valid time range, true otherwise.
141 */
142 bool add(Time_val tv, bool subtract);
143
144 /**
145 Add an interval to a time value, or subtract it
146
147 @param iv Interval to add or subtract
148 @param subtract If true, subtract the time value, otherwise add it.
149
150 @returns false if result is within valid time range, true otherwise.
151 */
152 bool add(Interval &iv, bool subtract);
153
154 /// Static functions for creation
155 /**
156 Creates Time_val with range check. Minute, second and microsecond
157 values must be within limits.
158
159 @returns false if valid range, true if outside valid range.
160 */
161 static bool make_time(bool negative, uint32_t hour, uint32_t minute,
162 uint32_t second, uint32_t microsecond, Time_val *time) {
163 if (hour > TIME_MAX_HOUR || (hour == TIME_MAX_HOUR && microsecond != 0)) {
164 return true;
165 }
168 *time = Time_val(negative, hour, minute, second, microsecond);
169 return false;
170 }
171 /// Creates a Time_val from a date_time by extracting only the time fields
172 static Time_val strip_date(const MYSQL_TIME &mt);
173
174 /// Convert time value to the generalized temporal time format.
175 explicit operator MYSQL_TIME() const;
176
177 /// @returns time value as number of seconds. Fraction seconds are ignored.
178 int32_t to_seconds() const {
179 return static_cast<int32_t>(unsigned_seconds(hour(), minute(), second())) *
180 (is_negative() ? -1 : 1);
181 }
182 /// @returns time value as number of microseconds.
183 int64_t to_microseconds() const {
184 return static_cast<int64_t>(
186 (is_negative() ? -1 : 1);
187 }
188 /**
189 base100 representation without microsecond, but rounded
190 '-12:34:56.999999' is returned as -123457
191 */
192 int64_t to_int_rounded() const;
193 /**
194 base100 representation without microsecond, '-12:34:56.999999' is
195 returned as -123456
196 */
197 int64_t to_int_truncated() const;
198 /**
199 base100 representation with microseconds, returned as double precision float
200 */
201 double to_double() const;
202
203 /// @returns true if value is adjusted to number of decimals in fraction
204 bool is_adjusted(uint32_t decimals) const;
205
206 /// @returns actual number of decimals in fraction
207 uint32_t actual_decimals() const;
208
209 // Mutators
210 void adjust_fraction(uint32_t decimals, bool round);
211
212 // Add nanoseconds to a time value, with rounding
213 bool add_nanoseconds_round(const int64_t nanoseconds) {
214 return nanoseconds < 0 ? add_microseconds((nanoseconds - 500) / 1000)
215 : add_microseconds((nanoseconds + 500) / 1000);
216 }
217
218 /**
219 Convert server time value to storage engine interface format
220
221 @param [out] ptr The buffer to put value at.
222 @param dec Precision.
223 */
224 void store_time(uint8_t *ptr, uint32_t dec) const;
225
226 /**
227 Convert from storage engine interface time format to server time value.
228
229 @param ptr The pointer to read the value at.
230 @param dec Precision.
231 @param[out] time Returned time value
232 */
233 static void load_time(const uint8_t *ptr, uint32_t dec, Time_val *time);
234
235 size_t to_string(char *buffer, uint32_t dec) const;
236
237 std::string to_string() const;
238
239 private:
240 explicit Time_val(int64_t val) : m_value(val) {}
241
242 /// Set microsecond part of time value
243 void set_microsecond(uint32_t fraction) {
244 m_value = (m_value & ~BITS_MICROSEC) |
245 (is_negative() ? (0xFFFFFFU - fraction) : fraction);
246 }
247
248 bool add_seconds(int32_t seconds) {
249 Time_val tv(seconds < 0, 0, 0, static_cast<uint8_t>(abs(seconds)), 0);
250 add(tv, false);
251 assert(is_valid());
252 return false;
253 }
254
255 bool add_microseconds(int64_t mu) {
256 int64_t signed_micro =
258 if (is_negative()) signed_micro = -signed_micro;
259 signed_micro += mu;
260 bool negative = signed_micro < 0;
261 uint64_t micro = negative ? -signed_micro : signed_micro;
262 if (micro > MAX_TIME_MICROSEC) {
263 return true;
264 }
265 uint32_t seconds = static_cast<uint32_t>(micro / TIME_MULT_SECOND);
266 micro %= TIME_MULT_SECOND;
267 *this = Time_val(negative, seconds, micro);
268 assert(is_valid());
269 return false;
270 }
271
272 bool is_valid() const {
273 return hour() <= TIME_MAX_HOUR && minute() <= TIME_MAX_MINUTE &&
275 m_value <= MAX_TIME_VALUE && m_value >= MIN_TIME_VALUE &&
276 m_value != 0x7fffffffffff;
277 }
278
279 static uint32_t unsigned_seconds(uint32_t hour, uint32_t minute,
280 uint32_t second) {
281 return (hour * SECS_PER_HOUR) + (minute * SECS_PER_MIN) + second;
282 }
283
284 static uint64_t unsigned_microsec(uint32_t hour, uint32_t minute,
285 uint32_t second, uint32_t microsec) {
286 return (hour * TIME_MULT_HOUR) + (minute * TIME_MULT_MINUTE) +
287 (second * TIME_MULT_SECOND) + microsec;
288 }
289
290 static constexpr const uint32_t TIME_MAX_HOUR = 838;
291 static constexpr const uint32_t TIME_MAX_MINUTE = 59;
292 static constexpr const uint32_t TIME_MAX_SECOND = 59;
293 static constexpr const uint32_t TIME_MAX_MICROSEC = 999999;
294
295 static constexpr uint64_t TIME_MULT_SECOND = 1000000;
296 static constexpr uint64_t TIME_MULT_MINUTE = 60000000;
297 static constexpr uint64_t TIME_MULT_HOUR = 3600000000;
298
299 static constexpr uint64_t BITS_MICROSEC = 0x0000000000FFFFFF;
300 static constexpr uint64_t BITS_SECOND = 0x000000003F000000;
301 static constexpr uint64_t BITS_MINUTE = 0x0000000FC0000000;
302 static constexpr uint64_t BITS_HOUR = 0x00007FF000000000;
303 static constexpr uint64_t BITS_SIGN = 0x0000800000000000;
304 static constexpr int TIME_SHIFT_SECOND = 24;
305 static constexpr int TIME_SHIFT_MINUTE = 30;
306 static constexpr int TIME_SHIFT_HOUR = 36;
307
308 static constexpr uint64_t MAX_TIME_VALUE =
309 BITS_SIGN | (static_cast<uint64_t>(TIME_MAX_HOUR) << TIME_SHIFT_HOUR) |
310 (static_cast<uint64_t>(TIME_MAX_MINUTE) << TIME_SHIFT_MINUTE) |
311 (static_cast<uint64_t>(TIME_MAX_SECOND) << TIME_SHIFT_SECOND);
312
313 static constexpr uint64_t MIN_TIME_VALUE =
314 (static_cast<uint64_t>(-static_cast<int64_t>(MAX_TIME_VALUE)) &
316 1;
317
318 // 838:59:59.000000
319 static constexpr uint64_t MAX_TIME_MICROSEC =
322
323 /**
324 A TIME value is stored in bit coded fields in a 64 bit unsigned value.
325 The format is efficient for comparison, storage, retrieval and movement.
326 The fields are stored in two's complement, but with a sign bit set for
327 non-negative values. This means that values can be compared using regular
328 unsigned integer logic.
329 Format:
330 Bits 0-23: microseconds (0-999999)
331 Bits 24-29: seconds (0-59)
332 Bits 30-35: minutes (0-59)
333 Bits 36-46: hours (0-838) (Theoretical range up to 2047)
334 Bits 47-47: Sign (1 for positive value, 0 for negative value)
335 */
336 uint64_t m_value = 0xffffffffffffffff;
337};
338
339class Datetime_val : public MYSQL_TIME {
340 public:
342 year = 0;
343 month = 0;
344 day = 0;
345 hour = 0;
346 minute = 0;
347 second = 0;
348 second_part = 0;
349 neg = false;
352 }
353 Datetime_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg,
354 uint32_t hour_arg, uint32_t minute_arg, uint32_t second_arg,
355 uint32_t micro_arg) {
356 year = year_arg;
357 month = month_arg;
358 day = day_arg;
359 hour = hour_arg;
360 minute = minute_arg;
361 second = second_arg;
362 second_part = micro_arg;
363 neg = false;
366 }
367 Datetime_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg,
368 uint32_t hour_arg, uint32_t minute_arg, uint32_t second_arg,
369 uint32_t micro_arg, int32_t time_zone_displacement_arg) {
370 year = year_arg;
371 month = month_arg;
372 day = day_arg;
373 hour = hour_arg;
374 minute = minute_arg;
375 second = second_arg;
376 second_part = micro_arg;
377 neg = false;
379 time_zone_displacement = time_zone_displacement_arg;
380 }
381 Datetime_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg) {
382 year = year_arg;
383 month = month_arg;
384 day = day_arg;
385 hour = 0;
386 minute = 0;
387 second = 0;
388 second_part = 0;
389 neg = false;
392 }
393};
394
395class Date_val : public Datetime_val {
396 public:
397 Date_val() = default;
398
399 Date_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg)
400 : Datetime_val(year_arg, month_arg, day_arg) {}
401};
402
403/**
404 @} (end of ingroup MY_TEMPORAL)
405*/
406#endif // MY_TEMPORAL_H
Definition: my_temporal.h:395
Date_val()=default
Date_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg)
Definition: my_temporal.h:399
Definition: my_temporal.h:339
Datetime_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg, uint32_t hour_arg, uint32_t minute_arg, uint32_t second_arg, uint32_t micro_arg, int32_t time_zone_displacement_arg)
Definition: my_temporal.h:367
Datetime_val()
Definition: my_temporal.h:341
Datetime_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg)
Definition: my_temporal.h:381
Datetime_val(uint32_t year_arg, uint32_t month_arg, uint32_t day_arg, uint32_t hour_arg, uint32_t minute_arg, uint32_t second_arg, uint32_t micro_arg)
Definition: my_temporal.h:353
Time_val is a temporal type that represents only time.
Definition: my_temporal.h:55
uint32_t minute() const
Definition: my_temporal.h:95
uint32_t second() const
Definition: my_temporal.h:99
static constexpr int TIME_SHIFT_MINUTE
Definition: my_temporal.h:305
static constexpr int TIME_SHIFT_SECOND
Definition: my_temporal.h:304
Time_val(bool negative, uint32_t second, uint32_t microsecond)
Definition: my_temporal.h:79
void set_zero()
Set zero time.
Definition: my_temporal.h:124
static constexpr const uint32_t TIME_MAX_SECOND
Definition: my_temporal.h:292
bool is_extreme_value(bool positive) const
Check against extreme values.
Definition: my_temporal.h:119
Time_val(const MYSQL_TIME &mtime)
Definition: my_temporal.h:84
bool add_nanoseconds_round(const int64_t nanoseconds)
Definition: my_temporal.h:213
static constexpr uint64_t TIME_MULT_MINUTE
Definition: my_temporal.h:296
uint32_t microsecond() const
Definition: my_temporal.h:103
bool operator==(const Time_val rhs) const
Definition: my_temporal.h:131
int64_t for_comparison() const
Definition: my_temporal.h:116
static uint32_t unsigned_seconds(uint32_t hour, uint32_t minute, uint32_t second)
Definition: my_temporal.h:279
static constexpr uint64_t TIME_MULT_SECOND
Definition: my_temporal.h:295
Time_val(bool negative, uint32_t hour, uint32_t minute, uint32_t second, uint32_t microsecond)
Definition: my_temporal.h:59
static bool make_time(bool negative, uint32_t hour, uint32_t minute, uint32_t second, uint32_t microsecond, Time_val *time)
Static functions for creation.
Definition: my_temporal.h:161
static constexpr int TIME_SHIFT_HOUR
Definition: my_temporal.h:306
bool add_seconds(int32_t seconds)
Definition: my_temporal.h:248
bool add_microseconds(int64_t mu)
Definition: my_temporal.h:255
static constexpr uint64_t MAX_TIME_MICROSEC
Definition: my_temporal.h:319
static constexpr uint64_t MAX_TIME_VALUE
Definition: my_temporal.h:308
uint32_t hour() const
Definition: my_temporal.h:91
uint64_t m_value
A TIME value is stored in bit coded fields in a 64 bit unsigned value.
Definition: my_temporal.h:336
static constexpr uint64_t BITS_MINUTE
Definition: my_temporal.h:301
int compare(const Time_val arg) const
Definition: my_temporal.h:112
static constexpr uint64_t TIME_MULT_HOUR
Definition: my_temporal.h:297
Time_val(int64_t val)
Definition: my_temporal.h:240
static uint64_t unsigned_microsec(uint32_t hour, uint32_t minute, uint32_t second, uint32_t microsec)
Definition: my_temporal.h:284
void set_extreme_value(bool negative)
Set extreme value.
Definition: my_temporal.h:127
static constexpr uint64_t MIN_TIME_VALUE
Definition: my_temporal.h:313
void set_microsecond(uint32_t fraction)
Set microsecond part of time value.
Definition: my_temporal.h:243
int64_t to_microseconds() const
Definition: my_temporal.h:183
Time_val()
Definition: my_temporal.h:57
static constexpr const uint32_t TIME_MAX_MICROSEC
Definition: my_temporal.h:293
static constexpr uint64_t BITS_SIGN
Definition: my_temporal.h:303
static constexpr uint64_t BITS_SECOND
Definition: my_temporal.h:300
static constexpr uint64_t BITS_MICROSEC
Definition: my_temporal.h:299
static constexpr uint64_t BITS_HOUR
Definition: my_temporal.h:302
static constexpr const uint32_t TIME_MAX_HOUR
Definition: my_temporal.h:290
bool operator<(const Time_val rhs) const
Definition: my_temporal.h:133
bool is_negative() const
Definition: my_temporal.h:90
bool is_valid() const
Definition: my_temporal.h:272
int32_t to_seconds() const
Definition: my_temporal.h:178
static constexpr const uint32_t TIME_MAX_MINUTE
Definition: my_temporal.h:291
static const std::string dec("DECRYPTION")
void adjust_fraction(uint32_t decimals, bool round)
Definition: my_temporal.cc:58
bool add(Time_val tv, bool subtract)
Add a time value to another time value, or subtract it.
Definition: my_temporal.cc:88
static Time_val strip_date(const MYSQL_TIME &mt)
Creates a Time_val from a date_time by extracting only the time fields.
Definition: my_temporal.cc:158
int64_t to_int_truncated() const
base100 representation without microsecond, '-12:34:56.999999' is returned as -123456
Definition: my_temporal.cc:268
double to_double() const
base100 representation with microseconds, returned as double precision float
Definition: my_temporal.cc:273
void store_time(uint8_t *ptr, uint32_t dec) const
Convert server time value to storage engine interface format.
Definition: my_temporal.cc:178
uint32_t actual_decimals() const
Definition: my_temporal.cc:50
std::string to_string() const
Definition: my_temporal.cc:285
int64_t to_int_rounded() const
base100 representation without microsecond, but rounded '-12:34:56.999999' is returned as -123457
Definition: my_temporal.cc:261
static void load_time(const uint8_t *ptr, uint32_t dec, Time_val *time)
Convert from storage engine interface time format to server time value.
Definition: my_temporal.cc:220
bool is_adjusted(uint32_t decimals) const
Definition: my_temporal.cc:45
@ MYSQL_TIMESTAMP_TIME
Stores hour, minute, second and microsecond.
Definition: mysql_time.h:60
@ MYSQL_TIMESTAMP_DATETIME_TZ
A temporary type for DATETIME or TIMESTAMP types equipped with time zone information.
Definition: mysql_time.h:67
@ MYSQL_TIMESTAMP_DATETIME
Stores all date and time components.
Definition: mysql_time.h:57
@ MYSQL_TIMESTAMP_DATE
Stores year, month and day components.
Definition: mysql_time.h:50
struct MYSQL_TIME MYSQL_TIME
Interface for low level time utilities.
constexpr const int MINS_PER_HOUR
Definition: my_time.h:137
constexpr const int SECS_PER_MIN
Definition: my_time.h:136
constexpr const int SECS_PER_HOUR
Definition: my_time.h:142
std::chrono::seconds seconds
Definition: authorize_manager.cc:68
ValueType abs(const ValueType v1, const ValueType v2)
Definition: gtid.h:75
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
Struct representing a duration.
Definition: my_time.h:219
Definition: mysql_time.h:82
int time_zone_displacement
The time zone displacement, specified in seconds.
Definition: mysql_time.h:88
unsigned long second_part
microseconds
Definition: mysql_time.h:84
unsigned int second
Definition: mysql_time.h:83
enum enum_mysql_timestamp_type time_type
Definition: mysql_time.h:86
unsigned int hour
Definition: mysql_time.h:83
unsigned int minute
Definition: mysql_time.h:83
unsigned int month
Definition: mysql_time.h:83
unsigned int day
Definition: mysql_time.h:83
bool neg
Definition: mysql_time.h:85
unsigned int year
Definition: mysql_time.h:83