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