1 /* Copyright (c) 2004, 2012, 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 /*
24   This is a private header of sql-common library, containing
25   declarations for my_time.c
26 */
27 
28 #ifndef _my_time_h_
29 #define _my_time_h_
30 #include "my_global.h"
31 #include "mysql_time.h"
32 
33 C_MODE_START
34 
35 extern ulonglong log_10_int[20];
36 extern uchar days_in_month[];
37 extern const char my_zero_datetime6[]; /* "0000-00-00 00:00:00.000000" */
38 
39 /*
40   Portable time_t replacement.
41   Should be signed and hold seconds for 1902 -- 2038-01-19 range
42   i.e at least a 32bit variable
43 
44   Using the system built in time_t is not an option as
45   we rely on the above requirements in the time functions
46 */
47 typedef long my_time_t;
48 
49 #define MY_TIME_T_MAX LONG_MAX
50 #define MY_TIME_T_MIN LONG_MIN
51 
52 #define DATETIME_MAX_DECIMALS 6
53 
54 /* Time handling defaults */
55 #define TIMESTAMP_MAX_YEAR 2038
56 #define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1)
57 #define TIMESTAMP_MAX_VALUE INT_MAX32
58 #define TIMESTAMP_MIN_VALUE 1
59 
60 /* two-digit years < this are 20..; >= this are 19.. */
61 #define YY_PART_YEAR	   70
62 
63 /*
64   check for valid times only if the range of time_t is greater than
65   the range of my_time_t
66 */
67 #if SIZEOF_TIME_T > 4 || defined(TIME_T_UNSIGNED)
68 # define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \
69     ((x) <= TIMESTAMP_MAX_VALUE && \
70      (x) >= TIMESTAMP_MIN_VALUE)
71 #else
72 # define IS_TIME_T_VALID_FOR_TIMESTAMP(x) \
73     ((x) >= TIMESTAMP_MIN_VALUE)
74 #endif
75 
76 /* Flags to str_to_datetime and number_to_datetime */
77 #define TIME_FUZZY_DATE         1
78 #define TIME_DATETIME_ONLY      2
79 #define TIME_NO_NSEC_ROUNDING   4
80 #define TIME_NO_DATE_FRAC_WARN  8
81 
82 /* Must be same as MODE_NO_ZERO_IN_DATE */
83 #define TIME_NO_ZERO_IN_DATE    (65536L*2*2*2*2*2*2*2)
84 /* Must be same as MODE_NO_ZERO_DATE */
85 #define TIME_NO_ZERO_DATE	(TIME_NO_ZERO_IN_DATE*2)
86 #define TIME_INVALID_DATES	(TIME_NO_ZERO_DATE*2)
87 
88 /* Conversion warnings */
89 #define MYSQL_TIME_WARN_TRUNCATED         1
90 #define MYSQL_TIME_WARN_OUT_OF_RANGE      2
91 #define MYSQL_TIME_WARN_INVALID_TIMESTAMP 4
92 #define MYSQL_TIME_WARN_ZERO_DATE         8
93 #define MYSQL_TIME_NOTE_TRUNCATED        16
94 #define MYSQL_TIME_WARN_ZERO_IN_DATE     32
95 
96 /* Usefull constants */
97 #define SECONDS_IN_24H 86400L
98 
99 /* Limits for the TIME data type */
100 #define TIME_MAX_HOUR 838
101 #define TIME_MAX_MINUTE 59
102 #define TIME_MAX_SECOND 59
103 #define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \
104                         TIME_MAX_SECOND)
105 #define TIME_MAX_VALUE_SECONDS (TIME_MAX_HOUR * 3600L + \
106                                 TIME_MAX_MINUTE * 60L + TIME_MAX_SECOND)
107 
108 /*
109   Structure to return status from
110     str_to_datetime(), str_to_time(), number_to_datetime(), number_to_time()
111 */
112 typedef struct st_mysql_time_status
113 {
114   int warnings;
115   uint fractional_digits;
116   uint nanoseconds;
117 } MYSQL_TIME_STATUS;
118 
my_time_status_init(MYSQL_TIME_STATUS * status)119 static inline void my_time_status_init(MYSQL_TIME_STATUS *status)
120 {
121   status->warnings= status->fractional_digits= status->nanoseconds= 0;
122 }
123 
124 
125 my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
126                    ulonglong flags, int *was_cut);
127 my_bool str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
128                         ulonglong flags, MYSQL_TIME_STATUS *status);
129 longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
130                             ulonglong flags, int *was_cut);
131 my_bool number_to_time(longlong nr, MYSQL_TIME *ltime, int *warnings);
132 ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *);
133 ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *);
134 ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *);
135 ulonglong TIME_to_ulonglong(const MYSQL_TIME *);
136 
137 #define MY_PACKED_TIME_GET_INT_PART(x)     ((x) >> 24)
138 #define MY_PACKED_TIME_GET_FRAC_PART(x)    ((x) % (1LL << 24))
139 #define MY_PACKED_TIME_MAKE(i, f)          ((((longlong) (i)) << 24) + (f))
140 #define MY_PACKED_TIME_MAKE_INT(i)         ((((longlong) (i)) << 24))
141 
142 longlong year_to_longlong_datetime_packed(long year);
143 longlong TIME_to_longlong_datetime_packed(const MYSQL_TIME *);
144 longlong TIME_to_longlong_date_packed(const MYSQL_TIME *);
145 longlong TIME_to_longlong_time_packed(const MYSQL_TIME *);
146 longlong TIME_to_longlong_packed(const MYSQL_TIME *);
147 
148 void TIME_from_longlong_datetime_packed(MYSQL_TIME *ltime, longlong nr);
149 void TIME_from_longlong_time_packed(MYSQL_TIME *ltime, longlong nr);
150 void TIME_from_longlong_date_packed(MYSQL_TIME *ltime, longlong nr);
151 void TIME_set_yymmdd(MYSQL_TIME *ltime, uint yymmdd);
152 void TIME_set_hhmmss(MYSQL_TIME *ltime, uint hhmmss);
153 
154 void my_datetime_packed_to_binary(longlong nr, uchar *ptr, uint dec);
155 longlong my_datetime_packed_from_binary(const uchar *ptr, uint dec);
156 uint my_datetime_binary_length(uint dec);
157 
158 void my_time_packed_to_binary(longlong nr, uchar *ptr, uint dec);
159 longlong my_time_packed_from_binary(const uchar *ptr, uint dec);
160 uint my_time_binary_length(uint dec);
161 
162 void my_timestamp_to_binary(const struct timeval *tm, uchar *ptr, uint dec);
163 void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec);
164 uint my_timestamp_binary_length(uint dec);
165 
166 my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
167                     MYSQL_TIME_STATUS *status);
168 
169 my_bool check_time_mmssff_range(const MYSQL_TIME *ltime);
170 my_bool check_time_range_quick(const MYSQL_TIME *ltime);
171 my_bool check_datetime_range(const MYSQL_TIME *ltime);
172 void adjust_time_range(struct st_mysql_time *, int *warning);
173 
174 long calc_daynr(uint year,uint month,uint day);
175 uint calc_days_in_year(uint year);
176 uint year_2000_handling(uint year);
177 
178 void my_init_time(void);
179 
180 
181 /*
182   Function to check sanity of a TIMESTAMP value
183 
184   DESCRIPTION
185     Check if a given MYSQL_TIME value fits in TIMESTAMP range.
186     This function doesn't make precise check, but rather a rough
187     estimate.
188 
189   RETURN VALUES
190     TRUE    The value seems sane
191     FALSE   The MYSQL_TIME value is definitely out of range
192 */
193 
validate_timestamp_range(const MYSQL_TIME * t)194 static inline my_bool validate_timestamp_range(const MYSQL_TIME *t)
195 {
196   if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) ||
197       (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) ||
198       (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31)))
199     return FALSE;
200 
201   return TRUE;
202 }
203 
204 my_time_t
205 my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone,
206                   my_bool *in_dst_time_gap);
207 
208 void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type);
209 void set_max_time(MYSQL_TIME *tm, my_bool neg);
210 void set_max_hhmmss(MYSQL_TIME *tm);
211 
212 /*
213   Required buffer length for my_time_to_str, my_date_to_str,
214   my_datetime_to_str and TIME_to_string functions. Note, that the
215   caller is still responsible to check that given TIME structure
216   has values in valid ranges, otherwise size of the buffer could
217   be not enough. We also rely on the fact that even wrong values
218   sent using binary protocol fit in this buffer.
219 */
220 #define MAX_DATE_STRING_REP_LENGTH 30
221 
222 int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint dec);
223 int my_date_to_str(const MYSQL_TIME *l_time, char *to);
224 int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint dec);
225 int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint dec);
226 
227 int my_timeval_to_str(const struct timeval *tm, char *to, uint dec);
228 
229 /*
230   Available interval types used in any statement.
231 
232   'interval_type' must be sorted so that simple intervals comes first,
233   ie year, quarter, month, week, day, hour, etc. The order based on
234   interval size is also important and the intervals should be kept in a
235   large to smaller order. (get_interval_value() depends on this)
236 
237   Note: If you change the order of elements in this enum you should fix
238   order of elements in 'interval_type_to_name' and 'interval_names'
239   arrays
240 
241   See also interval_type_to_name, get_interval_value, interval_names
242 */
243 
244 enum interval_type
245 {
246   INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK, INTERVAL_DAY,
247   INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, INTERVAL_MICROSECOND,
248   INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
249   INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
250   INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
251   INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_LAST
252 };
253 
254 C_MODE_END
255 
256 #endif /* _my_time_h_ */
257