~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql-common/my_time.c

  • Committer: Monty Taylor
  • Date: 2008-07-05 18:10:38 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705181038-0ih0nnamu5qrut0y
Fixed prototypes. Cleaned define a little bit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
#include <my_time.h>
17
 
#include <mystrings/m_string.h>
18
 
#include <mystrings/m_ctype.h>
19
 
#include <drizzled/util/test.h>
 
17
#include <m_string.h>
 
18
#include <m_ctype.h>
20
19
/* Windows version of localtime_r() is declared in my_ptrhead.h */
 
20
#include <my_pthread.h>
21
21
 
22
 
uint64_t log_10_int[20]=
 
22
ulonglong log_10_int[20]=
23
23
{
24
24
  1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL,
25
 
  100000000ULL, 1000000000ULL, 10000000000ULL, 100000000000ULL,
26
 
  1000000000000ULL, 10000000000000ULL, 100000000000000ULL,
27
 
  1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
28
 
  1000000000000000000ULL, 10000000000000000000ULL
 
25
  ULL(100000000), ULL(1000000000), ULL(10000000000), ULL(100000000000),
 
26
  ULL(1000000000000), ULL(10000000000000), ULL(100000000000000),
 
27
  ULL(1000000000000000), ULL(10000000000000000), ULL(100000000000000000),
 
28
  ULL(1000000000000000000), ULL(10000000000000000000)
29
29
};
30
30
 
31
31
 
32
32
/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */
33
33
 
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};
36
36
 
37
37
static char time_separator=':';
38
38
 
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};
41
41
 
42
42
/*
43
43
  Offset of system time zone from UTC in seconds used to speed up 
48
48
 
49
49
/* Calc days in one year. works with 0 <= year <= 99 */
50
50
 
51
 
uint32_t calc_days_in_year(uint32_t year)
 
51
uint calc_days_in_year(uint year)
52
52
{
53
53
  return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ?
54
54
          366 : 365);
75
75
    1  error
76
76
*/
77
77
 
78
 
bool check_date(const DRIZZLE_TIME *ltime, bool not_zero_date,
79
 
                   uint32_t flags, int *was_cut)
 
78
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
 
79
                   ulong flags, int *was_cut)
80
80
{
81
81
  if (not_zero_date)
82
82
  {
88
88
          ltime->day != 29)))
89
89
    {
90
90
      *was_cut= 2;
91
 
      return true;
 
91
      return TRUE;
92
92
    }
93
93
  }
94
94
  else if (flags & TIME_NO_ZERO_DATE)
97
97
      We don't set *was_cut here to signal that the problem was a zero date
98
98
      and not an invalid date
99
99
    */
100
 
    return true;
 
100
    return TRUE;
101
101
  }
102
 
  return false;
 
102
  return FALSE;
103
103
}
104
104
 
105
105
 
106
106
/*
107
 
  Convert a timestamp string to a DRIZZLE_TIME value.
 
107
  Convert a timestamp string to a MYSQL_TIME value.
108
108
 
109
109
  SYNOPSIS
110
110
    str_to_datetime()
145
145
   - The hour part must be specified in hour-minute-second order.
146
146
 
147
147
  RETURN VALUES
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
155
155
*/
156
156
 
157
157
#define MAX_DATE_PARTS 8
158
158
 
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)
162
162
{
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;
168
 
  const char *pos, *last_field_pos=NULL;
 
163
  uint field_length, year_length, 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
  const char *pos, *last_field_pos;
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;
 
173
  DBUG_ENTER("str_to_datetime");
 
174
  DBUG_PRINT("ENTER",("str: %.*s",length,str));
173
175
 
174
176
  *was_cut= 0;
175
177
 
176
178
  /* Skip space at start */
177
 
  for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++)
 
179
  for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
178
180
    ;
179
 
  if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str))
 
181
  if (str == end || ! my_isdigit(&my_charset_latin1, *str))
180
182
  {
181
183
    *was_cut= 1;
182
 
    return(DRIZZLE_TIMESTAMP_NONE);
 
184
    DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
183
185
  }
184
186
 
185
187
  is_internal_format= 0;
192
194
    (YYYY-MM-DD,  YYYYMMDD, YYYYYMMDDHHMMSS)
193
195
  */
194
196
  for (pos=str;
195
 
       pos != end && (my_isdigit(&my_charset_utf8_general_ci,*pos) || *pos == 'T');
 
197
       pos != end && (my_isdigit(&my_charset_latin1,*pos) || *pos == 'T');
196
198
       pos++)
197
199
    ;
198
200
 
217
219
        We do this by checking if there is two numbers separated by
218
220
        space in the input.
219
221
      */
220
 
      while (pos < end && !my_isspace(&my_charset_utf8_general_ci, *pos))
 
222
      while (pos < end && !my_isspace(&my_charset_latin1, *pos))
221
223
        pos++;
222
 
      while (pos < end && !my_isdigit(&my_charset_utf8_general_ci, *pos))
 
224
      while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
223
225
        pos++;
224
226
      if (pos == end)
225
227
      {
226
228
        if (flags & TIME_DATETIME_ONLY)
227
229
        {
228
230
          *was_cut= 1;
229
 
          return(DRIZZLE_TIMESTAMP_NONE);   /* Can't be a full datetime */
 
231
          DBUG_RETURN(MYSQL_TIMESTAMP_NONE);   /* Can't be a full datetime */
230
232
        }
231
233
        /* Date field.  Set hour, minutes and seconds to 0 */
232
234
        date[0]= date[1]= date[2]= date[3]= date[4]= 0;
245
247
    2003-03-03 20:00:20 AM
246
248
    20:00:20.000000 AM 03-03-2000
247
249
  */
248
 
  i= cmax((uint) format_position[0], (uint) format_position[1]);
 
250
  i= max((uint) format_position[0], (uint) format_position[1]);
249
251
  set_if_bigger(i, (uint) format_position[2]);
250
252
  allow_space= ((1 << i) | (1 << format_position[6]));
251
253
  allow_space&= (1 | 2 | 4 | 8);
253
255
  not_zero_date= 0;
254
256
  for (i = start_loop;
255
257
       i < MAX_DATE_PARTS-1 && str != end &&
256
 
         my_isdigit(&my_charset_utf8_general_ci,*str);
 
258
         my_isdigit(&my_charset_latin1,*str);
257
259
       i++)
258
260
  {
259
261
    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]) &&
 
262
    ulong tmp_value= (uint) (uchar) (*str++ - '0');
 
263
    while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
262
264
           (!is_internal_format || --field_length))
263
265
    {
264
 
      tmp_value=tmp_value*10 + (uint32_t) (unsigned char) (*str - '0');
 
266
      tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0');
265
267
      str++;
266
268
    }
267
269
    date_len[i]= (uint) (str - start);
268
270
    if (tmp_value > 999999)                     /* Impossible date part */
269
271
    {
270
272
      *was_cut= 1;
271
 
      return(DRIZZLE_TIMESTAMP_NONE);
 
273
      DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
272
274
    }
273
275
    date[i]=tmp_value;
274
276
    not_zero_date|= tmp_value;
297
299
      continue;
298
300
    }
299
301
    while (str != end &&
300
 
           (my_ispunct(&my_charset_utf8_general_ci,*str) ||
301
 
            my_isspace(&my_charset_utf8_general_ci,*str)))
 
302
           (my_ispunct(&my_charset_latin1,*str) ||
 
303
            my_isspace(&my_charset_latin1,*str)))
302
304
    {
303
 
      if (my_isspace(&my_charset_utf8_general_ci,*str))
 
305
      if (my_isspace(&my_charset_latin1,*str))
304
306
      {
305
307
        if (!(allow_space & (1 << i)))
306
308
        {
307
309
          *was_cut= 1;
308
 
          return(DRIZZLE_TIMESTAMP_NONE);
 
310
          DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
309
311
        }
310
312
        found_space= 1;
311
313
      }
326
328
            continue;                           /* Not AM/PM */
327
329
          str+= 2;                              /* Skip AM/PM */
328
330
          /* Skip space after AM/PM */
329
 
          while (str != end && my_isspace(&my_charset_utf8_general_ci,*str))
 
331
          while (str != end && my_isspace(&my_charset_latin1,*str))
330
332
            str++;
331
333
        }
332
334
      }
336
338
  if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
337
339
  {
338
340
    *was_cut= 1;
339
 
    return(DRIZZLE_TIMESTAMP_NONE);          /* Can't be a datetime */
 
341
    DBUG_RETURN(MYSQL_TIMESTAMP_NONE);          /* Can't be a datetime */
340
342
  }
341
343
 
342
344
  str= last_field_pos;
354
356
    if (!year_length)                           /* Year must be specified */
355
357
    {
356
358
      *was_cut= 1;
357
 
      return(DRIZZLE_TIMESTAMP_NONE);
 
359
      DBUG_RETURN(MYSQL_TIMESTAMP_NONE);
358
360
    }
359
361
 
360
362
    l_time->year=               date[(uint) format_position[0]];
370
372
      date[frac_pos]*= (uint) log_10_int[6 - frac_len];
371
373
    l_time->second_part= date[frac_pos];
372
374
 
373
 
    if (format_position[7] != (unsigned char) 255)
 
375
    if (format_position[7] != (uchar) 255)
374
376
    {
375
377
      if (l_time->hour > 12)
376
378
      {
407
409
    {
408
410
      for (; str != end ; str++)
409
411
      {
410
 
        if (!my_isspace(&my_charset_utf8_general_ci, *str))
 
412
        if (!my_isspace(&my_charset_latin1, *str))
411
413
        {
412
414
          not_zero_date= 1;                     /* Give warning */
413
415
          break;
422
424
    goto err;
423
425
 
424
426
  l_time->time_type= (number_of_fields <= 3 ?
425
 
                      DRIZZLE_TIMESTAMP_DATE : DRIZZLE_TIMESTAMP_DATETIME);
 
427
                      MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
426
428
 
427
429
  for (; str != end ; str++)
428
430
  {
429
 
    if (!my_isspace(&my_charset_utf8_general_ci,*str))
 
431
    if (!my_isspace(&my_charset_latin1,*str))
430
432
    {
431
433
      *was_cut= 1;
432
434
      break;
433
435
    }
434
436
  }
435
437
 
436
 
  return(l_time->time_type=
437
 
              (number_of_fields <= 3 ? DRIZZLE_TIMESTAMP_DATE :
438
 
                                       DRIZZLE_TIMESTAMP_DATETIME));
 
438
  DBUG_RETURN(l_time->time_type=
 
439
              (number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE :
 
440
                                       MYSQL_TIMESTAMP_DATETIME));
439
441
 
440
442
err:
441
 
  memset(l_time, 0, sizeof(*l_time));
442
 
  return(DRIZZLE_TIMESTAMP_ERROR);
 
443
  bzero((char*) l_time, sizeof(*l_time));
 
444
  DBUG_RETURN(MYSQL_TIMESTAMP_ERROR);
443
445
}
444
446
 
445
447
 
446
448
/*
447
 
 Convert a time string to a DRIZZLE_TIME struct.
 
449
 Convert a time string to a MYSQL_TIME struct.
448
450
 
449
451
  SYNOPSIS
450
452
   str_to_time()
454
456
                        There may be an optional [.second_part] after seconds
455
457
   length               Length of str
456
458
   l_time               Store result here
457
 
   warning              Set DRIZZLE_TIME_WARN_TRUNCATED flag if the input string
 
459
   warning              Set MYSQL_TIME_WARN_TRUNCATED flag if the input string
458
460
                        was cut during conversion, and/or
459
 
                        DRIZZLE_TIME_WARN_OUT_OF_RANGE flag, if the value is
 
461
                        MYSQL_TIME_WARN_OUT_OF_RANGE flag, if the value is
460
462
                        out of range.
461
463
 
462
464
   NOTES
468
470
     1  error
469
471
*/
470
472
 
471
 
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,
472
474
                    int *warning)
473
475
{
474
 
  uint32_t date[5];
475
 
  uint64_t value;
 
476
  ulong date[5];
 
477
  ulonglong value;
476
478
  const char *end=str+length, *end_of_days;
477
 
  bool found_days,found_hours;
478
 
  uint32_t state;
 
479
  my_bool found_days,found_hours;
 
480
  uint state;
479
481
 
480
482
  l_time->neg=0;
481
483
  *warning= 0;
482
 
  for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++)
 
484
  for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
483
485
    length--;
484
486
  if (str != end && *str == '-')
485
487
  {
494
496
  if (length >= 12)
495
497
  {                                             /* Probably full timestamp */
496
498
    int was_cut;
497
 
    enum enum_drizzle_timestamp_type
 
499
    enum enum_mysql_timestamp_type
498
500
      res= str_to_datetime(str, length, l_time,
499
501
                           (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
500
 
    if ((int) res >= (int) DRIZZLE_TIMESTAMP_ERROR)
 
502
    if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
501
503
    {
502
504
      if (was_cut)
503
 
        *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
504
 
      return res == DRIZZLE_TIMESTAMP_ERROR;
 
505
        *warning|= MYSQL_TIME_WARN_TRUNCATED;
 
506
      return res == MYSQL_TIMESTAMP_ERROR;
505
507
    }
506
508
  }
507
509
 
508
510
  /* 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++)
 
511
  for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
510
512
    value=value*10L + (long) (*str - '0');
511
513
 
512
514
  /* Skip all space after 'days' */
513
515
  end_of_days= str;
514
 
  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++)
515
517
    ;
516
518
 
517
519
  found_days=found_hours=0;
518
520
  if ((uint) (end-str) > 1 && str != end_of_days &&
519
 
      my_isdigit(&my_charset_utf8_general_ci, *str))
 
521
      my_isdigit(&my_charset_latin1, *str))
520
522
  {                                             /* Found days part */
521
 
    date[0]= (uint32_t) value;
 
523
    date[0]= (ulong) value;
522
524
    state= 1;                                   /* Assume next is hours */
523
525
    found_days= 1;
524
526
  }
525
527
  else if ((end-str) > 1 &&  *str == time_separator &&
526
 
           my_isdigit(&my_charset_utf8_general_ci, str[1]))
 
528
           my_isdigit(&my_charset_latin1, str[1]))
527
529
  {
528
530
    date[0]= 0;                                 /* Assume we found hours */
529
 
    date[1]= (uint32_t) value;
 
531
    date[1]= (ulong) value;
530
532
    state=2;
531
533
    found_hours=1;
532
534
    str++;                                      /* skip ':' */
535
537
  {
536
538
    /* String given as one number; assume HHMMSS format */
537
539
    date[0]= 0;
538
 
    date[1]= (uint32_t) (value/10000);
539
 
    date[2]= (uint32_t) (value/100 % 100);
540
 
    date[3]= (uint32_t) (value % 100);
 
540
    date[1]= (ulong) (value/10000);
 
541
    date[2]= (ulong) (value/100 % 100);
 
542
    date[3]= (ulong) (value % 100);
541
543
    state=4;
542
544
    goto fractional;
543
545
  }
545
547
  /* Read hours, minutes and seconds */
546
548
  for (;;)
547
549
  {
548
 
    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++)
549
551
      value=value*10L + (long) (*str - '0');
550
 
    date[state++]= (uint32_t) value;
 
552
    date[state++]= (ulong) value;
551
553
    if (state == 4 || (end-str) < 2 || *str != time_separator ||
552
 
        !my_isdigit(&my_charset_utf8_general_ci,str[1]))
 
554
        !my_isdigit(&my_charset_latin1,str[1]))
553
555
      break;
554
556
    str++;                                      /* Skip time_separator (':') */
555
557
  }
559
561
    /* Fix the date to assume that seconds was given */
560
562
    if (!found_hours && !found_days)
561
563
    {
562
 
      bmove_upp((unsigned char*) (date+4), (unsigned char*) (date+state),
 
564
      bmove_upp((uchar*) (date+4), (uchar*) (date+state),
563
565
                sizeof(long)*(state-1));
564
 
      memset(date, 0, sizeof(long)*(4-state));
 
566
      bzero((uchar*) date, sizeof(long)*(4-state));
565
567
    }
566
568
    else
567
 
      memset(date+state, 0, sizeof(long)*(4-state));
 
569
      bzero((uchar*) (date+state), sizeof(long)*(4-state));
568
570
  }
569
571
 
570
572
fractional:
571
573
  /* Get fractional second part */
572
 
  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
575
  {
574
576
    int field_length= 5;
575
 
    str++; value=(uint) (unsigned char) (*str - '0');
576
 
    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
579
    {
578
580
      if (field_length-- > 0)
579
 
        value= value*10 + (uint) (unsigned char) (*str - '0');
 
581
        value= value*10 + (uint) (uchar) (*str - '0');
580
582
    }
581
583
    if (field_length > 0)
582
584
      value*= (long) log_10_int[field_length];
583
585
    else if (field_length < 0)
584
 
      *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
585
 
    date[4]= (uint32_t) value;
 
586
      *warning|= MYSQL_TIME_WARN_TRUNCATED;
 
587
    date[4]= (ulong) value;
586
588
  }
587
589
  else
588
590
    date[4]=0;
591
593
  /* (may occur as result of %g formatting of time value) */
592
594
  if ((end - str) > 1 &&
593
595
      (*str == 'e' || *str == 'E') &&
594
 
      (my_isdigit(&my_charset_utf8_general_ci, str[1]) ||
 
596
      (my_isdigit(&my_charset_latin1, str[1]) ||
595
597
       ((str[1] == '-' || str[1] == '+') &&
596
598
        (end - str) > 2 &&
597
 
        my_isdigit(&my_charset_utf8_general_ci, str[2]))))
 
599
        my_isdigit(&my_charset_latin1, str[2]))))
598
600
    return 1;
599
601
 
600
602
  if (internal_format_positions[7] != 255)
601
603
  {
602
604
    /* Read a possible AM/PM */
603
 
    while (str != end && my_isspace(&my_charset_utf8_general_ci, *str))
 
605
    while (str != end && my_isspace(&my_charset_latin1, *str))
604
606
      str++;
605
607
    if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
606
608
    {
627
629
  l_time->minute=       date[2];
628
630
  l_time->second=       date[3];
629
631
  l_time->second_part=  date[4];
630
 
  l_time->time_type= DRIZZLE_TIMESTAMP_TIME;
 
632
  l_time->time_type= MYSQL_TIMESTAMP_TIME;
631
633
 
632
 
  /* 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 */
633
635
  if (check_time_range(l_time, warning))
634
636
    return 1;
635
637
  
636
 
  /* 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 */
637
639
  if (str != end)
638
640
  {
639
641
    do
640
642
    {
641
 
      if (!my_isspace(&my_charset_utf8_general_ci,*str))
 
643
      if (!my_isspace(&my_charset_latin1,*str))
642
644
      {
643
 
        *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
 
645
        *warning|= MYSQL_TIME_WARN_TRUNCATED;
644
646
        break;
645
647
      }
646
648
    } while (++str != end);
650
652
 
651
653
 
652
654
/*
653
 
  Check 'time' value to lie in the DRIZZLE_TIME range
 
655
  Check 'time' value to lie in the MYSQL_TIME range
654
656
 
655
657
  SYNOPSIS:
656
658
    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
 
659
    time     pointer to MYSQL_TIME value
 
660
    warning  set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
659
661
 
660
662
  DESCRIPTION
661
663
  If the time value lies outside of the range [-838:59:59, 838:59:59],
662
664
  set it to the closest endpoint of the range and set
663
 
  DRIZZLE_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
 
665
  MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
664
666
 
665
667
  RETURN
666
668
    0        time value is valid, but was possibly truncated
667
669
    1        time value is invalid
668
670
*/
669
671
 
670
 
int check_time_range(DRIZZLE_TIME *my_time, int *warning) 
 
672
int check_time_range(struct st_mysql_time *my_time, int *warning) 
671
673
{
672
 
  int64_t hour;
 
674
  longlong hour;
673
675
 
674
676
  if (my_time->minute >= 60 || my_time->second >= 60)
675
677
    return 1;
685
687
  my_time->minute= TIME_MAX_MINUTE;
686
688
  my_time->second= TIME_MAX_SECOND;
687
689
  my_time->second_part= 0;
688
 
  *warning|= DRIZZLE_TIME_WARN_OUT_OF_RANGE;
 
690
  *warning|= MYSQL_TIME_WARN_OUT_OF_RANGE;
689
691
  return 0;
690
692
}
691
693
 
700
702
{
701
703
  time_t seconds;
702
704
  struct tm *l_time,tm_tmp;
703
 
  DRIZZLE_TIME my_time;
704
 
  bool not_used;
 
705
  MYSQL_TIME my_time;
 
706
  my_bool not_used;
705
707
 
706
708
  seconds= (time_t) time((time_t*) 0);
707
709
  localtime_r(&seconds,&tm_tmp);
728
730
    Year between 1970-2069
729
731
*/
730
732
 
731
 
uint32_t year_2000_handling(uint32_t year)
 
733
uint year_2000_handling(uint year)
732
734
{
733
735
  if ((year=year+1900) < 1900+YY_PART_YEAR)
734
736
    year+=100;
751
753
    Days since 0000-00-00
752
754
*/
753
755
 
754
 
long calc_daynr(uint32_t year,uint32_t month,uint32_t day)
 
756
long calc_daynr(uint year,uint month,uint day)
755
757
{
756
758
  long delsum;
757
759
  int temp;
 
760
  DBUG_ENTER("calc_daynr");
758
761
 
759
762
  if (year == 0 && month == 0 && day == 0)
760
 
    return(0);                          /* Skip errors */
 
763
    DBUG_RETURN(0);                             /* Skip errors */
761
764
  delsum= (long) (365L * year+ 31*(month-1) +day);
762
765
  if (month <= 2)
763
766
      year--;
764
767
  else
765
768
    delsum-= (long) (month*4+23)/10;
766
769
  temp=(int) ((year/100+1)*3)/4;
767
 
  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);
768
773
} /* calc_daynr */
769
774
 
770
775
 
771
776
/*
772
 
  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
773
778
  my_time_t form (number of seconds in UTC since begginning of Unix Epoch).
774
779
 
775
780
  SYNOPSIS
791
796
    Time in UTC seconds since Unix Epoch representation.
792
797
*/
793
798
my_time_t
794
 
my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone,
795
 
                  bool *in_dst_time_gap)
 
799
my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
 
800
                  my_bool *in_dst_time_gap)
796
801
{
797
 
  uint32_t loop;
 
802
  uint loop;
798
803
  time_t tmp= 0;
799
804
  int shift= 0;
800
 
  DRIZZLE_TIME tmp_time;
801
 
  DRIZZLE_TIME *t= &tmp_time;
 
805
  MYSQL_TIME tmp_time;
 
806
  MYSQL_TIME *t= &tmp_time;
802
807
  struct tm *l_time,tm_tmp;
803
808
  long diff, current_timezone;
804
809
 
806
811
    Use temp variable to avoid trashing input data, which could happen in
807
812
    case of shift required for boundary dates processing.
808
813
  */
809
 
  memcpy(&tmp_time, t_src, sizeof(DRIZZLE_TIME));
 
814
  memcpy(&tmp_time, t_src, sizeof(MYSQL_TIME));
810
815
 
811
816
  if (!validate_timestamp_range(t))
812
817
    return 0;
955
960
    else if (diff == -3600)
956
961
      tmp-=t->minute*60 + t->second;            /* Move to previous hour */
957
962
 
958
 
    *in_dst_time_gap= true;
 
963
    *in_dst_time_gap= 1;
959
964
  }
960
965
  *my_timezone= current_timezone;
961
966
 
980
985
} /* my_system_gmt_sec */
981
986
 
982
987
 
983
 
/* 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
989
 
985
 
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
991
{
987
 
  memset(tm, 0, sizeof(*tm));
 
992
  bzero((void*) tm, sizeof(*tm));
988
993
  tm->time_type= time_type;
989
994
}
990
995
 
992
997
/*
993
998
  Functions to convert time/date/datetime value to a string,
994
999
  using default format.
995
 
  This functions don't check that given DRIZZLE_TIME structure members are
 
1000
  This functions don't check that given MYSQL_TIME structure members are
996
1001
  in valid range. If they are not, return value won't reflect any
997
1002
  valid date either. Additionally, make_time doesn't take into
998
1003
  account time->day member: it's assumed that days have been converted
1002
1007
    number of characters written to 'to'
1003
1008
*/
1004
1009
 
1005
 
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
1011
{
1007
 
  uint32_t extra_hours= 0;
1008
 
  return sprintf(to, "%s%02u:%02u:%02u",
 
1012
  uint extra_hours= 0;
 
1013
  return my_sprintf(to, (to, "%s%02u:%02u:%02u",
1009
1014
                         (l_time->neg ? "-" : ""),
1010
1015
                         extra_hours+ l_time->hour,
1011
1016
                         l_time->minute,
1012
 
                         l_time->second);
 
1017
                         l_time->second));
1013
1018
}
1014
1019
 
1015
 
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
1021
{
1017
 
  return sprintf(to, "%04u-%02u-%02u",
 
1022
  return my_sprintf(to, (to, "%04u-%02u-%02u",
1018
1023
                         l_time->year,
1019
1024
                         l_time->month,
1020
 
                         l_time->day);
 
1025
                         l_time->day));
1021
1026
}
1022
1027
 
1023
 
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
1029
{
1025
 
  return sprintf(to, "%04u-%02u-%02u %02u:%02u:%02u",
 
1030
  return my_sprintf(to, (to, "%04u-%02u-%02u %02u:%02u:%02u",
1026
1031
                         l_time->year,
1027
1032
                         l_time->month,
1028
1033
                         l_time->day,
1029
1034
                         l_time->hour,
1030
1035
                         l_time->minute,
1031
 
                         l_time->second);
 
1036
                         l_time->second));
1032
1037
}
1033
1038
 
1034
1039
 
1043
1048
    The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
1044
1049
*/
1045
1050
 
1046
 
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
1052
{
1048
1053
  switch (l_time->time_type) {
1049
 
  case DRIZZLE_TIMESTAMP_DATETIME:
 
1054
  case MYSQL_TIMESTAMP_DATETIME:
1050
1055
    return my_datetime_to_str(l_time, to);
1051
 
  case DRIZZLE_TIMESTAMP_DATE:
 
1056
  case MYSQL_TIMESTAMP_DATE:
1052
1057
    return my_date_to_str(l_time, to);
1053
 
  case DRIZZLE_TIMESTAMP_TIME:
 
1058
  case MYSQL_TIMESTAMP_TIME:
1054
1059
    return my_time_to_str(l_time, to);
1055
 
  case DRIZZLE_TIMESTAMP_NONE:
1056
 
  case DRIZZLE_TIMESTAMP_ERROR:
 
1060
  case MYSQL_TIMESTAMP_NONE:
 
1061
  case MYSQL_TIMESTAMP_ERROR:
1057
1062
    to[0]='\0';
1058
1063
    return 0;
1059
1064
  default:
1060
 
    assert(0);
 
1065
    DBUG_ASSERT(0);
1061
1066
    return 0;
1062
1067
  }
1063
1068
}
1078
1083
 
1079
1084
  DESCRIPTION
1080
1085
    Convert a datetime value of formats YYMMDD, YYYYMMDD, YYMMDDHHMSS,
1081
 
    YYYYMMDDHHMMSS to broken-down DRIZZLE_TIME representation. Return value in
 
1086
    YYYYMMDDHHMMSS to broken-down MYSQL_TIME representation. Return value in
1082
1087
    YYYYMMDDHHMMSS format as side-effect.
1083
1088
 
1084
1089
    This function also checks if datetime value fits in DATETIME range.
1089
1094
    Datetime value in YYYYMMDDHHMMSS format.
1090
1095
*/
1091
1096
 
1092
 
int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res,
1093
 
                            uint32_t flags, int *was_cut)
 
1097
longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
 
1098
                            uint flags, int *was_cut)
1094
1099
{
1095
1100
  long part1,part2;
1096
1101
 
1097
1102
  *was_cut= 0;
1098
 
  memset(time_res, 0, sizeof(*time_res));
1099
 
  time_res->time_type=DRIZZLE_TIMESTAMP_DATE;
 
1103
  bzero((char*) time_res, sizeof(*time_res));
 
1104
  time_res->time_type=MYSQL_TIMESTAMP_DATE;
1100
1105
 
1101
 
  if (nr == 0LL || nr >= 10000101000000LL)
 
1106
  if (nr == LL(0) || nr >= LL(10000101000000))
1102
1107
  {
1103
 
    time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
 
1108
    time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
1104
1109
    goto ok;
1105
1110
  }
1106
1111
  if (nr < 101)
1127
1132
  if (nr < 101000000L)
1128
1133
    goto err;
1129
1134
 
1130
 
  time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
 
1135
  time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
1131
1136
 
1132
 
  if (nr <= (YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
 
1137
  if (nr <= (YY_PART_YEAR-1)*LL(10000000000)+LL(1231235959))
1133
1138
  {
1134
 
    nr= nr + 20000000000000LL;                   /* YYMMDDHHMMSS, 2000-2069 */
 
1139
    nr= nr+LL(20000000000000);                   /* YYMMDDHHMMSS, 2000-2069 */
1135
1140
    goto ok;
1136
1141
  }
1137
 
  if (nr <  YY_PART_YEAR * 10000000000LL + 101000000LL)
 
1142
  if (nr <  YY_PART_YEAR*LL(10000000000)+ LL(101000000))
1138
1143
    goto err;
1139
 
  if (nr <= 991231235959LL)
1140
 
    nr= nr + 19000000000000LL;          /* YYMMDDHHMMSS, 1970-1999 */
 
1144
  if (nr <= LL(991231235959))
 
1145
    nr= nr+LL(19000000000000);          /* YYMMDDHHMMSS, 1970-1999 */
1141
1146
 
1142
1147
 ok:
1143
 
  part1=(long) (nr / 1000000LL);
1144
 
  part2=(long) (nr - (int64_t) part1 * 1000000LL);
 
1148
  part1=(long) (nr/LL(1000000));
 
1149
  part2=(long) (nr - (longlong) part1*LL(1000000));
1145
1150
  time_res->year=  (int) (part1/10000L);  part1%=10000L;
1146
1151
  time_res->month= (int) part1 / 100;
1147
1152
  time_res->day=   (int) part1 % 100;
1157
1162
 
1158
1163
  /* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */
1159
1164
  if (!nr && (flags & TIME_NO_ZERO_DATE))
1160
 
    return -1LL;
 
1165
    return LL(-1);
1161
1166
 
1162
1167
 err:
1163
1168
  *was_cut= 1;
1164
 
  return -1LL;
 
1169
  return LL(-1);
1165
1170
}
1166
1171
 
1167
1172
 
1168
1173
/* Convert time value to integer in YYYYMMDDHHMMSS format */
1169
1174
 
1170
 
uint64_t TIME_to_uint64_t_datetime(const DRIZZLE_TIME *my_time)
 
1175
ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *my_time)
1171
1176
{
1172
 
  return ((uint64_t) (my_time->year * 10000UL +
 
1177
  return ((ulonglong) (my_time->year * 10000UL +
1173
1178
                       my_time->month * 100UL +
1174
 
                       my_time->day) * 1000000ULL +
1175
 
          (uint64_t) (my_time->hour * 10000UL +
 
1179
                       my_time->day) * ULL(1000000) +
 
1180
          (ulonglong) (my_time->hour * 10000UL +
1176
1181
                       my_time->minute * 100UL +
1177
1182
                       my_time->second));
1178
1183
}
1179
1184
 
1180
1185
 
1181
 
/* Convert DRIZZLE_TIME value to integer in YYYYMMDD format */
 
1186
/* Convert MYSQL_TIME value to integer in YYYYMMDD format */
1182
1187
 
1183
 
uint64_t TIME_to_uint64_t_date(const DRIZZLE_TIME *my_time)
 
1188
ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *my_time)
1184
1189
{
1185
 
  return (uint64_t) (my_time->year * 10000UL + my_time->month * 100UL +
 
1190
  return (ulonglong) (my_time->year * 10000UL + my_time->month * 100UL +
1186
1191
                      my_time->day);
1187
1192
}
1188
1193
 
1189
1194
 
1190
1195
/*
1191
 
  Convert DRIZZLE_TIME value to integer in HHMMSS format.
 
1196
  Convert MYSQL_TIME value to integer in HHMMSS format.
1192
1197
  This function doesn't take into account time->day member:
1193
1198
  it's assumed that days have been converted to hours already.
1194
1199
*/
1195
1200
 
1196
 
uint64_t TIME_to_uint64_t_time(const DRIZZLE_TIME *my_time)
 
1201
ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *my_time)
1197
1202
{
1198
 
  return (uint64_t) (my_time->hour * 10000UL +
 
1203
  return (ulonglong) (my_time->hour * 10000UL +
1199
1204
                      my_time->minute * 100UL +
1200
1205
                      my_time->second);
1201
1206
}
1202
1207
 
1203
1208
 
1204
1209
/*
1205
 
  Convert struct DRIZZLE_TIME (date and time split into year/month/day/hour/...
 
1210
  Convert struct MYSQL_TIME (date and time split into year/month/day/hour/...
1206
1211
  to a number in format YYYYMMDDHHMMSS (DATETIME),
1207
1212
  YYYYMMDD (DATE)  or HHMMSS (TIME).
1208
1213
 
1209
1214
  SYNOPSIS
1210
 
    TIME_to_uint64_t()
 
1215
    TIME_to_ulonglong()
1211
1216
 
1212
1217
  DESCRIPTION
1213
1218
    The function is used when we need to convert value of time item
1216
1221
    SELECT ?+1;
1217
1222
 
1218
1223
  NOTE
1219
 
    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
1220
1225
    in valid range. If they are not, return value won't reflect any
1221
1226
    valid date either.
1222
1227
*/
1223
1228
 
1224
 
uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *my_time)
 
1229
ulonglong TIME_to_ulonglong(const MYSQL_TIME *my_time)
1225
1230
{
1226
1231
  switch (my_time->time_type) {
1227
 
  case DRIZZLE_TIMESTAMP_DATETIME:
1228
 
    return TIME_to_uint64_t_datetime(my_time);
1229
 
  case DRIZZLE_TIMESTAMP_DATE:
1230
 
    return TIME_to_uint64_t_date(my_time);
1231
 
  case DRIZZLE_TIMESTAMP_TIME:
1232
 
    return TIME_to_uint64_t_time(my_time);
1233
 
  case DRIZZLE_TIMESTAMP_NONE:
1234
 
  case DRIZZLE_TIMESTAMP_ERROR:
1235
 
    return 0ULL;
 
1232
  case MYSQL_TIMESTAMP_DATETIME:
 
1233
    return TIME_to_ulonglong_datetime(my_time);
 
1234
  case MYSQL_TIMESTAMP_DATE:
 
1235
    return TIME_to_ulonglong_date(my_time);
 
1236
  case MYSQL_TIMESTAMP_TIME:
 
1237
    return TIME_to_ulonglong_time(my_time);
 
1238
  case MYSQL_TIMESTAMP_NONE:
 
1239
  case MYSQL_TIMESTAMP_ERROR:
 
1240
    return ULL(0);
1236
1241
  default:
1237
 
    assert(0);
 
1242
    DBUG_ASSERT(0);
1238
1243
  }
1239
1244
  return 0;
1240
1245
}