~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/my_time.c

  • Committer: Brian Aker
  • Date: 2008-07-14 16:24:25 UTC
  • Revision ID: brian@tangent.org-20080714162425-juw3vw221gs9kysh
Cleanup around intptr_t

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