31
32
/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */
33
static unsigned char internal_format_positions[]=
34
{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};
36
37
static char time_separator=':';
38
static uint32_t const days_at_timestart=719528; /* daynr at 1970.01.01 */
39
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};
42
43
Offset of system time zone from UTC in seconds used to speed up
144
145
- The hour part must be specified in hour-minute-second order.
147
DRIZZLE_TIMESTAMP_NONE String wasn't a timestamp, like
148
MYSQL_TIMESTAMP_NONE String wasn't a timestamp, like
148
149
[DD [HH:[MM:[SS]]]].fraction.
149
150
l_time is not changed.
150
DRIZZLE_TIMESTAMP_DATE DATE string (YY MM and DD parts ok)
151
DRIZZLE_TIMESTAMP_DATETIME Full timestamp
152
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.
153
154
All elements in l_time is set to 0
156
157
#define MAX_DATE_PARTS 8
158
enum enum_drizzle_timestamp_type
159
str_to_datetime(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
160
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)
162
uint32_t field_length, year_length=4, digits, i, number_of_fields;
163
uint32_t date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
164
uint32_t add_hours= 0, start_loop;
165
uint32_t not_zero_date, allow_space;
166
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;
167
168
const char *pos, *last_field_pos=NULL;
168
169
const char *end=str+length;
169
const unsigned char *format_position;
170
bool found_delimitier= 0, found_space= 0;
171
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;
173
DBUG_ENTER("str_to_datetime");
174
DBUG_PRINT("ENTER",("str: %.*s",length,str));
175
178
/* Skip space at start */
176
for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++)
179
for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
178
if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str))
181
if (str == end || ! my_isdigit(&my_charset_latin1, *str))
181
return(DRIZZLE_TIMESTAMP_NONE);
184
DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
184
187
is_internal_format= 0;
216
219
We do this by checking if there is two numbers separated by
217
220
space in the input.
219
while (pos < end && !my_isspace(&my_charset_utf8_general_ci, *pos))
222
while (pos < end && !my_isspace(&my_charset_latin1, *pos))
221
while (pos < end && !my_isdigit(&my_charset_utf8_general_ci, *pos))
224
while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
225
228
if (flags & TIME_DATETIME_ONLY)
228
return(DRIZZLE_TIMESTAMP_NONE); /* Can't be a full datetime */
231
DBUG_RETURN(MYSQL_TIMESTAMP_NONE); /* Can't be a full datetime */
230
233
/* Date field. Set hour, minutes and seconds to 0 */
231
234
date[0]= date[1]= date[2]= date[3]= date[4]= 0;
252
255
not_zero_date= 0;
253
256
for (i = start_loop;
254
257
i < MAX_DATE_PARTS-1 && str != end &&
255
my_isdigit(&my_charset_utf8_general_ci,*str);
258
my_isdigit(&my_charset_latin1,*str);
258
261
const char *start= str;
259
uint32_t tmp_value= (uint) (unsigned char) (*str++ - '0');
260
while (str != end && my_isdigit(&my_charset_utf8_general_ci,str[0]) &&
262
ulong tmp_value= (uint) (uchar) (*str++ - '0');
263
while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
261
264
(!is_internal_format || --field_length))
263
tmp_value=tmp_value*10 + (uint32_t) (unsigned char) (*str - '0');
266
tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
266
269
date_len[i]= (uint) (str - start);
267
270
if (tmp_value > 999999) /* Impossible date part */
270
return(DRIZZLE_TIMESTAMP_NONE);
273
DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
272
275
date[i]=tmp_value;
273
276
not_zero_date|= tmp_value;
298
301
while (str != end &&
299
(my_ispunct(&my_charset_utf8_general_ci,*str) ||
300
my_isspace(&my_charset_utf8_general_ci,*str)))
302
(my_ispunct(&my_charset_latin1,*str) ||
303
my_isspace(&my_charset_latin1,*str)))
302
if (my_isspace(&my_charset_utf8_general_ci,*str))
305
if (my_isspace(&my_charset_latin1,*str))
304
307
if (!(allow_space & (1 << i)))
307
return(DRIZZLE_TIMESTAMP_NONE);
310
DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
423
426
l_time->time_type= (number_of_fields <= 3 ?
424
DRIZZLE_TIMESTAMP_DATE : DRIZZLE_TIMESTAMP_DATETIME);
427
MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
426
429
for (; str != end ; str++)
428
if (!my_isspace(&my_charset_utf8_general_ci,*str))
431
if (!my_isspace(&my_charset_latin1,*str))
435
return(l_time->time_type=
436
(number_of_fields <= 3 ? DRIZZLE_TIMESTAMP_DATE :
437
DRIZZLE_TIMESTAMP_DATETIME));
438
DBUG_RETURN(l_time->time_type=
439
(number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE :
440
MYSQL_TIMESTAMP_DATETIME));
440
memset(l_time, 0, sizeof(*l_time));
441
return(DRIZZLE_TIMESTAMP_ERROR);
443
bzero((char*) l_time, sizeof(*l_time));
444
DBUG_RETURN(MYSQL_TIMESTAMP_ERROR);
446
Convert a time string to a DRIZZLE_TIME struct.
449
Convert a time string to a MYSQL_TIME struct.
470
bool str_to_time(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
473
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
475
478
const char *end=str+length, *end_of_days;
476
bool found_days,found_hours;
479
my_bool found_days,found_hours;
481
for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++)
484
for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
483
486
if (str != end && *str == '-')
493
496
if (length >= 12)
494
497
{ /* Probably full timestamp */
496
enum enum_drizzle_timestamp_type
499
enum enum_mysql_timestamp_type
497
500
res= str_to_datetime(str, length, l_time,
498
501
(TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
499
if ((int) res >= (int) DRIZZLE_TIMESTAMP_ERROR)
502
if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
502
*warning|= DRIZZLE_TIME_WARN_TRUNCATED;
503
return res == DRIZZLE_TIMESTAMP_ERROR;
505
*warning|= MYSQL_TIME_WARN_TRUNCATED;
506
return res == MYSQL_TIMESTAMP_ERROR;
507
510
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
508
for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++)
511
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
509
512
value=value*10L + (long) (*str - '0');
511
514
/* Skip all space after 'days' */
512
515
end_of_days= str;
513
for (; str != end && my_isspace(&my_charset_utf8_general_ci, str[0]) ; str++)
516
for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++)
516
519
found_days=found_hours=0;
517
520
if ((uint) (end-str) > 1 && str != end_of_days &&
518
my_isdigit(&my_charset_utf8_general_ci, *str))
521
my_isdigit(&my_charset_latin1, *str))
519
522
{ /* Found days part */
520
date[0]= (uint32_t) value;
523
date[0]= (ulong) value;
521
524
state= 1; /* Assume next is hours */
524
527
else if ((end-str) > 1 && *str == time_separator &&
525
my_isdigit(&my_charset_utf8_general_ci, str[1]))
528
my_isdigit(&my_charset_latin1, str[1]))
527
530
date[0]= 0; /* Assume we found hours */
528
date[1]= (uint32_t) value;
531
date[1]= (ulong) value;
531
534
str++; /* skip ':' */
544
547
/* Read hours, minutes and seconds */
547
for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++)
550
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
548
551
value=value*10L + (long) (*str - '0');
549
date[state++]= (uint32_t) value;
552
date[state++]= (ulong) value;
550
553
if (state == 4 || (end-str) < 2 || *str != time_separator ||
551
!my_isdigit(&my_charset_utf8_general_ci,str[1]))
554
!my_isdigit(&my_charset_latin1,str[1]))
553
556
str++; /* Skip time_separator (':') */
558
561
/* Fix the date to assume that seconds was given */
559
562
if (!found_hours && !found_days)
561
bmove_upp((unsigned char*) (date+4), (unsigned char*) (date+state),
564
bmove_upp((uchar*) (date+4), (uchar*) (date+state),
562
565
sizeof(long)*(state-1));
563
memset(date, 0, sizeof(long)*(4-state));
566
bzero((uchar*) date, sizeof(long)*(4-state));
566
memset(date+state, 0, sizeof(long)*(4-state));
569
bzero((uchar*) (date+state), sizeof(long)*(4-state));
570
573
/* Get fractional second part */
571
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_utf8_general_ci,str[1]))
574
if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
573
576
int field_length= 5;
574
str++; value=(uint) (unsigned char) (*str - '0');
575
while (++str != end && my_isdigit(&my_charset_utf8_general_ci, *str))
577
str++; value=(uint) (uchar) (*str - '0');
578
while (++str != end && my_isdigit(&my_charset_latin1, *str))
577
580
if (field_length-- > 0)
578
value= value*10 + (uint) (unsigned char) (*str - '0');
581
value= value*10 + (uint) (uchar) (*str - '0');
580
583
if (field_length > 0)
581
584
value*= (long) log_10_int[field_length];
582
585
else if (field_length < 0)
583
*warning|= DRIZZLE_TIME_WARN_TRUNCATED;
584
date[4]= (uint32_t) value;
586
*warning|= MYSQL_TIME_WARN_TRUNCATED;
587
date[4]= (ulong) value;
590
593
/* (may occur as result of %g formatting of time value) */
591
594
if ((end - str) > 1 &&
592
595
(*str == 'e' || *str == 'E') &&
593
(my_isdigit(&my_charset_utf8_general_ci, str[1]) ||
596
(my_isdigit(&my_charset_latin1, str[1]) ||
594
597
((str[1] == '-' || str[1] == '+') &&
595
598
(end - str) > 2 &&
596
my_isdigit(&my_charset_utf8_general_ci, str[2]))))
599
my_isdigit(&my_charset_latin1, str[2]))))
599
602
if (internal_format_positions[7] != 255)
601
604
/* Read a possible AM/PM */
602
while (str != end && my_isspace(&my_charset_utf8_general_ci, *str))
605
while (str != end && my_isspace(&my_charset_latin1, *str))
604
607
if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
626
629
l_time->minute= date[2];
627
630
l_time->second= date[3];
628
631
l_time->second_part= date[4];
629
l_time->time_type= DRIZZLE_TIMESTAMP_TIME;
632
l_time->time_type= MYSQL_TIMESTAMP_TIME;
631
/* Check if the value is valid and fits into DRIZZLE_TIME range */
634
/* Check if the value is valid and fits into MYSQL_TIME range */
632
635
if (check_time_range(l_time, warning))
635
/* Check if there is garbage at end of the DRIZZLE_TIME specification */
638
/* Check if there is garbage at end of the MYSQL_TIME specification */
640
if (!my_isspace(&my_charset_utf8_general_ci,*str))
643
if (!my_isspace(&my_charset_latin1,*str))
642
*warning|= DRIZZLE_TIME_WARN_TRUNCATED;
645
*warning|= MYSQL_TIME_WARN_TRUNCATED;
645
648
} while (++str != end);
652
Check 'time' value to lie in the DRIZZLE_TIME range
655
Check 'time' value to lie in the MYSQL_TIME range
655
658
check_time_range()
656
time pointer to DRIZZLE_TIME value
657
warning set DRIZZLE_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
659
time pointer to MYSQL_TIME value
660
warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
660
663
If the time value lies outside of the range [-838:59:59, 838:59:59],
661
664
set it to the closest endpoint of the range and set
662
DRIZZLE_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
665
MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
665
668
0 time value is valid, but was possibly truncated
666
669
1 time value is invalid
669
int check_time_range(DRIZZLE_TIME *my_time, int *warning)
672
int check_time_range(struct st_mysql_time *my_time, int *warning)
750
753
Days since 0000-00-00
753
long calc_daynr(uint32_t year,uint32_t month,uint32_t day)
756
long calc_daynr(uint year,uint month,uint day)
760
DBUG_ENTER("calc_daynr");
758
762
if (year == 0 && month == 0 && day == 0)
759
return(0); /* Skip errors */
763
DBUG_RETURN(0); /* Skip errors */
760
764
delsum= (long) (365L * year+ 31*(month-1) +day);
764
768
delsum-= (long) (month*4+23)/10;
765
769
temp=(int) ((year/100+1)*3)/4;
766
return(delsum+(int) year/4-temp);
770
DBUG_PRINT("exit",("year: %d month: %d day: %d -> daynr: %ld",
771
year+(month <= 2),month,day,delsum+year/4-temp));
772
DBUG_RETURN(delsum+(int) year/4-temp);
767
773
} /* calc_daynr */
771
Convert time in DRIZZLE_TIME representation in system time zone to its
777
Convert time in MYSQL_TIME representation in system time zone to its
772
778
my_time_t form (number of seconds in UTC since begginning of Unix Epoch).
790
796
Time in UTC seconds since Unix Epoch representation.
793
my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone,
799
my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
794
800
bool *in_dst_time_gap)
799
DRIZZLE_TIME tmp_time;
800
DRIZZLE_TIME *t= &tmp_time;
806
MYSQL_TIME *t= &tmp_time;
801
807
struct tm *l_time,tm_tmp;
802
808
long diff, current_timezone;
979
985
} /* my_system_gmt_sec */
982
/* Set DRIZZLE_TIME structure to 0000-00-00 00:00:00.000000 */
988
/* Set MYSQL_TIME structure to 0000-00-00 00:00:00.000000 */
984
void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type)
990
void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
986
memset(tm, 0, sizeof(*tm));
992
bzero((void*) tm, sizeof(*tm));
987
993
tm->time_type= time_type;
1001
1007
number of characters written to 'to'
1004
int my_time_to_str(const DRIZZLE_TIME *l_time, char *to)
1010
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
1006
uint32_t extra_hours= 0;
1007
return sprintf(to, "%s%02u:%02u:%02u",
1012
uint extra_hours= 0;
1013
return my_sprintf(to, (to, "%s%02u:%02u:%02u",
1008
1014
(l_time->neg ? "-" : ""),
1009
1015
extra_hours+ l_time->hour,
1010
1016
l_time->minute,
1014
int my_date_to_str(const DRIZZLE_TIME *l_time, char *to)
1020
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
1016
return sprintf(to, "%04u-%02u-%02u",
1022
return my_sprintf(to, (to, "%04u-%02u-%02u",
1022
int my_datetime_to_str(const DRIZZLE_TIME *l_time, char *to)
1028
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
1024
return sprintf(to, "%04u-%02u-%02u %02u:%02u:%02u",
1030
return my_sprintf(to, (to, "%04u-%02u-%02u %02u:%02u:%02u",
1029
1035
l_time->minute,
1042
1048
The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
1045
int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to)
1051
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to)
1047
1053
switch (l_time->time_type) {
1048
case DRIZZLE_TIMESTAMP_DATETIME:
1054
case MYSQL_TIMESTAMP_DATETIME:
1049
1055
return my_datetime_to_str(l_time, to);
1050
case DRIZZLE_TIMESTAMP_DATE:
1056
case MYSQL_TIMESTAMP_DATE:
1051
1057
return my_date_to_str(l_time, to);
1052
case DRIZZLE_TIMESTAMP_TIME:
1058
case MYSQL_TIMESTAMP_TIME:
1053
1059
return my_time_to_str(l_time, to);
1054
case DRIZZLE_TIMESTAMP_NONE:
1055
case DRIZZLE_TIMESTAMP_ERROR:
1060
case MYSQL_TIMESTAMP_NONE:
1061
case MYSQL_TIMESTAMP_ERROR:
1088
1094
Datetime value in YYYYMMDDHHMMSS format.
1091
int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res,
1092
uint32_t flags, int *was_cut)
1097
int64_t number_to_datetime(int64_t nr, MYSQL_TIME *time_res,
1098
uint flags, int *was_cut)
1094
1100
long part1,part2;
1097
memset(time_res, 0, sizeof(*time_res));
1098
time_res->time_type=DRIZZLE_TIMESTAMP_DATE;
1103
bzero((char*) time_res, sizeof(*time_res));
1104
time_res->time_type=MYSQL_TIMESTAMP_DATE;
1100
1106
if (nr == 0LL || nr >= 10000101000000LL)
1102
time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
1108
time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
1190
Convert DRIZZLE_TIME value to integer in HHMMSS format.
1196
Convert MYSQL_TIME value to integer in HHMMSS format.
1191
1197
This function doesn't take into account time->day member:
1192
1198
it's assumed that days have been converted to hours already.
1195
uint64_t TIME_to_uint64_t_time(const DRIZZLE_TIME *my_time)
1201
uint64_t TIME_to_uint64_t_time(const MYSQL_TIME *my_time)
1197
1203
return (uint64_t) (my_time->hour * 10000UL +
1198
1204
my_time->minute * 100UL +
1218
This function doesn't check that given DRIZZLE_TIME structure members are
1224
This function doesn't check that given MYSQL_TIME structure members are
1219
1225
in valid range. If they are not, return value won't reflect any
1220
1226
valid date either.
1223
uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *my_time)
1229
uint64_t TIME_to_uint64_t(const MYSQL_TIME *my_time)
1225
1231
switch (my_time->time_type) {
1226
case DRIZZLE_TIMESTAMP_DATETIME:
1232
case MYSQL_TIMESTAMP_DATETIME:
1227
1233
return TIME_to_uint64_t_datetime(my_time);
1228
case DRIZZLE_TIMESTAMP_DATE:
1234
case MYSQL_TIMESTAMP_DATE:
1229
1235
return TIME_to_uint64_t_date(my_time);
1230
case DRIZZLE_TIMESTAMP_TIME:
1236
case MYSQL_TIMESTAMP_TIME:
1231
1237
return TIME_to_uint64_t_time(my_time);
1232
case DRIZZLE_TIMESTAMP_NONE:
1233
case DRIZZLE_TIMESTAMP_ERROR:
1238
case MYSQL_TIMESTAMP_NONE:
1239
case MYSQL_TIMESTAMP_ERROR: