~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/drizzle_time.cc

  • Committer: lbieber
  • Date: 2010-10-02 19:48:35 UTC
  • mfrom: (1730.6.19 drizzle-make-lcov)
  • Revision ID: lbieber@orisndriz08-20101002194835-q5zd9qc4lvx1xnfo
Merge Hartmut - clean up lex, now require flex to build, also "make lcov" improvements

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
 You should have received a copy of the GNU General Public License
13
13
 along with this program; if not, write to the Free Software
14
 
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
#include "config.h"
17
17
 
18
 
#include "drizzled/type/time.h"
19
 
 
20
 
#include <drizzled/util/gmtime.h>
 
18
#include "drizzled/drizzle_time.h"
21
19
 
22
20
#include "drizzled/internal/m_string.h"
23
21
#include "drizzled/charset_info.h"
24
22
#include <drizzled/util/test.h>
25
23
#include "drizzled/definitions.h"
26
 
#include <drizzled/sql_string.h>
27
24
 
28
25
#include <cstdio>
29
26
#include <algorithm>
33
30
namespace drizzled
34
31
{
35
32
 
36
 
static int check_time_range(type::Time *my_time, int *warning);
 
33
static int check_time_range(DRIZZLE_TIME *my_time, int *warning);
37
34
 
38
35
/* Windows version of localtime_r() is declared in my_ptrhead.h */
39
36
 
72
69
          366 : 365);
73
70
}
74
71
 
75
 
 
76
 
namespace type {
77
72
/**
78
73
  @brief Check datetime value for validity according to flags.
79
74
 
80
75
  @param[in]  ltime          Date to check.
81
76
  @param[in]  not_zero_date  ltime is not the zero date
82
77
  @param[in]  flags          flags to check
83
 
                             (see store() flags in drizzle_time.h)
 
78
                             (see str_to_datetime() flags in drizzle_time.h)
84
79
  @param[out] was_cut        set to 2 if value was invalid according to flags.
85
80
                             (Feb 29 in non-leap etc.)  This remains unchanged
86
81
                             if value is not invalid.
87
82
 
88
83
  @details Here we assume that year and month is ok!
89
84
    If month is 0 we allow any date. (This only happens if we allow zero
90
 
    date parts in store())
 
85
    date parts in str_to_datetime())
91
86
    Disallow dates with zero year and non-zero month and/or day.
92
87
 
93
88
  @return
95
90
    1  error
96
91
*/
97
92
 
98
 
bool Time::check(bool not_zero_date, uint32_t flags, type::cut_t &was_cut) const
 
93
bool check_date(const DRIZZLE_TIME *ltime, bool not_zero_date,
 
94
                   uint32_t flags, int *was_cut)
99
95
{
100
96
  if (not_zero_date)
101
97
  {
102
98
    if ((((flags & TIME_NO_ZERO_IN_DATE) || !(flags & TIME_FUZZY_DATE)) &&
103
 
         (month == 0 || day == 0)) ||
104
 
        (not (flags & TIME_INVALID_DATES) &&
105
 
         month && day > days_in_month[month-1] &&
106
 
         (month != 2 || calc_days_in_year(year) != 366 ||
107
 
          day != 29)))
 
99
         (ltime->month == 0 || ltime->day == 0)) ||
 
100
        (!(flags & TIME_INVALID_DATES) &&
 
101
         ltime->month && ltime->day > days_in_month[ltime->month-1] &&
 
102
         (ltime->month != 2 || calc_days_in_year(ltime->year) != 366 ||
 
103
          ltime->day != 29)))
108
104
    {
109
 
      was_cut= type::INVALID;
 
105
      *was_cut= 2;
110
106
      return true;
111
107
    }
112
108
  }
113
109
  else if (flags & TIME_NO_ZERO_DATE)
114
110
  {
115
111
    /*
116
 
      We don't set &was_cut here to signal that the problem was a zero date
 
112
      We don't set *was_cut here to signal that the problem was a zero date
117
113
      and not an invalid date
118
114
    */
119
115
    return true;
121
117
  return false;
122
118
}
123
119
 
 
120
 
124
121
/*
125
 
  Convert a timestamp string to a type::Time value.
 
122
  Convert a timestamp string to a DRIZZLE_TIME value.
126
123
 
127
124
  SYNOPSIS
128
 
    store()
 
125
    str_to_datetime()
129
126
    str                 String to parse
130
127
    length              Length of string
131
128
    l_time              Date is stored here
137
134
                        TIME_INVALID_DATES      Allow 2000-02-31
138
135
    was_cut             0       Value OK
139
136
                        1       If value was cut during conversion
140
 
                        2       check(date,flags) considers date invalid
 
137
                        2       check_date(date,flags) considers date invalid
141
138
 
142
139
  DESCRIPTION
143
140
    At least the following formats are recogniced (based on number of digits)
174
171
 
175
172
#define MAX_DATE_PARTS 8
176
173
 
177
 
type::timestamp_t Time::store(const char *str, uint32_t length, uint32_t flags, type::cut_t &was_cut)
 
174
enum enum_drizzle_timestamp_type
 
175
str_to_datetime(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
 
176
                uint32_t flags, int *was_cut)
178
177
{
179
178
  uint32_t field_length, year_length=4, digits, i, number_of_fields;
180
179
  uint32_t date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
187
186
  bool found_delimitier= 0, found_space= 0;
188
187
  uint32_t frac_pos, frac_len;
189
188
 
190
 
  was_cut= type::VALID;
 
189
  *was_cut= 0;
191
190
 
192
191
  /* Skip space at start */
193
192
  for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++)
194
193
    ;
195
 
 
196
194
  if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str))
197
195
  {
198
 
    was_cut= type::CUT;
199
 
    return(type::DRIZZLE_TIMESTAMP_NONE);
 
196
    *was_cut= 1;
 
197
    return(DRIZZLE_TIMESTAMP_NONE);
200
198
  }
201
199
 
202
200
  is_internal_format= 0;
242
240
      {
243
241
        if (flags & TIME_DATETIME_ONLY)
244
242
        {
245
 
          was_cut= type::CUT;
246
 
          return(type::DRIZZLE_TIMESTAMP_NONE);   /* Can't be a full datetime */
 
243
          *was_cut= 1;
 
244
          return(DRIZZLE_TIMESTAMP_NONE);   /* Can't be a full datetime */
247
245
        }
248
246
        /* Date field.  Set hour, minutes and seconds to 0 */
249
247
        date[0]= date[1]= date[2]= date[3]= date[4]= 0;
284
282
    date_len[i]= (uint32_t) (str - start);
285
283
    if (tmp_value > 999999)                     /* Impossible date part */
286
284
    {
287
 
      was_cut= type::CUT;
288
 
      return(type::DRIZZLE_TIMESTAMP_NONE);
 
285
      *was_cut= 1;
 
286
      return(DRIZZLE_TIMESTAMP_NONE);
289
287
    }
290
288
    date[i]=tmp_value;
291
289
    not_zero_date|= tmp_value;
321
319
      {
322
320
        if (!(allow_space & (1 << i)))
323
321
        {
324
 
          was_cut= type::CUT;
325
 
          return(type::DRIZZLE_TIMESTAMP_NONE);
 
322
          *was_cut= 1;
 
323
          return(DRIZZLE_TIMESTAMP_NONE);
326
324
        }
327
325
        found_space= 1;
328
326
      }
352
350
  }
353
351
  if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
354
352
  {
355
 
    was_cut= type::CUT;
356
 
    return(type::DRIZZLE_TIMESTAMP_NONE);          /* Can't be a datetime */
 
353
    *was_cut= 1;
 
354
    return(DRIZZLE_TIMESTAMP_NONE);          /* Can't be a datetime */
357
355
  }
358
356
 
359
357
  str= last_field_pos;
365
363
    date[i++]= 0;
366
364
  }
367
365
 
368
 
  do 
 
366
  if (!is_internal_format)
369
367
  {
370
 
    if (not is_internal_format)
371
 
    {
372
 
      year_length= date_len[(uint32_t) format_position[0]];
373
 
      if (!year_length)                           /* Year must be specified */
 
368
    year_length= date_len[(uint32_t) format_position[0]];
 
369
    if (!year_length)                           /* Year must be specified */
 
370
    {
 
371
      *was_cut= 1;
 
372
      return(DRIZZLE_TIMESTAMP_NONE);
 
373
    }
 
374
 
 
375
    l_time->year=               date[(uint32_t) format_position[0]];
 
376
    l_time->month=              date[(uint32_t) format_position[1]];
 
377
    l_time->day=                date[(uint32_t) format_position[2]];
 
378
    l_time->hour=               date[(uint32_t) format_position[3]];
 
379
    l_time->minute=             date[(uint32_t) format_position[4]];
 
380
    l_time->second=             date[(uint32_t) format_position[5]];
 
381
 
 
382
    frac_pos= (uint32_t) format_position[6];
 
383
    frac_len= date_len[frac_pos];
 
384
    if (frac_len < 6)
 
385
      date[frac_pos]*= (uint32_t) log_10_int[6 - frac_len];
 
386
    l_time->second_part= date[frac_pos];
 
387
 
 
388
    if (format_position[7] != (unsigned char) 255)
 
389
    {
 
390
      if (l_time->hour > 12)
374
391
      {
375
 
        was_cut= type::CUT;
376
 
        return(type::DRIZZLE_TIMESTAMP_NONE);
 
392
        *was_cut= 1;
 
393
        goto err;
377
394
      }
378
 
 
379
 
      this->year=               date[(uint32_t) format_position[0]];
380
 
      this->month=              date[(uint32_t) format_position[1]];
381
 
      this->day=                date[(uint32_t) format_position[2]];
382
 
      this->hour=               date[(uint32_t) format_position[3]];
383
 
      this->minute=             date[(uint32_t) format_position[4]];
384
 
      this->second=             date[(uint32_t) format_position[5]];
385
 
 
386
 
      frac_pos= (uint32_t) format_position[6];
387
 
      frac_len= date_len[frac_pos];
388
 
      if (frac_len < 6)
389
 
        date[frac_pos]*= (uint32_t) log_10_int[6 - frac_len];
390
 
      this->second_part= date[frac_pos];
391
 
 
392
 
      if (format_position[7] != (unsigned char) 255)
 
395
      l_time->hour= l_time->hour%12 + add_hours;
 
396
    }
 
397
  }
 
398
  else
 
399
  {
 
400
    l_time->year=       date[0];
 
401
    l_time->month=      date[1];
 
402
    l_time->day=        date[2];
 
403
    l_time->hour=       date[3];
 
404
    l_time->minute=     date[4];
 
405
    l_time->second=     date[5];
 
406
    if (date_len[6] < 6)
 
407
      date[6]*= (uint32_t) log_10_int[6 - date_len[6]];
 
408
    l_time->second_part=date[6];
 
409
  }
 
410
  l_time->neg= 0;
 
411
 
 
412
  if (year_length == 2 && not_zero_date)
 
413
    l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);
 
414
 
 
415
  if (number_of_fields < 3 ||
 
416
      l_time->year > 9999 || l_time->month > 12 ||
 
417
      l_time->day > 31 || l_time->hour > 23 ||
 
418
      l_time->minute > 59 || l_time->second > 59)
 
419
  {
 
420
    /* Only give warning for a zero date if there is some garbage after */
 
421
    if (!not_zero_date)                         /* If zero date */
 
422
    {
 
423
      for (; str != end ; str++)
393
424
      {
394
 
        if (this->hour > 12)
 
425
        if (!my_isspace(&my_charset_utf8_general_ci, *str))
395
426
        {
396
 
          was_cut= type::CUT;
 
427
          not_zero_date= 1;                     /* Give warning */
397
428
          break;
398
429
        }
399
 
        this->hour= this->hour%12 + add_hours;
400
 
      }
401
 
    }
402
 
    else
403
 
    {
404
 
      this->year=       date[0];
405
 
      this->month=      date[1];
406
 
      this->day=        date[2];
407
 
      this->hour=       date[3];
408
 
      this->minute=     date[4];
409
 
      this->second=     date[5];
410
 
      if (date_len[6] < 6)
411
 
        date[6]*= (uint32_t) log_10_int[6 - date_len[6]];
412
 
      this->second_part=date[6];
413
 
    }
414
 
    this->neg= 0;
415
 
 
416
 
    if (year_length == 2 && not_zero_date)
417
 
      this->year+= (this->year < YY_PART_YEAR ? 2000 : 1900);
418
 
 
419
 
    if (number_of_fields < 3 ||
420
 
        this->year > 9999 || this->month > 12 ||
421
 
        this->day > 31 || this->hour > 23 ||
422
 
        this->minute > 59 || this->second > 59)
423
 
    {
424
 
      /* Only give warning for a zero date if there is some garbage after */
425
 
      if (!not_zero_date)                         /* If zero date */
426
 
      {
427
 
        for (; str != end ; str++)
428
 
        {
429
 
          if (!my_isspace(&my_charset_utf8_general_ci, *str))
430
 
          {
431
 
            not_zero_date= 1;                     /* Give warning */
432
 
            break;
433
 
          }
434
 
        }
435
 
      }
436
 
      was_cut= test(not_zero_date) ? type::CUT : type::VALID;
437
 
      break;
438
 
    }
439
 
 
440
 
    if (check(not_zero_date != 0, flags, was_cut))
441
 
    {
442
 
      break;
443
 
    }
444
 
 
445
 
    this->time_type= (number_of_fields <= 3 ?
446
 
                      type::DRIZZLE_TIMESTAMP_DATE : type::DRIZZLE_TIMESTAMP_DATETIME);
447
 
 
448
 
    for (; str != end ; str++)
449
 
    {
450
 
      if (!my_isspace(&my_charset_utf8_general_ci,*str))
451
 
      {
452
 
        was_cut= type::CUT;
453
 
        break;
454
 
      }
455
 
    }
456
 
 
457
 
    return(time_type= (number_of_fields <= 3 ? type::DRIZZLE_TIMESTAMP_DATE : type::DRIZZLE_TIMESTAMP_DATETIME));
458
 
  } while (0);
459
 
 
460
 
  reset();
461
 
 
462
 
  return type::DRIZZLE_TIMESTAMP_ERROR;
463
 
}
464
 
 
465
 
type::timestamp_t Time::store(const char *str, uint32_t length, uint32_t flags)
466
 
{
467
 
  type::cut_t was_cut;
468
 
  return store(str, length, flags, was_cut);
469
 
}
 
430
      }
 
431
    }
 
432
    *was_cut= test(not_zero_date);
 
433
    goto err;
 
434
  }
 
435
 
 
436
  if (check_date(l_time, not_zero_date != 0, flags, was_cut))
 
437
    goto err;
 
438
 
 
439
  l_time->time_type= (number_of_fields <= 3 ?
 
440
                      DRIZZLE_TIMESTAMP_DATE : DRIZZLE_TIMESTAMP_DATETIME);
 
441
 
 
442
  for (; str != end ; str++)
 
443
  {
 
444
    if (!my_isspace(&my_charset_utf8_general_ci,*str))
 
445
    {
 
446
      *was_cut= 1;
 
447
      break;
 
448
    }
 
449
  }
 
450
 
 
451
  return(l_time->time_type=
 
452
              (number_of_fields <= 3 ? DRIZZLE_TIMESTAMP_DATE :
 
453
                                       DRIZZLE_TIMESTAMP_DATETIME));
 
454
 
 
455
err:
 
456
  memset(l_time, 0, sizeof(*l_time));
 
457
  return(DRIZZLE_TIMESTAMP_ERROR);
 
458
}
 
459
 
470
460
 
471
461
/*
472
 
 Convert a time string to a type::Time struct.
 
462
 Convert a time string to a DRIZZLE_TIME struct.
473
463
 
474
464
  SYNOPSIS
475
465
   str_to_time()
493
483
     1  error
494
484
*/
495
485
 
496
 
bool Time::store(const char *str, uint32_t length, int &warning, type::timestamp_t arg)
 
486
bool str_to_time(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
 
487
                    int *warning)
497
488
{
498
489
  uint32_t date[5];
499
490
  uint64_t value;
501
492
  bool found_days,found_hours;
502
493
  uint32_t state;
503
494
 
504
 
  assert(arg == DRIZZLE_TIMESTAMP_TIME);
505
 
 
506
 
  this->neg=0;
507
 
  warning= 0;
 
495
  l_time->neg=0;
 
496
  *warning= 0;
508
497
  for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++)
509
498
    length--;
510
499
  if (str != end && *str == '-')
511
500
  {
512
 
    this->neg=1;
 
501
    l_time->neg=1;
513
502
    str++;
514
503
    length--;
515
504
  }
516
505
  if (str == end)
517
 
    return true;
 
506
    return 1;
518
507
 
519
508
  /* Check first if this is a full TIMESTAMP */
520
509
  if (length >= 12)
521
510
  {                                             /* Probably full timestamp */
522
 
    type::cut_t was_cut;
523
 
    type::timestamp_t res= this->store(str, length, (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut);
524
 
    if ((int) res >= (int) type::DRIZZLE_TIMESTAMP_ERROR)
 
511
    int was_cut;
 
512
    enum enum_drizzle_timestamp_type
 
513
      res= str_to_datetime(str, length, l_time,
 
514
                           (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
 
515
    if ((int) res >= (int) DRIZZLE_TIMESTAMP_ERROR)
525
516
    {
526
 
      if (was_cut != type::VALID)
527
 
        warning|= DRIZZLE_TIME_WARN_TRUNCATED;
528
 
 
529
 
      return res == type::DRIZZLE_TIMESTAMP_ERROR;
 
517
      if (was_cut)
 
518
        *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
 
519
      return res == DRIZZLE_TIMESTAMP_ERROR;
530
520
    }
531
521
  }
532
522
 
604
594
        value= value*10 + (uint32_t) (unsigned char) (*str - '0');
605
595
    }
606
596
    if (field_length > 0)
607
 
    {
608
597
      value*= (long) log_10_int[field_length];
609
 
    }
610
598
    else if (field_length < 0)
611
 
    {
612
 
      warning|= DRIZZLE_TIME_WARN_TRUNCATED;
613
 
    }
614
 
 
 
599
      *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
615
600
    date[4]= (uint32_t) value;
616
601
  }
617
602
  else
618
 
  {
619
603
    date[4]=0;
620
 
  }
621
604
 
622
605
  /* Check for exponent part: E<gigit> | E<sign><digit> */
623
606
  /* (may occur as result of %g formatting of time value) */
652
635
      date[4] > UINT_MAX)
653
636
    return 1;
654
637
 
655
 
  this->year=         0;                      /* For protocol::store_time */
656
 
  this->month=        0;
657
 
  this->day=          date[0];
658
 
  this->hour=         date[1];
659
 
  this->minute=       date[2];
660
 
  this->second=       date[3];
661
 
  this->second_part=  date[4];
662
 
  this->time_type= type::DRIZZLE_TIMESTAMP_TIME;
 
638
  l_time->year=         0;                      /* For protocol::store_time */
 
639
  l_time->month=        0;
 
640
  l_time->day=          date[0];
 
641
  l_time->hour=         date[1];
 
642
  l_time->minute=       date[2];
 
643
  l_time->second=       date[3];
 
644
  l_time->second_part=  date[4];
 
645
  l_time->time_type= DRIZZLE_TIMESTAMP_TIME;
663
646
 
664
 
  /* Check if the value is valid and fits into type::Time range */
665
 
  if (check_time_range(this, &warning))
666
 
  {
 
647
  /* Check if the value is valid and fits into DRIZZLE_TIME range */
 
648
  if (check_time_range(l_time, warning))
667
649
    return 1;
668
 
  }
669
650
 
670
 
  /* Check if there is garbage at end of the type::Time specification */
 
651
  /* Check if there is garbage at end of the DRIZZLE_TIME specification */
671
652
  if (str != end)
672
653
  {
673
654
    do
674
655
    {
675
656
      if (!my_isspace(&my_charset_utf8_general_ci,*str))
676
657
      {
677
 
        warning|= DRIZZLE_TIME_WARN_TRUNCATED;
 
658
        *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
678
659
        break;
679
660
      }
680
661
    } while (++str != end);
682
663
  return 0;
683
664
}
684
665
 
685
 
} // namespace type
686
 
 
687
 
 
688
666
 
689
667
/*
690
 
  Check 'time' value to lie in the type::Time range
 
668
  Check 'time' value to lie in the DRIZZLE_TIME range
691
669
 
692
670
  SYNOPSIS:
693
671
    check_time_range()
694
 
    time     pointer to type::Time value
 
672
    time     pointer to DRIZZLE_TIME value
695
673
    warning  set DRIZZLE_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
696
674
 
697
675
  DESCRIPTION
704
682
    1        time value is invalid
705
683
*/
706
684
 
707
 
static int check_time_range(type::Time *my_time, int *warning)
 
685
static int check_time_range(DRIZZLE_TIME *my_time, int *warning)
708
686
{
709
687
  int64_t hour;
710
688
 
737
715
{
738
716
  time_t seconds;
739
717
  struct tm *l_time,tm_tmp;
740
 
  type::Time my_time;
741
 
  type::Time::epoch_t epoch;
 
718
  DRIZZLE_TIME my_time;
742
719
  bool not_used;
743
720
 
744
721
  seconds= (time_t) time((time_t*) 0);
745
 
  localtime_r(&seconds, &tm_tmp);
 
722
  localtime_r(&seconds,&tm_tmp);
746
723
  l_time= &tm_tmp;
747
724
  my_time_zone=         3600;           /* Comp. for -3600 in my_gmt_sec */
748
725
  my_time.year=         (uint32_t) l_time->tm_year+1900;
751
728
  my_time.hour=         (uint32_t) l_time->tm_hour;
752
729
  my_time.minute=       (uint32_t) l_time->tm_min;
753
730
  my_time.second=       (uint32_t) l_time->tm_sec;
754
 
  my_time.time_type=    type::DRIZZLE_TIMESTAMP_NONE;
 
731
  my_time.time_type=    DRIZZLE_TIMESTAMP_NONE;
755
732
  my_time.second_part=  0;
756
733
  my_time.neg=          false;
757
 
  my_time.convert(epoch, &my_time_zone, &not_used); /* Init my_time_zone */
 
734
  my_system_gmt_sec(&my_time, &my_time_zone, &not_used); /* Init my_time_zone */
758
735
}
759
736
 
760
737
 
809
786
} /* calc_daynr */
810
787
 
811
788
 
812
 
namespace type {
813
789
/*
814
 
  Convert time in type::Time representation in system time zone to its
 
790
  Convert time in DRIZZLE_TIME representation in system time zone to its
815
791
  time_t form (number of seconds in UTC since begginning of Unix Epoch).
816
792
 
817
793
  SYNOPSIS
832
808
  RETURN VALUE
833
809
    Time in UTC seconds since Unix Epoch representation.
834
810
*/
835
 
void Time::convert(epoch_t &epoch, long *my_timezone, bool *in_dst_time_gap, bool skip_timezone) const
 
811
time_t
 
812
my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone,
 
813
                  bool *in_dst_time_gap)
836
814
{
837
815
  uint32_t loop;
 
816
  time_t tmp= 0;
838
817
  int shift= 0;
839
 
  type::Time tmp_time;
840
 
  type::Time *t= &tmp_time;
 
818
  DRIZZLE_TIME tmp_time;
 
819
  DRIZZLE_TIME *t= &tmp_time;
841
820
  struct tm *l_time,tm_tmp;
842
821
  long diff, current_timezone;
843
822
 
845
824
    Use temp variable to avoid trashing input data, which could happen in
846
825
    case of shift required for boundary dates processing.
847
826
  */
848
 
  tmp_time= *this;
 
827
  memcpy(&tmp_time, t_src, sizeof(DRIZZLE_TIME));
849
828
 
850
 
  if (not t->isValidEpoch())
851
 
  {
852
 
    epoch= 0;
853
 
    return;
854
 
  }
 
829
  if (!validate_timestamp_range(t))
 
830
    return 0;
855
831
 
856
832
  /*
857
833
    Calculate the gmt time based on current time and timezone
864
840
    We can't use mktime() as it's buggy on many platforms and not thread safe.
865
841
 
866
842
    Note: this code assumes that our time_t estimation is not too far away
867
 
    from real value (we assume that localtime_r(epoch) will return something
 
843
    from real value (we assume that localtime_r(tmp) will return something
868
844
    within 24 hrs from t) which is probably true for all current time zones.
869
845
 
870
846
    Note2: For the dates, which have time_t representation close to
903
879
    We are safe with shifts close to MAX_INT32, as there are no known
904
880
    time switches on Jan 2038 yet :)
905
881
  */
 
882
  if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && (t->day > 4))
 
883
  {
 
884
    /*
 
885
      Below we will pass (uint32_t) (t->day - shift) to calc_daynr.
 
886
      As we don't want to get an overflow here, we will shift
 
887
      only safe dates. That's why we have (t->day > 4) above.
 
888
    */
 
889
    t->day-= 2;
 
890
    shift= 2;
 
891
  }
906
892
#ifdef TIME_T_UNSIGNED
 
893
  else
907
894
  {
908
895
    /*
909
896
      We can get 0 in time_t representaion only on 1969, 31 of Dec or on
932
919
  }
933
920
#endif
934
921
 
935
 
  epoch= (type::Time::epoch_t) (((calc_daynr((uint32_t) t->year, (uint32_t) t->month, (uint32_t) t->day) -
 
922
  tmp= (time_t) (((calc_daynr((uint32_t) t->year, (uint32_t) t->month, (uint32_t) t->day) -
936
923
                   (long) days_at_timestart)*86400L + (long) t->hour*3600L +
937
924
                  (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
938
925
                 3600);
939
926
 
940
927
  current_timezone= my_time_zone;
941
 
  if (skip_timezone)
942
 
  {
943
 
    util::gmtime(epoch, &tm_tmp);
944
 
  }
945
 
  else
946
 
  {
947
 
    util::localtime(epoch, &tm_tmp);
948
 
  }
949
 
 
950
 
  l_time= &tm_tmp;
 
928
  localtime_r(&tmp,&tm_tmp);
 
929
  l_time=&tm_tmp;
951
930
  for (loop=0;
952
931
       loop < 2 &&
953
932
         (t->hour != (uint32_t) l_time->tm_hour ||
965
944
          (long) (60*((int) t->minute - (int) l_time->tm_min)) +
966
945
          (long) ((int) t->second - (int) l_time->tm_sec));
967
946
    current_timezone+= diff+3600;               /* Compensate for -3600 above */
968
 
    epoch+= (time_t) diff;
969
 
    if (skip_timezone)
970
 
    {
971
 
      util::gmtime(epoch, &tm_tmp);
972
 
    }
973
 
    else
974
 
    {
975
 
      util::localtime(epoch, &tm_tmp);
976
 
    }
 
947
    tmp+= (time_t) diff;
 
948
    localtime_r(&tmp,&tm_tmp);
977
949
    l_time=&tm_tmp;
978
950
  }
979
951
  /*
997
969
          (long) (60*((int) t->minute - (int) l_time->tm_min)) +
998
970
          (long) ((int) t->second - (int) l_time->tm_sec));
999
971
    if (diff == 3600)
1000
 
      epoch+=3600 - t->minute*60 - t->second;   /* Move to next hour */
 
972
      tmp+=3600 - t->minute*60 - t->second;     /* Move to next hour */
1001
973
    else if (diff == -3600)
1002
 
      epoch-=t->minute*60 + t->second;          /* Move to previous hour */
 
974
      tmp-=t->minute*60 + t->second;            /* Move to previous hour */
1003
975
 
1004
976
    *in_dst_time_gap= true;
1005
977
  }
1007
979
 
1008
980
 
1009
981
  /* shift back, if we were dealing with boundary dates */
1010
 
  epoch+= shift*86400L;
 
982
  tmp+= shift*86400L;
1011
983
 
1012
984
  /*
1013
985
    This is possible for dates, which slightly exceed boundaries.
1014
986
    Conversion will pass ok for them, but we don't allow them.
1015
987
    First check will pass for platforms with signed time_t.
1016
 
    instruction above (epoch+= shift*86400L) could exceed
 
988
    instruction above (tmp+= shift*86400L) could exceed
1017
989
    MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen.
1018
 
    So, epoch < TIMESTAMP_MIN_VALUE will be triggered.
 
990
    So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms
 
991
    with unsigned time_t tmp+= shift*86400L might result in a number,
 
992
    larger then TIMESTAMP_MAX_VALUE, so another check will work.
1019
993
  */
1020
 
  if (epoch < TIMESTAMP_MIN_VALUE)
1021
 
  {
1022
 
    epoch= 0;
1023
 
  }
 
994
  if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE))
 
995
    tmp= 0;
 
996
 
 
997
  return (time_t) tmp;
1024
998
} /* my_system_gmt_sec */
1025
999
 
1026
1000
 
1027
 
void Time::store(const struct tm &from)
1028
 
{
1029
 
  _is_local_time= false;
1030
 
  neg= 0;
1031
 
  second_part= 0;
1032
 
  year= (int32_t) ((from.tm_year+1900) % 10000);
1033
 
  month= (int32_t) from.tm_mon+1;
1034
 
  day= (int32_t) from.tm_mday;
1035
 
  hour= (int32_t) from.tm_hour;
1036
 
  minute= (int32_t) from.tm_min;
1037
 
  second= (int32_t) from.tm_sec;
1038
 
 
1039
 
  time_type= DRIZZLE_TIMESTAMP_DATETIME;
1040
 
}
1041
 
 
1042
 
void Time::store(const struct timeval &from)
1043
 
{
1044
 
  store(from.tv_sec, (usec_t)from.tv_usec);
1045
 
  time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
1046
 
}
1047
 
 
1048
 
 
1049
 
void Time::store(const type::Time::epoch_t &from, bool use_localtime)
1050
 
{
1051
 
  store(from, 0, use_localtime);
1052
 
}
1053
 
 
1054
 
void Time::store(const type::Time::epoch_t &from_arg, const usec_t &from_fractional_seconds, bool use_localtime)
1055
 
{
1056
 
  epoch_t from= from_arg;
1057
 
 
1058
 
  if (use_localtime)
1059
 
  {
1060
 
    util::localtime(from, *this);
1061
 
    _is_local_time= true;
1062
 
  }
1063
 
  else
1064
 
  {
1065
 
    util::gmtime(from, *this);
1066
 
  }
1067
 
 
1068
 
  // Since time_t/epoch_t doesn't have fractional seconds, we have to
1069
 
  // collect them outside of the gmtime function.
1070
 
  second_part= from_fractional_seconds;
1071
 
  time_type= DRIZZLE_TIMESTAMP_DATETIME;
1072
 
}
1073
 
 
1074
 
// Only implemented for one case, extend as needed.
1075
 
void Time::truncate(const timestamp_t arg)
1076
 
{
1077
 
  assert(arg == type::DRIZZLE_TIMESTAMP_TIME);
1078
 
  year= month= day= 0;
1079
 
 
1080
 
  time_type= arg;
1081
 
}
1082
 
 
1083
 
void Time::convert(String &str, timestamp_t arg)
1084
 
{
1085
 
  str.alloc(MAX_STRING_LENGTH);
1086
 
  size_t length= MAX_STRING_LENGTH;
1087
 
 
1088
 
  convert(str.c_ptr(), length, arg);
1089
 
 
1090
 
  str.length(length);
1091
 
  str.set_charset(&my_charset_bin);
1092
 
}
1093
 
 
1094
 
void Time::convert(char *str, size_t &to_length, timestamp_t arg)
1095
 
{
1096
 
  int32_t length= 0;
1097
 
  switch (arg) {
 
1001
/* Set DRIZZLE_TIME structure to 0000-00-00 00:00:00.000000 */
 
1002
 
 
1003
void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type)
 
1004
{
 
1005
  memset(tm, 0, sizeof(*tm));
 
1006
  tm->time_type= time_type;
 
1007
}
 
1008
 
 
1009
 
 
1010
/*
 
1011
  Functions to convert time/date/datetime value to a string,
 
1012
  using default format.
 
1013
  This functions don't check that given DRIZZLE_TIME structure members are
 
1014
  in valid range. If they are not, return value won't reflect any
 
1015
  valid date either. Additionally, make_time doesn't take into
 
1016
  account time->day member: it's assumed that days have been converted
 
1017
  to hours already.
 
1018
 
 
1019
  RETURN
 
1020
    number of characters written to 'to'
 
1021
*/
 
1022
 
 
1023
static int my_time_to_str(const DRIZZLE_TIME *l_time, char *to)
 
1024
{
 
1025
  uint32_t extra_hours= 0;
 
1026
  return sprintf(to, "%s%02u:%02u:%02u",
 
1027
                         (l_time->neg ? "-" : ""),
 
1028
                         extra_hours+ l_time->hour,
 
1029
                         l_time->minute,
 
1030
                         l_time->second);
 
1031
}
 
1032
 
 
1033
int my_date_to_str(const DRIZZLE_TIME *l_time, char *to)
 
1034
{
 
1035
  return sprintf(to, "%04u-%02u-%02u",
 
1036
                         l_time->year,
 
1037
                         l_time->month,
 
1038
                         l_time->day);
 
1039
}
 
1040
 
 
1041
int my_datetime_to_str(const DRIZZLE_TIME *l_time, char *to)
 
1042
{
 
1043
  return sprintf(to, "%04u-%02u-%02u %02u:%02u:%02u",
 
1044
                         l_time->year,
 
1045
                         l_time->month,
 
1046
                         l_time->day,
 
1047
                         l_time->hour,
 
1048
                         l_time->minute,
 
1049
                         l_time->second);
 
1050
}
 
1051
 
 
1052
 
 
1053
/*
 
1054
  Convert struct DATE/TIME/DATETIME value to string using built-in
 
1055
  MySQL time conversion formats.
 
1056
 
 
1057
  SYNOPSIS
 
1058
    my_TIME_to_string()
 
1059
 
 
1060
  NOTE
 
1061
    The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
 
1062
*/
 
1063
 
 
1064
int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to)
 
1065
{
 
1066
  switch (l_time->time_type) {
1098
1067
  case DRIZZLE_TIMESTAMP_DATETIME:
1099
 
    length= snprintf(str, to_length,
1100
 
                     "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
1101
 
                     " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
1102
 
                     year,
1103
 
                     month,
1104
 
                     day,
1105
 
                     hour,
1106
 
                     minute,
1107
 
                     second,
1108
 
                     second_part);
1109
 
    break;
1110
 
 
 
1068
    return my_datetime_to_str(l_time, to);
1111
1069
  case DRIZZLE_TIMESTAMP_DATE:
1112
 
    length= snprintf(str, to_length, "%04u-%02u-%02u",
1113
 
                     year,
1114
 
                     month,
1115
 
                     day);
1116
 
    break;
1117
 
 
 
1070
    return my_date_to_str(l_time, to);
1118
1071
  case DRIZZLE_TIMESTAMP_TIME:
1119
 
    {
1120
 
      uint32_t extra_hours= 0;
1121
 
 
1122
 
      length= snprintf(str, to_length,
1123
 
                       "%s%02u:%02u:%02u",
1124
 
                       (neg ? "-" : ""),
1125
 
                       extra_hours+ hour,
1126
 
                       minute,
1127
 
                       second);
1128
 
    }
1129
 
    break;
1130
 
 
 
1072
    return my_time_to_str(l_time, to);
1131
1073
  case DRIZZLE_TIMESTAMP_NONE:
1132
1074
  case DRIZZLE_TIMESTAMP_ERROR:
 
1075
    to[0]='\0';
 
1076
    return 0;
 
1077
  default:
1133
1078
    assert(0);
1134
 
    break;
1135
 
  }
1136
 
 
1137
 
  if (length < 0)
1138
 
  {
1139
 
    to_length= 0;
1140
 
    return;
1141
 
  }
1142
 
 
1143
 
  to_length= length;
1144
 
}
1145
 
 
1146
 
}
 
1079
    return 0;
 
1080
  }
 
1081
}
 
1082
 
1147
1083
 
1148
1084
/*
1149
1085
  Convert datetime value specified as number to broken-down TIME
1153
1089
    number_to_datetime()
1154
1090
      nr         - datetime value as number
1155
1091
      time_res   - pointer for structure for broken-down representation
1156
 
      flags      - flags to use in validating date, as in store()
 
1092
      flags      - flags to use in validating date, as in str_to_datetime()
1157
1093
      was_cut    0      Value ok
1158
1094
                 1      If value was cut during conversion
1159
 
                 2      check(date,flags) considers date invalid
 
1095
                 2      check_date(date,flags) considers date invalid
1160
1096
 
1161
1097
  DESCRIPTION
1162
1098
    Convert a datetime value of formats YYMMDD, YYYYMMDD, YYMMDDHHMSS,
1163
 
    YYYYMMDDHHMMSS to broken-down type::Time representation. Return value in
 
1099
    YYYYMMDDHHMMSS to broken-down DRIZZLE_TIME representation. Return value in
1164
1100
    YYYYMMDDHHMMSS format as side-effect.
1165
1101
 
1166
1102
    This function also checks if datetime value fits in DATETIME range.
1171
1107
    Datetime value in YYYYMMDDHHMMSS format.
1172
1108
*/
1173
1109
 
1174
 
static int64_t number_to_datetime(int64_t nr, type::Time *time_res,
1175
 
                                  uint32_t flags, type::cut_t &was_cut)
 
1110
int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res,
 
1111
                            uint32_t flags, int *was_cut)
1176
1112
{
1177
1113
  long part1,part2;
1178
1114
 
1179
 
  was_cut= type::VALID;
1180
 
  time_res->reset();
1181
 
  time_res->time_type=type::DRIZZLE_TIMESTAMP_DATE;
 
1115
  *was_cut= 0;
 
1116
  memset(time_res, 0, sizeof(*time_res));
 
1117
  time_res->time_type=DRIZZLE_TIMESTAMP_DATE;
1182
1118
 
1183
1119
  if (nr == 0LL || nr >= 10000101000000LL)
1184
1120
  {
1185
 
    time_res->time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
 
1121
    time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
1186
1122
    goto ok;
1187
1123
  }
1188
1124
  if (nr < 101)
1209
1145
  if (nr < 101000000L)
1210
1146
    goto err;
1211
1147
 
1212
 
  time_res->time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
 
1148
  time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
1213
1149
 
1214
1150
  if (nr <= (YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
1215
1151
  {
1234
1170
  if (time_res->year <= 9999 && time_res->month <= 12 &&
1235
1171
      time_res->day <= 31 && time_res->hour <= 23 &&
1236
1172
      time_res->minute <= 59 && time_res->second <= 59 &&
1237
 
      not time_res->check((nr != 0), flags, was_cut))
1238
 
  {
 
1173
      !check_date(time_res, (nr != 0), flags, was_cut))
1239
1174
    return nr;
1240
 
  }
1241
1175
 
1242
1176
  /* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */
1243
1177
  if (!nr && (flags & TIME_NO_ZERO_DATE))
1244
1178
    return -1LL;
1245
1179
 
1246
1180
 err:
1247
 
  was_cut= type::CUT;
 
1181
  *was_cut= 1;
1248
1182
  return -1LL;
1249
1183
}
1250
1184
 
1251
1185
 
1252
 
namespace type {
1253
 
 
1254
 
void Time::convert(datetime_t &ret, int64_t nr, uint32_t flags)
1255
 
{
1256
 
  type::cut_t was_cut;
1257
 
  ret= number_to_datetime(nr, this, flags, was_cut);
1258
 
}
1259
 
 
1260
 
void Time::convert(datetime_t &ret, int64_t nr, uint32_t flags, type::cut_t &was_cut)
1261
 
{
1262
 
  ret= number_to_datetime(nr, this, flags, was_cut);
1263
 
}
1264
 
 
1265
 
/*
1266
 
  Convert struct type::Time (date and time split into year/month/day/hour/...
 
1186
/* Convert time value to integer in YYYYMMDDHHMMSS format */
 
1187
 
 
1188
uint64_t TIME_to_uint64_t_datetime(const DRIZZLE_TIME *my_time)
 
1189
{
 
1190
  return ((uint64_t) (my_time->year * 10000UL +
 
1191
                       my_time->month * 100UL +
 
1192
                       my_time->day) * 1000000ULL +
 
1193
          (uint64_t) (my_time->hour * 10000UL +
 
1194
                       my_time->minute * 100UL +
 
1195
                       my_time->second));
 
1196
}
 
1197
 
 
1198
 
 
1199
/* Convert DRIZZLE_TIME value to integer in YYYYMMDD format */
 
1200
 
 
1201
static uint64_t TIME_to_uint64_t_date(const DRIZZLE_TIME *my_time)
 
1202
{
 
1203
  return (uint64_t) (my_time->year * 10000UL + my_time->month * 100UL +
 
1204
                      my_time->day);
 
1205
}
 
1206
 
 
1207
 
 
1208
/*
 
1209
  Convert DRIZZLE_TIME value to integer in HHMMSS format.
 
1210
  This function doesn't take into account time->day member:
 
1211
  it's assumed that days have been converted to hours already.
 
1212
*/
 
1213
 
 
1214
static uint64_t TIME_to_uint64_t_time(const DRIZZLE_TIME *my_time)
 
1215
{
 
1216
  return (uint64_t) (my_time->hour * 10000UL +
 
1217
                      my_time->minute * 100UL +
 
1218
                      my_time->second);
 
1219
}
 
1220
 
 
1221
 
 
1222
/*
 
1223
  Convert struct DRIZZLE_TIME (date and time split into year/month/day/hour/...
1267
1224
  to a number in format YYYYMMDDHHMMSS (DATETIME),
1268
1225
  YYYYMMDD (DATE)  or HHMMSS (TIME).
 
1226
 
 
1227
  SYNOPSIS
 
1228
    TIME_to_uint64_t()
 
1229
 
 
1230
  DESCRIPTION
 
1231
    The function is used when we need to convert value of time item
 
1232
    to a number if it's used in numeric context, i. e.:
 
1233
    SELECT NOW()+1, CURDATE()+0, CURTIMIE()+0;
 
1234
    SELECT ?+1;
 
1235
 
 
1236
  NOTE
 
1237
    This function doesn't check that given DRIZZLE_TIME structure members are
 
1238
    in valid range. If they are not, return value won't reflect any
 
1239
    valid date either.
1269
1240
*/
1270
1241
 
1271
 
 
1272
 
void Time::convert(datetime_t &datetime, timestamp_t arg)
 
1242
uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *my_time)
1273
1243
{
1274
 
  switch (arg)
1275
 
  {
1276
 
    // Convert to YYYYMMDDHHMMSS format
1277
 
  case type::DRIZZLE_TIMESTAMP_DATETIME:
1278
 
    datetime= ((int64_t) (year * 10000UL + month * 100UL + day) * 1000000ULL +
1279
 
               (int64_t) (hour * 10000UL + minute * 100UL + second));
1280
 
    break;
1281
 
 
1282
 
    // Convert to YYYYMMDD
1283
 
  case type::DRIZZLE_TIMESTAMP_DATE:
1284
 
    datetime= (year * 10000UL + month * 100UL + day);
1285
 
    break;
1286
 
 
1287
 
    // Convert to HHMMSS
1288
 
  case type::DRIZZLE_TIMESTAMP_TIME:
1289
 
    datetime= (hour * 10000UL + minute * 100UL + second);
1290
 
    break;
1291
 
 
1292
 
  case type::DRIZZLE_TIMESTAMP_NONE:
1293
 
  case type::DRIZZLE_TIMESTAMP_ERROR:
1294
 
    datetime= 0;
 
1244
  switch (my_time->time_type) {
 
1245
  case DRIZZLE_TIMESTAMP_DATETIME:
 
1246
    return TIME_to_uint64_t_datetime(my_time);
 
1247
  case DRIZZLE_TIMESTAMP_DATE:
 
1248
    return TIME_to_uint64_t_date(my_time);
 
1249
  case DRIZZLE_TIMESTAMP_TIME:
 
1250
    return TIME_to_uint64_t_time(my_time);
 
1251
  case DRIZZLE_TIMESTAMP_NONE:
 
1252
  case DRIZZLE_TIMESTAMP_ERROR:
 
1253
    return 0ULL;
 
1254
  default:
 
1255
    assert(0);
1295
1256
  }
 
1257
  return 0;
1296
1258
}
1297
1259
 
1298
 
} // namespace type
1299
 
 
1300
1260
} /* namespace drizzled */