32
32
/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */
34
static unsigned char internal_format_positions[]=
35
{0, 1, 2, 3, 4, 5, 6, (unsigned char) 255};
34
static uchar internal_format_positions[]=
35
{0, 1, 2, 3, 4, 5, 6, (uchar) 255};
37
37
static char time_separator=':';
39
static uint32_t const days_at_timestart=719528; /* daynr at 1970.01.01 */
40
unsigned char days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
39
static ulong const days_at_timestart=719528; /* daynr at 1970.01.01 */
40
uchar days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
43
43
Offset of system time zone from UTC in seconds used to speed up
145
145
- The hour part must be specified in hour-minute-second order.
148
DRIZZLE_TIMESTAMP_NONE String wasn't a timestamp, like
148
MYSQL_TIMESTAMP_NONE String wasn't a timestamp, like
149
149
[DD [HH:[MM:[SS]]]].fraction.
150
150
l_time is not changed.
151
DRIZZLE_TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
152
DRIZZLE_TIMESTAMP_DATETIME Full timestamp
153
DRIZZLE_TIMESTAMP_ERROR Timestamp with wrong values.
151
MYSQL_TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
152
MYSQL_TIMESTAMP_DATETIME Full timestamp
153
MYSQL_TIMESTAMP_ERROR Timestamp with wrong values.
154
154
All elements in l_time is set to 0
157
157
#define MAX_DATE_PARTS 8
159
enum enum_drizzle_timestamp_type
160
str_to_datetime(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
161
uint32_t flags, int *was_cut)
159
enum enum_mysql_timestamp_type
160
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
161
uint flags, int *was_cut)
163
uint32_t field_length, year_length=4, digits, i, number_of_fields;
164
uint32_t date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
165
uint32_t add_hours= 0, start_loop;
166
uint32_t not_zero_date, allow_space;
167
bool is_internal_format;
163
uint field_length, year_length=4, digits, i, number_of_fields;
164
uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
165
uint add_hours= 0, start_loop;
166
ulong not_zero_date, allow_space;
167
my_bool is_internal_format;
168
168
const char *pos, *last_field_pos=NULL;
169
169
const char *end=str+length;
170
const unsigned char *format_position;
171
bool found_delimitier= 0, found_space= 0;
172
uint32_t frac_pos, frac_len;
170
const uchar *format_position;
171
my_bool found_delimitier= 0, found_space= 0;
172
uint frac_pos, frac_len;
176
176
/* Skip space at start */
177
for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++)
177
for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
179
if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str))
179
if (str == end || ! my_isdigit(&my_charset_latin1, *str))
182
return(DRIZZLE_TIMESTAMP_NONE);
182
return(MYSQL_TIMESTAMP_NONE);
185
185
is_internal_format= 0;
217
217
We do this by checking if there is two numbers separated by
218
218
space in the input.
220
while (pos < end && !my_isspace(&my_charset_utf8_general_ci, *pos))
220
while (pos < end && !my_isspace(&my_charset_latin1, *pos))
222
while (pos < end && !my_isdigit(&my_charset_utf8_general_ci, *pos))
222
while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
226
226
if (flags & TIME_DATETIME_ONLY)
229
return(DRIZZLE_TIMESTAMP_NONE); /* Can't be a full datetime */
229
return(MYSQL_TIMESTAMP_NONE); /* Can't be a full datetime */
231
231
/* Date field. Set hour, minutes and seconds to 0 */
232
232
date[0]= date[1]= date[2]= date[3]= date[4]= 0;
253
253
not_zero_date= 0;
254
254
for (i = start_loop;
255
255
i < MAX_DATE_PARTS-1 && str != end &&
256
my_isdigit(&my_charset_utf8_general_ci,*str);
256
my_isdigit(&my_charset_latin1,*str);
259
259
const char *start= str;
260
uint32_t tmp_value= (uint) (unsigned char) (*str++ - '0');
261
while (str != end && my_isdigit(&my_charset_utf8_general_ci,str[0]) &&
260
ulong tmp_value= (uint) (uchar) (*str++ - '0');
261
while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
262
262
(!is_internal_format || --field_length))
264
tmp_value=tmp_value*10 + (uint32_t) (unsigned char) (*str - '0');
264
tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
267
267
date_len[i]= (uint) (str - start);
268
268
if (tmp_value > 999999) /* Impossible date part */
271
return(DRIZZLE_TIMESTAMP_NONE);
271
return(MYSQL_TIMESTAMP_NONE);
273
273
date[i]=tmp_value;
274
274
not_zero_date|= tmp_value;
299
299
while (str != end &&
300
(my_ispunct(&my_charset_utf8_general_ci,*str) ||
301
my_isspace(&my_charset_utf8_general_ci,*str)))
300
(my_ispunct(&my_charset_latin1,*str) ||
301
my_isspace(&my_charset_latin1,*str)))
303
if (my_isspace(&my_charset_utf8_general_ci,*str))
303
if (my_isspace(&my_charset_latin1,*str))
305
305
if (!(allow_space & (1 << i)))
308
return(DRIZZLE_TIMESTAMP_NONE);
308
return(MYSQL_TIMESTAMP_NONE);
436
436
return(l_time->time_type=
437
(number_of_fields <= 3 ? DRIZZLE_TIMESTAMP_DATE :
438
DRIZZLE_TIMESTAMP_DATETIME));
437
(number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE :
438
MYSQL_TIMESTAMP_DATETIME));
441
memset(l_time, 0, sizeof(*l_time));
442
return(DRIZZLE_TIMESTAMP_ERROR);
441
bzero((char*) l_time, sizeof(*l_time));
442
return(MYSQL_TIMESTAMP_ERROR);
447
Convert a time string to a DRIZZLE_TIME struct.
447
Convert a time string to a MYSQL_TIME struct.
454
454
There may be an optional [.second_part] after seconds
455
455
length Length of str
456
456
l_time Store result here
457
warning Set DRIZZLE_TIME_WARN_TRUNCATED flag if the input string
457
warning Set MYSQL_TIME_WARN_TRUNCATED flag if the input string
458
458
was cut during conversion, and/or
459
DRIZZLE_TIME_WARN_OUT_OF_RANGE flag, if the value is
459
MYSQL_TIME_WARN_OUT_OF_RANGE flag, if the value is
471
bool str_to_time(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
471
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
476
476
const char *end=str+length, *end_of_days;
477
bool found_days,found_hours;
477
my_bool found_days,found_hours;
482
for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++)
482
for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
484
484
if (str != end && *str == '-')
494
494
if (length >= 12)
495
495
{ /* Probably full timestamp */
497
enum enum_drizzle_timestamp_type
497
enum enum_mysql_timestamp_type
498
498
res= str_to_datetime(str, length, l_time,
499
499
(TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
500
if ((int) res >= (int) DRIZZLE_TIMESTAMP_ERROR)
500
if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
503
*warning|= DRIZZLE_TIME_WARN_TRUNCATED;
504
return res == DRIZZLE_TIMESTAMP_ERROR;
503
*warning|= MYSQL_TIME_WARN_TRUNCATED;
504
return res == MYSQL_TIMESTAMP_ERROR;
508
508
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
509
for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++)
509
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
510
510
value=value*10L + (long) (*str - '0');
512
512
/* Skip all space after 'days' */
513
513
end_of_days= str;
514
for (; str != end && my_isspace(&my_charset_utf8_general_ci, str[0]) ; str++)
514
for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++)
517
517
found_days=found_hours=0;
518
518
if ((uint) (end-str) > 1 && str != end_of_days &&
519
my_isdigit(&my_charset_utf8_general_ci, *str))
519
my_isdigit(&my_charset_latin1, *str))
520
520
{ /* Found days part */
521
date[0]= (uint32_t) value;
521
date[0]= (ulong) value;
522
522
state= 1; /* Assume next is hours */
525
525
else if ((end-str) > 1 && *str == time_separator &&
526
my_isdigit(&my_charset_utf8_general_ci, str[1]))
526
my_isdigit(&my_charset_latin1, str[1]))
528
528
date[0]= 0; /* Assume we found hours */
529
date[1]= (uint32_t) value;
529
date[1]= (ulong) value;
532
532
str++; /* skip ':' */
545
545
/* Read hours, minutes and seconds */
548
for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++)
548
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
549
549
value=value*10L + (long) (*str - '0');
550
date[state++]= (uint32_t) value;
550
date[state++]= (ulong) value;
551
551
if (state == 4 || (end-str) < 2 || *str != time_separator ||
552
!my_isdigit(&my_charset_utf8_general_ci,str[1]))
552
!my_isdigit(&my_charset_latin1,str[1]))
554
554
str++; /* Skip time_separator (':') */
559
559
/* Fix the date to assume that seconds was given */
560
560
if (!found_hours && !found_days)
562
bmove_upp((unsigned char*) (date+4), (unsigned char*) (date+state),
562
bmove_upp((uchar*) (date+4), (uchar*) (date+state),
563
563
sizeof(long)*(state-1));
564
memset(date, 0, sizeof(long)*(4-state));
564
bzero((uchar*) date, sizeof(long)*(4-state));
567
memset(date+state, 0, sizeof(long)*(4-state));
567
bzero((uchar*) (date+state), sizeof(long)*(4-state));
571
571
/* Get fractional second part */
572
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_utf8_general_ci,str[1]))
572
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
574
574
int field_length= 5;
575
str++; value=(uint) (unsigned char) (*str - '0');
576
while (++str != end && my_isdigit(&my_charset_utf8_general_ci, *str))
575
str++; value=(uint) (uchar) (*str - '0');
576
while (++str != end && my_isdigit(&my_charset_latin1, *str))
578
578
if (field_length-- > 0)
579
value= value*10 + (uint) (unsigned char) (*str - '0');
579
value= value*10 + (uint) (uchar) (*str - '0');
581
581
if (field_length > 0)
582
582
value*= (long) log_10_int[field_length];
583
583
else if (field_length < 0)
584
*warning|= DRIZZLE_TIME_WARN_TRUNCATED;
585
date[4]= (uint32_t) value;
584
*warning|= MYSQL_TIME_WARN_TRUNCATED;
585
date[4]= (ulong) value;
591
591
/* (may occur as result of %g formatting of time value) */
592
592
if ((end - str) > 1 &&
593
593
(*str == 'e' || *str == 'E') &&
594
(my_isdigit(&my_charset_utf8_general_ci, str[1]) ||
594
(my_isdigit(&my_charset_latin1, str[1]) ||
595
595
((str[1] == '-' || str[1] == '+') &&
596
596
(end - str) > 2 &&
597
my_isdigit(&my_charset_utf8_general_ci, str[2]))))
597
my_isdigit(&my_charset_latin1, str[2]))))
600
600
if (internal_format_positions[7] != 255)
602
602
/* Read a possible AM/PM */
603
while (str != end && my_isspace(&my_charset_utf8_general_ci, *str))
603
while (str != end && my_isspace(&my_charset_latin1, *str))
605
605
if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
627
627
l_time->minute= date[2];
628
628
l_time->second= date[3];
629
629
l_time->second_part= date[4];
630
l_time->time_type= DRIZZLE_TIMESTAMP_TIME;
630
l_time->time_type= MYSQL_TIMESTAMP_TIME;
632
/* Check if the value is valid and fits into DRIZZLE_TIME range */
632
/* Check if the value is valid and fits into MYSQL_TIME range */
633
633
if (check_time_range(l_time, warning))
636
/* Check if there is garbage at end of the DRIZZLE_TIME specification */
636
/* Check if there is garbage at end of the MYSQL_TIME specification */
641
if (!my_isspace(&my_charset_utf8_general_ci,*str))
641
if (!my_isspace(&my_charset_latin1,*str))
643
*warning|= DRIZZLE_TIME_WARN_TRUNCATED;
643
*warning|= MYSQL_TIME_WARN_TRUNCATED;
646
646
} while (++str != end);
653
Check 'time' value to lie in the DRIZZLE_TIME range
653
Check 'time' value to lie in the MYSQL_TIME range
656
656
check_time_range()
657
time pointer to DRIZZLE_TIME value
658
warning set DRIZZLE_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
657
time pointer to MYSQL_TIME value
658
warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
661
661
If the time value lies outside of the range [-838:59:59, 838:59:59],
662
662
set it to the closest endpoint of the range and set
663
DRIZZLE_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
663
MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
666
666
0 time value is valid, but was possibly truncated
667
667
1 time value is invalid
670
int check_time_range(DRIZZLE_TIME *my_time, int *warning)
670
int check_time_range(struct st_mysql_time *my_time, int *warning)
791
791
Time in UTC seconds since Unix Epoch representation.
794
my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone,
794
my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
795
795
bool *in_dst_time_gap)
800
DRIZZLE_TIME tmp_time;
801
DRIZZLE_TIME *t= &tmp_time;
801
MYSQL_TIME *t= &tmp_time;
802
802
struct tm *l_time,tm_tmp;
803
803
long diff, current_timezone;
980
980
} /* my_system_gmt_sec */
983
/* Set DRIZZLE_TIME structure to 0000-00-00 00:00:00.000000 */
983
/* Set MYSQL_TIME structure to 0000-00-00 00:00:00.000000 */
985
void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type)
985
void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
987
memset(tm, 0, sizeof(*tm));
987
bzero((void*) tm, sizeof(*tm));
988
988
tm->time_type= time_type;
993
993
Functions to convert time/date/datetime value to a string,
994
994
using default format.
995
This functions don't check that given DRIZZLE_TIME structure members are
995
This functions don't check that given MYSQL_TIME structure members are
996
996
in valid range. If they are not, return value won't reflect any
997
997
valid date either. Additionally, make_time doesn't take into
998
998
account time->day member: it's assumed that days have been converted
1002
1002
number of characters written to 'to'
1005
int my_time_to_str(const DRIZZLE_TIME *l_time, char *to)
1005
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
1007
uint32_t extra_hours= 0;
1007
uint extra_hours= 0;
1008
1008
return sprintf(to, "%s%02u:%02u:%02u",
1009
1009
(l_time->neg ? "-" : ""),
1010
1010
extra_hours+ l_time->hour,
1043
1043
The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
1046
int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to)
1046
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to)
1048
1048
switch (l_time->time_type) {
1049
case DRIZZLE_TIMESTAMP_DATETIME:
1049
case MYSQL_TIMESTAMP_DATETIME:
1050
1050
return my_datetime_to_str(l_time, to);
1051
case DRIZZLE_TIMESTAMP_DATE:
1051
case MYSQL_TIMESTAMP_DATE:
1052
1052
return my_date_to_str(l_time, to);
1053
case DRIZZLE_TIMESTAMP_TIME:
1053
case MYSQL_TIMESTAMP_TIME:
1054
1054
return my_time_to_str(l_time, to);
1055
case DRIZZLE_TIMESTAMP_NONE:
1056
case DRIZZLE_TIMESTAMP_ERROR:
1055
case MYSQL_TIMESTAMP_NONE:
1056
case MYSQL_TIMESTAMP_ERROR:
1089
1089
Datetime value in YYYYMMDDHHMMSS format.
1092
int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res,
1093
uint32_t flags, int *was_cut)
1092
int64_t number_to_datetime(int64_t nr, MYSQL_TIME *time_res,
1093
uint flags, int *was_cut)
1095
1095
long part1,part2;
1098
memset(time_res, 0, sizeof(*time_res));
1099
time_res->time_type=DRIZZLE_TIMESTAMP_DATE;
1098
bzero((char*) time_res, sizeof(*time_res));
1099
time_res->time_type=MYSQL_TIMESTAMP_DATE;
1101
1101
if (nr == 0LL || nr >= 10000101000000LL)
1103
time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
1103
time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
1191
Convert DRIZZLE_TIME value to integer in HHMMSS format.
1191
Convert MYSQL_TIME value to integer in HHMMSS format.
1192
1192
This function doesn't take into account time->day member:
1193
1193
it's assumed that days have been converted to hours already.
1196
uint64_t TIME_to_uint64_t_time(const DRIZZLE_TIME *my_time)
1196
uint64_t TIME_to_uint64_t_time(const MYSQL_TIME *my_time)
1198
1198
return (uint64_t) (my_time->hour * 10000UL +
1199
1199
my_time->minute * 100UL +
1219
This function doesn't check that given DRIZZLE_TIME structure members are
1219
This function doesn't check that given MYSQL_TIME structure members are
1220
1220
in valid range. If they are not, return value won't reflect any
1221
1221
valid date either.
1224
uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *my_time)
1224
uint64_t TIME_to_uint64_t(const MYSQL_TIME *my_time)
1226
1226
switch (my_time->time_type) {
1227
case DRIZZLE_TIMESTAMP_DATETIME:
1227
case MYSQL_TIMESTAMP_DATETIME:
1228
1228
return TIME_to_uint64_t_datetime(my_time);
1229
case DRIZZLE_TIMESTAMP_DATE:
1229
case MYSQL_TIMESTAMP_DATE:
1230
1230
return TIME_to_uint64_t_date(my_time);
1231
case DRIZZLE_TIMESTAMP_TIME:
1231
case MYSQL_TIMESTAMP_TIME:
1232
1232
return TIME_to_uint64_t_time(my_time);
1233
case DRIZZLE_TIMESTAMP_NONE:
1234
case DRIZZLE_TIMESTAMP_ERROR:
1233
case MYSQL_TIMESTAMP_NONE:
1234
case MYSQL_TIMESTAMP_ERROR: