1 /* Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #ifndef MY_TIME_INCLUDED
24 #define MY_TIME_INCLUDED
25
26 /**
27 @ingroup MY_TIME
28 @{
29
30 @file include/my_time.h
31
32 Interface for low level time utilities.
33 */
34
35 #include "my_config.h"
36
37 #include <assert.h> // assert
38 #include <cstddef> // std::size_t
39 #include <cstdint> // std::int32_t
40 #include <limits> // std::numeric_limits
41
42 #ifdef HAVE_SYS_TIME_H
43 #include <sys/time.h> // struct timeval
44 #endif /* HAVE_SYS_TIME_H */
45 #ifdef _WIN32
46 #include <winsock2.h> // struct timeval
47 #endif /* _WIN32 */
48
49 #include "mysql_time.h" // struct MYSQL_TIME, shared with client code
50
51 enum enum_field_types : int;
52
53 extern const unsigned long long int log_10_int[20];
54 extern const unsigned char days_in_month[];
55 extern const char my_zero_datetime6[]; /* "0000-00-00 00:00:00.000000" */
56
57 /**
58 Portable time_t replacement.
59 Should be signed and hold seconds for 1902 -- 2038-01-19 range
60 i.e at least a 32bit variable
61
62 Using the system built in time_t is not an option as
63 we rely on the above requirements in the time functions
64 */
65 using my_time_t = long int;
66
67 constexpr const my_time_t MY_TIME_T_MAX = std::numeric_limits<my_time_t>::max();
68 constexpr const my_time_t MY_TIME_T_MIN = std::numeric_limits<my_time_t>::min();
69
70 /** Time handling defaults */
71 constexpr const int TIMESTAMP_MAX_YEAR = 2038;
72
73 /** Two-digit years < this are 20XX; >= this are 19XX */
74 constexpr const int YY_PART_YEAR = 70;
75 constexpr const int TIMESTAMP_MIN_YEAR = (1900 + YY_PART_YEAR - 1);
76
77 constexpr const int TIMESTAMP_MAX_VALUE =
78 std::numeric_limits<std::int32_t>::max();
79 constexpr const int TIMESTAMP_MIN_VALUE = 1;
80
81 /** Flags to str_to_datetime and number_to_datetime */
82 using my_time_flags_t = unsigned int;
83
84 /** Allow zero day and zero month */
85 constexpr const my_time_flags_t TIME_FUZZY_DATE = 1;
86
87 /** Only allow full datetimes. */
88 constexpr const my_time_flags_t TIME_DATETIME_ONLY = 2;
89
90 constexpr const my_time_flags_t TIME_FRAC_TRUNCATE = 4;
91 constexpr const my_time_flags_t TIME_NO_DATE_FRAC_WARN = 8;
92
93 /** Don't allow zero day or zero month */
94 constexpr const my_time_flags_t TIME_NO_ZERO_IN_DATE = 16;
95
96 /** Don't allow 0000-00-00 date */
97 constexpr const my_time_flags_t TIME_NO_ZERO_DATE = 32;
98
99 /** Allow 2000-02-31 */
100 constexpr const my_time_flags_t TIME_INVALID_DATES = 64;
101
102 /** Allow only HH:MM:SS or MM:SS time formats */
103 constexpr const my_time_flags_t TIME_STRICT_COLON = 128;
104
105 /** Conversion warnings */
106 constexpr const int MYSQL_TIME_WARN_TRUNCATED = 1;
107 constexpr const int MYSQL_TIME_WARN_OUT_OF_RANGE = 2;
108 constexpr const int MYSQL_TIME_WARN_INVALID_TIMESTAMP = 4;
109 constexpr const int MYSQL_TIME_WARN_ZERO_DATE = 8;
110 constexpr const int MYSQL_TIME_NOTE_TRUNCATED = 16;
111 constexpr const int MYSQL_TIME_WARN_ZERO_IN_DATE = 32;
112 constexpr const int MYSQL_TIME_WARN_DATETIME_OVERFLOW = 64;
113
114 /** Usefull constants */
115 constexpr const long int SECONDS_IN_24H = 86400L;
116
117 /** Limits for the TIME data type */
118 constexpr const int TIME_MAX_HOUR = 838;
119 constexpr const int TIME_MAX_MINUTE = 59;
120 constexpr const int TIME_MAX_SECOND = 59;
121
122 /**
123 Note that this MUST be a signed type, as we use the unary - operator on it.
124 */
125 constexpr const int TIME_MAX_VALUE =
126 TIME_MAX_HOUR * 10000 + TIME_MAX_MINUTE * 100 + TIME_MAX_SECOND;
127
128 constexpr const int TIME_MAX_VALUE_SECONDS =
129 TIME_MAX_HOUR * 3600 + TIME_MAX_MINUTE * 60 + TIME_MAX_SECOND;
130
131 constexpr const int DATETIME_MAX_DECIMALS = 6;
132
133 constexpr const int SECS_PER_MIN = 60;
134 constexpr const int MINS_PER_HOUR = 60;
135 constexpr const int HOURS_PER_DAY = 24;
136 constexpr const int DAYS_PER_WEEK = 7;
137 constexpr const int DAYS_PER_NYEAR = 365;
138 constexpr const int DAYS_PER_LYEAR = 366;
139 constexpr const int SECS_PER_HOUR = (SECS_PER_MIN * MINS_PER_HOUR);
140 constexpr const int SECS_PER_DAY = (SECS_PER_HOUR * HOURS_PER_DAY);
141 constexpr const int MONS_PER_YEAR = 12;
142
143 constexpr const int MAX_TIME_ZONE_HOURS = 14;
144
145 /** Flags for calc_week() function. */
146 constexpr const unsigned int WEEK_MONDAY_FIRST = 1;
147 constexpr const unsigned int WEEK_YEAR = 2;
148 constexpr const unsigned int WEEK_FIRST_WEEKDAY = 4;
149
150 /** Daynumber from year 0 to 9999-12-31 */
151 constexpr const int64_t MAX_DAY_NUMBER = 3652424;
152
153 /**
154 Structure to return status from
155 str_to_datetime(), str_to_time(), number_to_datetime(), number_to_time()
156 @note Implicit default constructor initializes all members to 0.
157 */
158 struct MYSQL_TIME_STATUS {
159 int warnings{0};
160 unsigned int fractional_digits{0};
161 unsigned int nanoseconds{0};
162 };
163
164 /**
165 Struct representing a duration. Content is similar to MYSQL_TIME
166 but member variables are unsigned.
167 */
168 struct Interval {
169 unsigned long int year;
170 unsigned long int month;
171 unsigned long int day;
172 unsigned long int hour;
173 unsigned long long int minute;
174 unsigned long long int second;
175 unsigned long long int second_part;
176 bool neg;
177 };
178
179 void my_init_time();
180
181 long calc_daynr(unsigned int year, unsigned int month, unsigned int day);
182 unsigned int calc_days_in_year(unsigned int year);
183 unsigned int year_2000_handling(unsigned int year);
184
185 bool time_zone_displacement_to_seconds(const char *str, size_t length,
186 int *result);
187
188 void get_date_from_daynr(int64_t daynr, unsigned int *year, unsigned int *month,
189 unsigned int *day);
190 int calc_weekday(long daynr, bool sunday_first_day_of_week);
191 bool valid_period(long long int period);
192 unsigned long int convert_period_to_month(unsigned long int period);
193 unsigned long int convert_month_to_period(unsigned long int month);
194
195 /**
196 Check for valid times only if the range of time_t is greater than
197 the range of my_time_t. Which is almost always the case and even time_t
198 does have the same range, the compiler will optimize away
199 the unnecessary test (checked with compiler explorer).
200 */
is_time_t_valid_for_timestamp(time_t x)201 inline bool is_time_t_valid_for_timestamp(time_t x) {
202 return x <= TIMESTAMP_MAX_VALUE && x >= TIMESTAMP_MIN_VALUE;
203 }
204
205 unsigned int calc_week(const MYSQL_TIME &l_time, unsigned int week_behaviour,
206 unsigned int *year);
207
208 bool check_date(const MYSQL_TIME <ime, bool not_zero_date,
209 my_time_flags_t flags, int *was_cut);
210 bool str_to_datetime(const char *str, std::size_t length, MYSQL_TIME *l_time,
211 my_time_flags_t flags, MYSQL_TIME_STATUS *status);
212 long long int number_to_datetime(long long int nr, MYSQL_TIME *time_res,
213 my_time_flags_t flags, int *was_cut);
214 bool number_to_time(long long int nr, MYSQL_TIME *ltime, int *warnings);
215 unsigned long long int TIME_to_ulonglong_datetime(const MYSQL_TIME &my_time);
216 unsigned long long int TIME_to_ulonglong_date(const MYSQL_TIME &my_time);
217 unsigned long long int TIME_to_ulonglong_time(const MYSQL_TIME &my_time);
218 unsigned long long int TIME_to_ulonglong(const MYSQL_TIME &my_time);
219
220 unsigned long long int TIME_to_ulonglong_datetime_round(
221 const MYSQL_TIME &my_time, int *warnings);
222 unsigned long long int TIME_to_ulonglong_time_round(const MYSQL_TIME &my_time);
223
224 /**
225 Round any MYSQL_TIME timepoint and convert to ulonglong.
226 @param my_time input
227 @param[out] warnings warning vector
228 @return time point as ulonglong
229 */
TIME_to_ulonglong_round(const MYSQL_TIME & my_time,int * warnings)230 inline unsigned long long int TIME_to_ulonglong_round(const MYSQL_TIME &my_time,
231 int *warnings) {
232 switch (my_time.time_type) {
233 case MYSQL_TIMESTAMP_TIME:
234 return TIME_to_ulonglong_time_round(my_time);
235 case MYSQL_TIMESTAMP_DATETIME:
236 return TIME_to_ulonglong_datetime_round(my_time, warnings);
237 case MYSQL_TIMESTAMP_DATE:
238 return TIME_to_ulonglong_date(my_time);
239 default:
240 assert(false);
241 return 0;
242 }
243 }
244
245 /**
246 Extract the microsecond part of a MYSQL_TIME struct as an n *
247 (1/10^6) fraction as a double.
248
249 @return microseconds part as double
250 */
TIME_microseconds(const MYSQL_TIME & my_time)251 inline double TIME_microseconds(const MYSQL_TIME &my_time) {
252 return static_cast<double>(my_time.second_part) / 1000000.0;
253 }
254
255 /**
256 Convert a MYSQL_TIME datetime to double where the integral part is
257 the timepoint as an ulonglong, and the fractional part is the
258 fraction of the second.
259
260 @param my_time datetime to convert
261 @return datetime as double
262 */
TIME_to_double_datetime(const MYSQL_TIME & my_time)263 inline double TIME_to_double_datetime(const MYSQL_TIME &my_time) {
264 return static_cast<double>(TIME_to_ulonglong_datetime(my_time)) +
265 TIME_microseconds(my_time);
266 }
267
268 /**
269 Convert a MYSQL_TIME time to double where the integral part is
270 the timepoint as an ulonglong, and the fractional part is the
271 fraction of the second.
272
273 @param my_time time to convert
274 @return datetime as double
275 */
TIME_to_double_time(const MYSQL_TIME & my_time)276 inline double TIME_to_double_time(const MYSQL_TIME &my_time) {
277 return static_cast<double>(TIME_to_ulonglong_time(my_time)) +
278 TIME_microseconds(my_time);
279 }
280
281 /**
282 Convert a MYSQL_TIME to double where the integral part is the
283 timepoint as an ulonglong, and the fractional part is the fraction
284 of the second. The actual time type is extracted from
285 MYSQL_TIME::time_type.
286
287 @param my_time MYSQL_TIME to convert
288 @return MYSQL_TIME as double
289 */
TIME_to_double(const MYSQL_TIME & my_time)290 inline double TIME_to_double(const MYSQL_TIME &my_time) {
291 return static_cast<double>(TIME_to_ulonglong(my_time)) +
292 TIME_microseconds(my_time);
293 }
294
295 /**
296 Return the fraction of the second as the number of microseconds.
297
298 @param i timepoint as longlong
299 @return frational part of an timepoint represented as an (u)longlong
300 */
my_packed_time_get_frac_part(long long int i)301 inline long long int my_packed_time_get_frac_part(long long int i) {
302 return (i % (1LL << 24));
303 }
304
305 long long int year_to_longlong_datetime_packed(long year);
306 long long int TIME_to_longlong_datetime_packed(const MYSQL_TIME &my_time);
307 long long int TIME_to_longlong_date_packed(const MYSQL_TIME &my_time);
308 long long int TIME_to_longlong_time_packed(const MYSQL_TIME &my_time);
309 long long int TIME_to_longlong_packed(const MYSQL_TIME &my_time);
310
311 void TIME_from_longlong_datetime_packed(MYSQL_TIME *ltime, long long int nr);
312 void TIME_from_longlong_time_packed(MYSQL_TIME *ltime, long long int nr);
313 void TIME_from_longlong_date_packed(MYSQL_TIME *ltime, long long int nr);
314 void TIME_set_yymmdd(MYSQL_TIME *ltime, unsigned int yymmdd);
315 void TIME_set_hhmmss(MYSQL_TIME *ltime, unsigned int hhmmss);
316
317 void my_datetime_packed_to_binary(long long int nr, unsigned char *ptr,
318 unsigned int dec);
319 long long int my_datetime_packed_from_binary(const unsigned char *ptr,
320 unsigned int dec);
321
322 void my_time_packed_to_binary(long long int nr, unsigned char *ptr,
323 unsigned int dec);
324 long long int my_time_packed_from_binary(const unsigned char *ptr,
325 unsigned int dec);
326
327 void my_timestamp_to_binary(const struct timeval *tm, unsigned char *ptr,
328 unsigned int dec);
329 void my_timestamp_from_binary(struct timeval *tm, const unsigned char *ptr,
330 unsigned int dec);
331
332 bool str_to_time(const char *str, std::size_t length, MYSQL_TIME *l_time,
333 MYSQL_TIME_STATUS *status, my_time_flags_t flags = 0);
334
335 bool check_time_mmssff_range(const MYSQL_TIME &my_time);
336 bool check_time_range_quick(const MYSQL_TIME &my_time);
337 bool check_datetime_range(const MYSQL_TIME &my_time);
338 void adjust_time_range(MYSQL_TIME *, int *warning);
339
340 /**
341 Function to check sanity of a TIMESTAMP value.
342
343 Check if a given MYSQL_TIME value fits in TIMESTAMP range.
344 This function doesn't make precise check, but rather a rough
345 estimate.
346
347 @param my_time timepoint to check
348 @retval true The value seems sane
349 @retval false The MYSQL_TIME value is definitely out of range
350 */
validate_timestamp_range(const MYSQL_TIME & my_time)351 inline bool validate_timestamp_range(const MYSQL_TIME &my_time) {
352 if ((my_time.year > TIMESTAMP_MAX_YEAR ||
353 my_time.year < TIMESTAMP_MIN_YEAR) ||
354 (my_time.year == TIMESTAMP_MAX_YEAR &&
355 (my_time.month > 1 || my_time.day > 19)) ||
356 (my_time.year == TIMESTAMP_MIN_YEAR &&
357 (my_time.month < 12 || my_time.day < 31)))
358 return false;
359
360 return true;
361 }
362
363 my_time_t my_system_gmt_sec(const MYSQL_TIME &my_time, long *my_timezone,
364 bool *in_dst_time_gap);
365
366 void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type);
367 void set_max_time(MYSQL_TIME *tm, bool neg);
368 void set_max_hhmmss(MYSQL_TIME *tm);
369
370 /**
371 Required buffer length for my_time_to_str, my_date_to_str,
372 my_datetime_to_str and TIME_to_string functions. Note, that the
373 caller is still responsible to check that given TIME structure
374 has values in valid ranges, otherwise size of the buffer might
375 well be insufficient. We also rely on the fact that even incorrect values
376 sent using binary protocol fit in this buffer.
377 */
378 constexpr const std::size_t MAX_DATE_STRING_REP_LENGTH =
379 sizeof("YYYY-MM-DD AM HH:MM:SS.FFFFFF+HH:MM");
380
381 int my_time_to_str(const MYSQL_TIME &my_time, char *to, unsigned int dec);
382 int my_date_to_str(const MYSQL_TIME &my_time, char *to);
383 int my_datetime_to_str(const MYSQL_TIME &my_time, char *to, unsigned int dec);
384 int my_TIME_to_str(const MYSQL_TIME &my_time, char *to, unsigned int dec);
385
386 void my_date_to_binary(const MYSQL_TIME *ltime, unsigned char *ptr);
387 int my_timeval_to_str(const struct timeval *tm, char *to, unsigned int dec);
388
389 /**
390 Available interval types used in any statement.
391
392 'interval_type' must be sorted so that simple intervals comes first,
393 ie year, quarter, month, week, day, hour, etc. The order based on
394 interval size is also important and the intervals should be kept in a
395 large to smaller order. (get_interval_value() depends on this)
396
397 @note If you change the order of elements in this enum you should fix
398 order of elements in 'interval_type_to_name' and 'interval_names'
399 arrays
400
401 @see interval_type_to_name, get_interval_value, interval_names
402 */
403 enum interval_type {
404 INTERVAL_YEAR,
405 INTERVAL_QUARTER,
406 INTERVAL_MONTH,
407 INTERVAL_WEEK,
408 INTERVAL_DAY,
409 INTERVAL_HOUR,
410 INTERVAL_MINUTE,
411 INTERVAL_SECOND,
412 INTERVAL_MICROSECOND,
413 INTERVAL_YEAR_MONTH,
414 INTERVAL_DAY_HOUR,
415 INTERVAL_DAY_MINUTE,
416 INTERVAL_DAY_SECOND,
417 INTERVAL_HOUR_MINUTE,
418 INTERVAL_HOUR_SECOND,
419 INTERVAL_MINUTE_SECOND,
420 INTERVAL_DAY_MICROSECOND,
421 INTERVAL_HOUR_MICROSECOND,
422 INTERVAL_MINUTE_MICROSECOND,
423 INTERVAL_SECOND_MICROSECOND,
424 INTERVAL_LAST
425 };
426
427 bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type,
428 Interval interval, int *warnings);
429
430 /**
431 Round the input argument to the specified precision by computing
432 the remainder modulo log10 of the difference between max and
433 desired precison.
434
435 @param nr number to round
436 @param decimals desired precision
437 @return nr rounded according to the desired precision.
438 */
my_time_fraction_remainder(long nr,unsigned int decimals)439 inline long my_time_fraction_remainder(long nr, unsigned int decimals) {
440 assert(decimals <= DATETIME_MAX_DECIMALS);
441 return nr % static_cast<long>(log_10_int[DATETIME_MAX_DECIMALS - decimals]);
442 }
443
444 /**
445 Truncate the number of microseconds in MYSQL_TIME::second_part to
446 the desired precision.
447
448 @param ltime time point
449 @param decimals desired precision
450 */
my_time_trunc(MYSQL_TIME * ltime,unsigned int decimals)451 inline void my_time_trunc(MYSQL_TIME *ltime, unsigned int decimals) {
452 ltime->second_part -=
453 my_time_fraction_remainder(ltime->second_part, decimals);
454 }
455
456 /**
457 Alias for my_time_trunc.
458
459 @param ltime time point
460 @param decimals desired precision
461 */
my_datetime_trunc(MYSQL_TIME * ltime,unsigned int decimals)462 inline void my_datetime_trunc(MYSQL_TIME *ltime, unsigned int decimals) {
463 return my_time_trunc(ltime, decimals);
464 }
465
466 /**
467 Truncate the tv_usec member of a posix timeval struct to the
468 specified number of decimals.
469
470 @param tv timepoint/duration
471 @param decimals desired precision
472 */
my_timeval_trunc(struct timeval * tv,unsigned int decimals)473 inline void my_timeval_trunc(struct timeval *tv, unsigned int decimals) {
474 tv->tv_usec -= my_time_fraction_remainder(tv->tv_usec, decimals);
475 }
476
477 /**
478 Predicate for fuzzyness of date.
479
480 @param my_time time point to check
481 @param fuzzydate bitfield indicating if fuzzy dates are premitted
482 @retval true if TIME_FUZZY_DATE is unset and either month or day is 0
483 @retval false otherwise
484 */
check_fuzzy_date(const MYSQL_TIME & my_time,my_time_flags_t fuzzydate)485 inline bool check_fuzzy_date(const MYSQL_TIME &my_time,
486 my_time_flags_t fuzzydate) {
487 return !(fuzzydate & TIME_FUZZY_DATE) && (!my_time.month || !my_time.day);
488 }
489
490 /**
491 Predicate which returns true if at least one of the date members are non-zero.
492
493 @param my_time time point to check.
494 @retval false if all the date members are zero
495 @retval true otherwise
496 */
non_zero_date(const MYSQL_TIME & my_time)497 inline bool non_zero_date(const MYSQL_TIME &my_time) {
498 return my_time.year || my_time.month || my_time.day;
499 }
500
501 /**
502 Predicate which returns true if at least one of the time members are non-zero.
503
504 @param my_time time point to check.
505 @retval false if all the time members are zero
506 @retval true otherwise
507 */
non_zero_time(const MYSQL_TIME & my_time)508 inline bool non_zero_time(const MYSQL_TIME &my_time) {
509 return my_time.hour || my_time.minute || my_time.second ||
510 my_time.second_part;
511 }
512
513 /**
514 "Casts" MYSQL_TIME datetime to a MYSQL_TIME time. Sets
515 MYSQL_TIME::time_type to MYSQL_TIMESTAMP_TIME and zeroes out the
516 date members.
517
518 @param ltime timepoint to cast
519 */
datetime_to_time(MYSQL_TIME * ltime)520 inline void datetime_to_time(MYSQL_TIME *ltime) {
521 ltime->year = 0;
522 ltime->month = 0;
523 ltime->day = 0;
524 ltime->time_type = MYSQL_TIMESTAMP_TIME;
525 }
526
527 /**
528 "Casts" MYSQL_TIME datetime to a MYSQL_TIME date. Sets
529 MYSQL_TIME::time_type to MYSQL_TIMESTAMP_DATE and zeroes out the
530 time members.
531
532 @param ltime timepoint to cast
533 */
datetime_to_date(MYSQL_TIME * ltime)534 inline void datetime_to_date(MYSQL_TIME *ltime) {
535 ltime->hour = 0;
536 ltime->minute = 0;
537 ltime->second = 0;
538 ltime->second_part = 0;
539 ltime->time_type = MYSQL_TIMESTAMP_DATE;
540 }
541
542 /**
543 "Casts" a MYSQL_TIME to datetime by setting MYSQL_TIME::time_type to
544 MYSQL_TIMESTAMP_DATETIME.
545 @note There is no check to ensure that the result is a valid datetime.
546
547 @param ltime timpoint to cast
548 */
date_to_datetime(MYSQL_TIME * ltime)549 inline void date_to_datetime(MYSQL_TIME *ltime) {
550 ltime->time_type = MYSQL_TIMESTAMP_DATETIME;
551 }
552
553 bool time_add_nanoseconds_with_truncate(MYSQL_TIME *ltime,
554 unsigned int nanoseconds,
555 int *warnings);
556 bool datetime_add_nanoseconds_with_truncate(MYSQL_TIME *ltime,
557 unsigned int nanoseconds);
558 bool time_add_nanoseconds_with_round(MYSQL_TIME *ltime,
559 unsigned int nanoseconds, int *warnings);
560
561 bool datetime_add_nanoseconds_with_round(MYSQL_TIME *ltime,
562 unsigned int nanoseconds,
563 int *warnings);
564
565 bool time_add_nanoseconds_adjust_frac(MYSQL_TIME *ltime,
566 unsigned int nanoseconds, int *warnings,
567 bool truncate);
568
569 bool datetime_add_nanoseconds_adjust_frac(MYSQL_TIME *ltime,
570 unsigned int nanoseconds,
571 int *warnings, bool truncate);
572
573 bool my_time_adjust_frac(MYSQL_TIME *ltime, unsigned int dec, bool truncate);
574 bool my_datetime_adjust_frac(MYSQL_TIME *ltime, unsigned int dec, int *warnings,
575 bool truncate);
576 bool my_timeval_round(struct timeval *tv, unsigned int decimals);
577 void mix_date_and_time(MYSQL_TIME *ldate, const MYSQL_TIME &my_time);
578
579 void localtime_to_TIME(MYSQL_TIME *to, const struct tm *from);
580 void calc_time_from_sec(MYSQL_TIME *to, long long int seconds,
581 long microseconds);
582 bool calc_time_diff(const MYSQL_TIME &my_time1, const MYSQL_TIME &my_time2,
583 int l_sign, long long int *seconds_out,
584 long *microseconds_out);
585 int my_time_compare(const MYSQL_TIME &my_time_a, const MYSQL_TIME &my_time_b);
586
587 long long int TIME_to_longlong_packed(const MYSQL_TIME &my_time,
588 enum enum_field_types type);
589
590 void TIME_from_longlong_packed(MYSQL_TIME *ltime, enum enum_field_types type,
591 long long int packed_value);
592
593 long long int longlong_from_datetime_packed(enum enum_field_types type,
594 long long int packed_value);
595
596 double double_from_datetime_packed(enum enum_field_types type,
597 long long int packed_value);
598
599 /**
600 @} (end of ingroup MY_TIME)
601 */
602 #endif /* MY_TIME_INCLUDED */
603