96
96
next week is week 1.
99
uint32_t calc_week(DRIZZLE_TIME *l_time, uint32_t week_behaviour, uint32_t *year)
99
uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year)
102
102
ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day);
103
103
ulong first_daynr=calc_daynr(l_time->year,1,1);
104
104
bool monday_first= test(week_behaviour & WEEK_MONDAY_FIRST);
105
105
bool week_year= test(week_behaviour & WEEK_YEAR);
106
106
bool first_weekday= test(week_behaviour & WEEK_FIRST_WEEKDAY);
108
uint32_t weekday=calc_weekday(first_daynr, !monday_first);
108
uint weekday=calc_weekday(first_daynr, !monday_first);
109
109
*year=l_time->year;
111
111
if (l_time->month == 1 && l_time->day <= 7-weekday)
139
139
/* Change a daynr to year, month and day */
140
140
/* Daynr 0 is returned as date 00.00.00 */
142
void get_date_from_daynr(long daynr,uint32_t *ret_year,uint32_t *ret_month,
142
void get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month,
145
uint32_t year,temp,leap_day,day_of_year,days_in_year;
146
unsigned char *month_pos;
145
uint year,temp,leap_day,day_of_year,days_in_year;
147
DBUG_ENTER("get_date_from_daynr");
148
149
if (daynr <= 365L || daynr >= 3652500)
149
150
{ /* Fix if wrong daynr */
213
Convert a timestamp string to a DRIZZLE_TIME value and produce a warning
214
Convert a timestamp string to a MYSQL_TIME value and produce a warning
214
215
if string was truncated during conversion.
217
218
See description of str_to_datetime() for more information.
220
enum enum_drizzle_timestamp_type
221
str_to_datetime_with_warn(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
222
str_to_datetime_with_warn(const char *str, uint length, MYSQL_TIME *l_time,
225
226
THD *thd= current_thd;
226
enum enum_drizzle_timestamp_type ts_type;
227
timestamp_type ts_type;
228
229
ts_type= str_to_datetime(str, length, l_time,
229
230
(flags | (thd->variables.sql_mode &
230
231
(MODE_INVALID_DATES |
231
232
MODE_NO_ZERO_DATE))),
233
if (was_cut || ts_type <= DRIZZLE_TIMESTAMP_ERROR)
234
make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
235
str, length, ts_type, NULL);
234
if (was_cut || ts_type <= MYSQL_TIMESTAMP_ERROR)
235
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
236
str, length, ts_type, NullS);
241
Convert a datetime from broken-down DRIZZLE_TIME representation to corresponding
242
Convert a datetime from broken-down MYSQL_TIME representation to corresponding
276
Convert a time string to a DRIZZLE_TIME struct and produce a warning
277
Convert a time string to a MYSQL_TIME struct and produce a warning
277
278
if string was cut during conversion.
280
281
See str_to_time() for more info.
283
str_to_time_with_warn(const char *str, uint32_t length, DRIZZLE_TIME *l_time)
284
str_to_time_with_warn(const char *str, uint length, MYSQL_TIME *l_time)
286
287
bool ret_val= str_to_time(str, length, l_time, &warning);
287
288
if (ret_val || warning)
288
make_truncated_value_warning(current_thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
289
str, length, DRIZZLE_TIMESTAMP_TIME, NULL);
289
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
290
str, length, MYSQL_TIMESTAMP_TIME, NullS);
307
308
to->second= (int) from->tm_sec;
310
void calc_time_from_sec(DRIZZLE_TIME *to, long seconds, long microseconds)
311
void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds)
313
314
// to->neg is not cleared, it may already be set to a useful value
314
to->time_type= DRIZZLE_TIMESTAMP_TIME;
315
to->time_type= MYSQL_TIMESTAMP_TIME;
352
bool parse_date_time_format(enum enum_drizzle_timestamp_type format_type,
353
const char *format, uint32_t format_length,
353
bool parse_date_time_format(timestamp_type format_type,
354
const char *format, uint format_length,
354
355
DATE_TIME_FORMAT *date_time_format)
356
uint32_t offset= 0, separators= 0;
357
uint offset= 0, separators= 0;
357
358
const char *ptr= format, *format_str;
358
359
const char *end= ptr+format_length;
359
unsigned char *dt_pos= date_time_format->positions;
360
uchar *dt_pos= date_time_format->positions;
360
361
/* need_p is set if we are using AM/PM format */
361
362
bool need_p= 0, allow_separator= 0;
362
uint32_t part_map= 0, separator_map= 0;
363
ulong part_map= 0, separator_map= 0;
363
364
const char *parts[16];
365
366
date_time_format->time_separator= 0;
444
445
allow_separator= 0; // Don't allow two separators
446
447
/* Store in separator_map which parts are punct characters */
447
if (my_ispunct(&my_charset_utf8_general_ci, *ptr))
448
if (my_ispunct(&my_charset_latin1, *ptr))
448
449
separator_map|= (ulong) 1 << (offset-1);
449
else if (!my_isspace(&my_charset_utf8_general_ci, *ptr))
450
else if (!my_isspace(&my_charset_latin1, *ptr))
467
468
The last test is to ensure that %p is used if and only if
470
if ((format_type == DRIZZLE_TIMESTAMP_DATETIME &&
471
!test_all_bits(part_map, (uint32_t) (1 | 2 | 4 | 8 | 16 | 32))) ||
472
(format_type == DRIZZLE_TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
473
(format_type == DRIZZLE_TIMESTAMP_TIME &&
474
!test_all_bits(part_map, (uint32_t) (8 | 16 | 32))) ||
471
if ((format_type == MYSQL_TIMESTAMP_DATETIME &&
472
!test_all_bits(part_map, (1 | 2 | 4 | 8 | 16 | 32))) ||
473
(format_type == MYSQL_TIMESTAMP_DATE && part_map != (1 | 2 | 4)) ||
474
(format_type == MYSQL_TIMESTAMP_TIME &&
475
!test_all_bits(part_map, 8 | 16 | 32)) ||
475
476
!allow_separator || // %option should be last
476
477
(need_p && dt_pos[6] +1 != dt_pos[7]) ||
477
478
(need_p ^ (dt_pos[7] != 255)))
527
528
if (format_length == 6 && !need_p &&
528
529
!my_strnncoll(&my_charset_bin,
529
(const unsigned char *) format, 6,
530
(const unsigned char *) format_str, 6))
530
(const uchar *) format, 6,
531
(const uchar *) format_str, 6))
532
533
if (separator_map == (1 | 2))
534
if (format_type == DRIZZLE_TIMESTAMP_TIME)
535
if (format_type == MYSQL_TIMESTAMP_TIME)
536
537
if (*(format+2) != *(format+5))
550
551
if ((format_length == 12 && !need_p &&
551
552
!my_strnncoll(&my_charset_bin,
552
(const unsigned char *) format, 12,
553
(const unsigned char*) known_date_time_formats[INTERNAL_FORMAT].datetime_format,
553
(const uchar *) format, 12,
554
(const uchar*) known_date_time_formats[INTERNAL_FORMAT].datetime_format,
555
556
(separators == 5 && separator_map == (1 | 2 | 8 | 16)))
562
563
return 1; // Error
628
629
/* Put format string after current pos */
629
630
new_format->format.str= (char*) (new_format+1);
630
memcpy(new_format->positions, format->positions,
631
memcpy((char*) new_format->positions, (char*) format->positions,
631
632
sizeof(format->positions));
632
633
new_format->time_separator= format->time_separator;
633
634
/* We make the string null terminated for easy printf in SHOW VARIABLES */
634
memcpy(new_format->format.str, format->format.str,
635
memcpy((char*) new_format->format.str, format->format.str,
635
636
format->format.length);
636
637
new_format->format.str[format->format.length]= 0;
637
638
new_format->format.length= format->format.length;
659
660
const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
660
enum enum_drizzle_timestamp_type type)
663
case DRIZZLE_TIMESTAMP_DATE:
664
case MYSQL_TIMESTAMP_DATE:
664
665
return format->date_format;
665
case DRIZZLE_TIMESTAMP_DATETIME:
666
case MYSQL_TIMESTAMP_DATETIME:
666
667
return format->datetime_format;
667
case DRIZZLE_TIMESTAMP_TIME:
668
case MYSQL_TIMESTAMP_TIME:
668
669
return format->time_format;
670
assert(0); // Impossible
671
DBUG_ASSERT(0); // Impossible
680
681
MySQL doesn't support comparing of date/time/datetime strings that
681
682
are not in arbutary order as dates are compared as strings in some
683
This functions don't check that given DRIZZLE_TIME structure members are
684
This functions don't check that given MYSQL_TIME structure members are
684
685
in valid range. If they are not, return value won't reflect any
685
686
valid date either. Additionally, make_time doesn't take into
686
687
account time->day member: it's assumed that days have been converted
688
689
****************************************************************************/
690
691
void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
691
const DRIZZLE_TIME *l_time, String *str)
692
const MYSQL_TIME *l_time, String *str)
693
uint32_t length= (uint) my_time_to_str(l_time, (char*) str->ptr());
694
uint length= (uint) my_time_to_str(l_time, (char*) str->ptr());
694
695
str->length(length);
695
696
str->set_charset(&my_charset_bin);
699
700
void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
700
const DRIZZLE_TIME *l_time, String *str)
701
const MYSQL_TIME *l_time, String *str)
702
uint32_t length= (uint) my_date_to_str(l_time, (char*) str->ptr());
703
uint length= (uint) my_date_to_str(l_time, (char*) str->ptr());
703
704
str->length(length);
704
705
str->set_charset(&my_charset_bin);
708
709
void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
709
const DRIZZLE_TIME *l_time, String *str)
710
const MYSQL_TIME *l_time, String *str)
711
uint32_t length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
712
uint length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
712
713
str->length(length);
713
714
str->set_charset(&my_charset_bin);
717
void make_truncated_value_warning(THD *thd, DRIZZLE_ERROR::enum_warning_level level,
718
void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
718
719
const char *str_val,
720
enum enum_drizzle_timestamp_type time_type,
720
uint str_length, timestamp_type time_type,
721
721
const char *field_name)
723
char warn_buff[DRIZZLE_ERRMSG_SIZE];
723
char warn_buff[MYSQL_ERRMSG_SIZE];
724
724
const char *type_str;
725
CHARSET_INFO *cs= &my_charset_utf8_general_ci;
725
CHARSET_INFO *cs= &my_charset_latin1;
727
String str(buff,(uint32_t) sizeof(buff), system_charset_info);
727
String str(buff,(uint32) sizeof(buff), system_charset_info);
728
728
str.copy(str_val, str_length, system_charset_info);
729
729
str[str_length]= 0; // Ensure we have end 0 for snprintf
731
731
switch (time_type) {
732
case DRIZZLE_TIMESTAMP_DATE:
732
case MYSQL_TIMESTAMP_DATE:
733
733
type_str= "date";
735
case DRIZZLE_TIMESTAMP_TIME:
735
case MYSQL_TIMESTAMP_TIME:
736
736
type_str= "time";
738
case DRIZZLE_TIMESTAMP_DATETIME: // FALLTHROUGH
738
case MYSQL_TIMESTAMP_DATETIME: // FALLTHROUGH
740
740
type_str= "datetime";
786
786
case INTERVAL_DAY_MINUTE:
787
787
case INTERVAL_DAY_HOUR:
789
int64_t sec, days, daynr, microseconds, extra_sec;
790
ltime->time_type= DRIZZLE_TIMESTAMP_DATETIME; // Return full date
789
longlong sec, days, daynr, microseconds, extra_sec;
790
ltime->time_type= MYSQL_TIMESTAMP_DATETIME; // Return full date
791
791
microseconds= ltime->second_part + sign*interval.second_part;
792
792
extra_sec= microseconds/1000000L;
793
793
microseconds= microseconds%1000000L;
795
795
sec=((ltime->day-1)*3600*24L+ltime->hour*3600+ltime->minute*60+
797
sign* (int64_t) (interval.day*3600*24L +
798
interval.hour*3600L+interval.minute*60L+
797
sign* (longlong) (interval.day*3600*24L +
798
interval.hour*LL(3600)+interval.minute*LL(60)+
799
799
interval.second))+ extra_sec;
800
800
if (microseconds < 0)
802
microseconds+= 1000000L;
802
microseconds+= LL(1000000);
805
days= sec/(3600*24L);
805
days= sec/(3600*LL(24));
806
sec-= days*3600*LL(24);
812
812
ltime->second_part= (uint) microseconds;
813
813
ltime->second= (uint) (sec % 60);
815
815
ltime->hour= (uint) (sec/3600);
816
816
daynr= calc_daynr(ltime->year,ltime->month,1) + days;
817
817
/* Day number from year 0 to 9999-12-31 */
818
if ((uint64_t) daynr > MAX_DAY_NUMBER)
818
if ((ulonglong) daynr > MAX_DAY_NUMBER)
819
819
goto invalid_date;
820
820
get_date_from_daynr((long) daynr, <ime->year, <ime->month,
901
calc_time_diff(DRIZZLE_TIME *l_time1, DRIZZLE_TIME *l_time2, int l_sign, int64_t *seconds_out,
901
calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, longlong *seconds_out,
902
902
long *microseconds_out)
906
int64_t microseconds;
906
longlong microseconds;
909
We suppose that if first argument is DRIZZLE_TIMESTAMP_TIME
909
We suppose that if first argument is MYSQL_TIMESTAMP_TIME
910
910
the second argument should be TIMESTAMP_TIME also.
911
911
We should check it before calc_time_diff call.
913
if (l_time1->time_type == DRIZZLE_TIMESTAMP_TIME) // Time value
913
if (l_time1->time_type == MYSQL_TIMESTAMP_TIME) // Time value
914
914
days= (long)l_time1->day - l_sign * (long)l_time2->day;
917
917
days= calc_daynr((uint) l_time1->year,
918
918
(uint) l_time1->month,
919
919
(uint) l_time1->day);
920
if (l_time2->time_type == DRIZZLE_TIMESTAMP_TIME)
920
if (l_time2->time_type == MYSQL_TIMESTAMP_TIME)
921
921
days-= l_sign * (long)l_time2->day;
923
923
days-= l_sign*calc_daynr((uint) l_time2->year,
925
925
(uint) l_time2->day);
928
microseconds= ((int64_t)days*86400L +
929
(int64_t)(l_time1->hour*3600L +
928
microseconds= ((longlong)days*LL(86400) +
929
(longlong)(l_time1->hour*3600L +
930
930
l_time1->minute*60L +
931
931
l_time1->second) -
932
l_sign*(int64_t)(l_time2->hour*3600L +
932
l_sign*(longlong)(l_time2->hour*3600L +
933
933
l_time2->minute*60L +
934
l_time2->second)) * 1000000L +
935
(int64_t)l_time1->second_part -
936
l_sign*(int64_t)l_time2->second_part;
934
l_time2->second)) * LL(1000000) +
935
(longlong)l_time1->second_part -
936
l_sign*(longlong)l_time2->second_part;
939
939
if (microseconds < 0)
969
my_time_compare(DRIZZLE_TIME *a, DRIZZLE_TIME *b)
969
my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
971
uint64_t a_t= TIME_to_uint64_t_datetime(a);
972
uint64_t b_t= TIME_to_uint64_t_datetime(b);
971
my_ulonglong a_t= TIME_to_ulonglong_datetime(a);
972
my_ulonglong b_t= TIME_to_ulonglong_datetime(b);