321
262
to->second_part= microseconds;
326
Parse a format string specification
329
parse_date_time_format()
330
format_type Format of string (time, date or datetime)
331
format_str String to parse
332
format_length Length of string
333
date_time_format Format to fill in
336
Fills in date_time_format->positions for all date time parts.
338
positions marks the position for a datetime element in the format string.
339
The position array elements are in the following order:
340
YYYY-DD-MM HH-MM-DD.FFFFFF AM
343
If positions[0]= 5, it means that year will be the forth element to
344
read from the parsed date string.
351
bool parse_date_time_format(enum enum_drizzle_timestamp_type format_type,
352
const char *format, uint32_t format_length,
353
DATE_TIME_FORMAT *date_time_format)
355
uint32_t offset= 0, separators= 0;
356
const char *ptr= format, *format_str;
357
const char *end= ptr+format_length;
358
unsigned char *dt_pos= date_time_format->positions;
359
/* need_p is set if we are using AM/PM format */
360
bool need_p= 0, allow_separator= 0;
361
uint32_t part_map= 0, separator_map= 0;
362
const char *parts[16];
364
date_time_format->time_separator= 0;
365
date_time_format->flag= 0; // For future
368
Fill position with 'dummy' arguments to found out if a format tag is
369
used twice (This limit's the format to 255 characters, but this is ok)
371
dt_pos[0]= dt_pos[1]= dt_pos[2]= dt_pos[3]=
372
dt_pos[4]= dt_pos[5]= dt_pos[6]= dt_pos[7]= 255;
374
for (; ptr != end; ptr++)
376
if (*ptr == '%' && ptr+1 != end)
395
need_p= 1; // Need AM/PM
410
if (dt_pos[5] != offset-1 || ptr[-2] != '.')
411
return 1; // Wrong usage of %f
414
if (offset == 0) // Can't be first
419
return 1; // Unknown controll char
421
if (dt_pos[position] != 255) // Don't allow same tag twice
423
parts[position]= ptr-1;
426
If switching from time to date, ensure that all time parts
429
if (part_map && position <= 2 && !(part_map & (1 | 2 | 4)))
431
part_map|= UINT32_C(1) << position;
432
dt_pos[position]= offset++;
438
Don't allow any characters in format as this could easily confuse
441
if (!allow_separator)
442
return 1; // No separator here
443
allow_separator= 0; // Don't allow two separators
445
/* Store in separator_map which parts are punct characters */
446
if (my_ispunct(&my_charset_utf8_general_ci, *ptr))
447
separator_map|= (ulong) 1 << (offset-1);
448
else if (!my_isspace(&my_charset_utf8_general_ci, *ptr))
453
/* If no %f, specify it after seconds. Move %p up, if necessary */
454
if ((part_map & 32) && !(part_map & 64))
456
dt_pos[6]= dt_pos[5] +1;
457
parts[6]= parts[5]; // For later test in (need_p)
458
if (dt_pos[6] == dt_pos[7]) // Move %p one step up if used
463
Check that we have not used a non legal format specifier and that all
464
format specifiers have been used
466
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))) ||
474
!allow_separator || // %option should be last
475
(need_p && dt_pos[6] +1 != dt_pos[7]) ||
476
(need_p ^ (dt_pos[7] != 255)))
479
if (dt_pos[6] != 255) // If fractional seconds
481
/* remove fractional seconds from later tests */
482
uint32_t pos= dt_pos[6] -1;
483
/* Remove separator before %f from sep map */
484
separator_map= ((separator_map & ((ulong) (1 << pos)-1)) |
485
((separator_map & ~((ulong) (1 << pos)-1)) >> 1));
488
separators--; // There is always a separator
489
need_p= 1; // force use of separators
494
Remove possible separator before %p from sep_map
495
(This can either be at position 3, 4, 6 or 7) h.m.d.%f %p
497
if (dt_pos[7] != 255)
499
if (need_p && parts[7] != parts[6]+2)
503
Calculate if %p is in first or last part of the datetime field
505
At this point we have either %H-%i-%s %p 'year parts' or
506
'year parts' &H-%i-%s %p" as %f was removed above
508
offset= dt_pos[6] <= 3 ? 3 : 6;
509
/* Remove separator before %p from sep map */
510
separator_map= ((separator_map & ((ulong) (1 << offset)-1)) |
511
((separator_map & ~((ulong) (1 << offset)-1)) >> 1));
514
switch (format_type) {
515
case DRIZZLE_TIMESTAMP_DATE:
516
format_str= known_date_time_formats[INTERNAL_FORMAT].date_format;
518
case DRIZZLE_TIMESTAMP_TIME:
520
format_str=known_date_time_formats[INTERNAL_FORMAT].time_format;
523
If there is no separators, allow the internal format as we can read
524
this. If separators are used, they must be between each part
526
if (format_length == 6 && !need_p &&
527
!my_strnncoll(&my_charset_bin,
528
(const unsigned char *) format, 6,
529
(const unsigned char *) format_str, 6))
531
if (separator_map == (1 | 2))
533
if (format_type == DRIZZLE_TIMESTAMP_TIME)
535
if (*(format+2) != *(format+5))
537
/* Store the character used for time formats */
538
date_time_format->time_separator= *(format+2);
543
case DRIZZLE_TIMESTAMP_DATETIME:
545
If there is no separators, allow the internal format as we can read
546
this. If separators are used, they must be between each part.
547
Between DATE and TIME we also allow space as separator
549
if ((format_length == 12 && !need_p &&
550
!my_strnncoll(&my_charset_bin,
551
(const unsigned char *) format, 12,
552
(const unsigned char*) known_date_time_formats[INTERNAL_FORMAT].datetime_format,
554
(separators == 5 && separator_map == (1 | 2 | 8 | 16)))
566
Create a DATE_TIME_FORMAT object from a format string specification
569
date_time_format_make()
570
format_type Format to parse (time, date or datetime)
571
format_str String to parse
572
format_length Length of string
575
The returned object should be freed with free()
583
*date_time_format_make(enum enum_drizzle_timestamp_type format_type,
584
const char *format_str, uint32_t format_length)
586
DATE_TIME_FORMAT tmp;
588
if (format_length && format_length < 255 &&
589
!parse_date_time_format(format_type, format_str,
590
format_length, &tmp))
592
tmp.format.str= (char*) format_str;
593
tmp.format.length= format_length;
594
return date_time_format_copy((THD *)0, &tmp);
601
Create a copy of a DATE_TIME_FORMAT object
604
date_and_time_format_copy()
605
thd Set if variable should be allocated in thread mem
606
format format to copy
609
The returned object should be freed with free()
616
DATE_TIME_FORMAT *date_time_format_copy(THD *thd, DATE_TIME_FORMAT *format)
618
DATE_TIME_FORMAT *new_format;
619
ulong length= sizeof(*format) + format->format.length + 1;
622
new_format= (DATE_TIME_FORMAT *) thd->alloc(length);
624
new_format= (DATE_TIME_FORMAT *) my_malloc(length, MYF(MY_WME));
627
/* Put format string after current pos */
628
new_format->format.str= (char*) (new_format+1);
629
memcpy(new_format->positions, format->positions,
630
sizeof(format->positions));
631
new_format->time_separator= format->time_separator;
632
/* We make the string null terminated for easy printf in SHOW VARIABLES */
633
memcpy(new_format->format.str, format->format.str,
634
format->format.length);
635
new_format->format.str[format->format.length]= 0;
636
new_format->format.length= format->format.length;
642
KNOWN_DATE_TIME_FORMAT known_date_time_formats[6]=
644
{"USA", "%m.%d.%Y", "%Y-%m-%d %H.%i.%s", "%h:%i:%s %p" },
645
{"JIS", "%Y-%m-%d", "%Y-%m-%d %H:%i:%s", "%H:%i:%s" },
646
{"ISO", "%Y-%m-%d", "%Y-%m-%d %H:%i:%s", "%H:%i:%s" },
647
{"EUR", "%d.%m.%Y", "%Y-%m-%d %H.%i.%s", "%H.%i.%s" },
648
{"INTERNAL", "%Y%m%d", "%Y%m%d%H%i%s", "%H%i%s" },
654
Return format string according format name.
655
If name is unknown, result is NULL
658
const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
659
enum enum_drizzle_timestamp_type type)
662
case DRIZZLE_TIMESTAMP_DATE:
663
return format->date_format;
664
case DRIZZLE_TIMESTAMP_DATETIME:
665
return format->datetime_format;
666
case DRIZZLE_TIMESTAMP_TIME:
667
return format->time_format;
669
assert(0); // Impossible
674
/****************************************************************************
675
Functions to create default time/date/datetime strings
678
For the moment the DATE_TIME_FORMAT argument is ignored becasue
679
MySQL doesn't support comparing of date/time/datetime strings that
680
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
683
in valid range. If they are not, return value won't reflect any
684
valid date either. Additionally, make_time doesn't take into
685
account time->day member: it's assumed that days have been converted
687
****************************************************************************/
689
void make_time(const DATE_TIME_FORMAT *format __attribute__((unused)),
690
const DRIZZLE_TIME *l_time, String *str)
692
uint32_t length= (uint) my_time_to_str(l_time, (char*) str->ptr());
694
str->set_charset(&my_charset_bin);
698
void make_date(const DATE_TIME_FORMAT *format __attribute__((unused)),
699
const DRIZZLE_TIME *l_time, String *str)
701
uint32_t length= (uint) my_date_to_str(l_time, (char*) str->ptr());
703
str->set_charset(&my_charset_bin);
707
void make_datetime(const DATE_TIME_FORMAT *format __attribute__((unused)),
708
const DRIZZLE_TIME *l_time, String *str)
710
uint32_t length= (uint) my_datetime_to_str(l_time, (char*) str->ptr());
712
str->set_charset(&my_charset_bin);
716
void make_truncated_value_warning(THD *thd, DRIZZLE_ERROR::enum_warning_level level,
265
void make_time(const DRIZZLE_TIME *l_time, String *str)
267
str->alloc(MAX_DATE_STRING_REP_LENGTH);
268
uint32_t length= (uint32_t) my_time_to_str(l_time, str->c_ptr());
270
str->set_charset(&my_charset_bin);
274
void make_date(const DRIZZLE_TIME *l_time, String *str)
276
str->alloc(MAX_DATE_STRING_REP_LENGTH);
277
uint32_t length= (uint32_t) my_date_to_str(l_time, str->c_ptr());
279
str->set_charset(&my_charset_bin);
283
void make_datetime(const DRIZZLE_TIME *l_time, String *str)
285
str->alloc(MAX_DATE_STRING_REP_LENGTH);
286
uint32_t length= (uint32_t) my_datetime_to_str(l_time, str->c_ptr());
288
str->set_charset(&my_charset_bin);
292
void make_truncated_value_warning(Session *session, DRIZZLE_ERROR::enum_warning_level level,
717
293
const char *str_val,
718
294
uint32_t str_length,
719
295
enum enum_drizzle_timestamp_type time_type,