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 &ltime, 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