~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/my_time.c

  • Committer: Brian Aker
  • Date: 2008-09-04 19:31:00 UTC
  • Revision ID: brian@tangent.org-20080904193100-l849hgghfy4urj43
Changing default character set from this point on.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#include <my_time.h>
17
17
#include <mystrings/m_string.h>
18
18
#include <mystrings/m_ctype.h>
19
 
#include <drizzled/util/test.h>
20
19
/* Windows version of localtime_r() is declared in my_ptrhead.h */
21
20
 
22
21
uint64_t log_10_int[20]=
31
30
 
32
31
/* Position for YYYY-DD-MM HH-MM-DD.FFFFFF AM in default format */
33
32
 
34
 
static unsigned char internal_format_positions[]=
35
 
{0, 1, 2, 3, 4, 5, 6, (unsigned char) 255};
 
33
static uchar internal_format_positions[]=
 
34
{0, 1, 2, 3, 4, 5, 6, (uchar) 255};
36
35
 
37
36
static char time_separator=':';
38
37
 
39
38
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
uchar days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
41
40
 
42
41
/*
43
42
  Offset of system time zone from UTC in seconds used to speed up 
48
47
 
49
48
/* Calc days in one year. works with 0 <= year <= 99 */
50
49
 
51
 
uint32_t calc_days_in_year(uint32_t year)
 
50
uint calc_days_in_year(uint year)
52
51
{
53
52
  return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ?
54
53
          366 : 365);
157
156
#define MAX_DATE_PARTS 8
158
157
 
159
158
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
str_to_datetime(const char *str, uint length, DRIZZLE_TIME *l_time,
 
160
                uint flags, int *was_cut)
162
161
{
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;
 
162
  uint field_length, year_length=4, digits, i, number_of_fields;
 
163
  uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
 
164
  uint add_hours= 0, start_loop;
166
165
  uint32_t not_zero_date, allow_space;
167
166
  bool is_internal_format;
168
167
  const char *pos, *last_field_pos=NULL;
169
168
  const char *end=str+length;
170
 
  const unsigned char *format_position;
 
169
  const uchar *format_position;
171
170
  bool found_delimitier= 0, found_space= 0;
172
 
  uint32_t frac_pos, frac_len;
 
171
  uint frac_pos, frac_len;
173
172
 
174
173
  *was_cut= 0;
175
174
 
176
175
  /* Skip space at start */
177
 
  for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++)
 
176
  for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
178
177
    ;
179
 
  if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str))
 
178
  if (str == end || ! my_isdigit(&my_charset_latin1, *str))
180
179
  {
181
180
    *was_cut= 1;
182
181
    return(DRIZZLE_TIMESTAMP_NONE);
192
191
    (YYYY-MM-DD,  YYYYMMDD, YYYYYMMDDHHMMSS)
193
192
  */
194
193
  for (pos=str;
195
 
       pos != end && (my_isdigit(&my_charset_utf8_general_ci,*pos) || *pos == 'T');
 
194
       pos != end && (my_isdigit(&my_charset_latin1,*pos) || *pos == 'T');
196
195
       pos++)
197
196
    ;
198
197
 
217
216
        We do this by checking if there is two numbers separated by
218
217
        space in the input.
219
218
      */
220
 
      while (pos < end && !my_isspace(&my_charset_utf8_general_ci, *pos))
 
219
      while (pos < end && !my_isspace(&my_charset_latin1, *pos))
221
220
        pos++;
222
 
      while (pos < end && !my_isdigit(&my_charset_utf8_general_ci, *pos))
 
221
      while (pos < end && !my_isdigit(&my_charset_latin1, *pos))
223
222
        pos++;
224
223
      if (pos == end)
225
224
      {
245
244
    2003-03-03 20:00:20 AM
246
245
    20:00:20.000000 AM 03-03-2000
247
246
  */
248
 
  i= cmax((uint) format_position[0], (uint) format_position[1]);
 
247
  i= max((uint) format_position[0], (uint) format_position[1]);
249
248
  set_if_bigger(i, (uint) format_position[2]);
250
249
  allow_space= ((1 << i) | (1 << format_position[6]));
251
250
  allow_space&= (1 | 2 | 4 | 8);
253
252
  not_zero_date= 0;
254
253
  for (i = start_loop;
255
254
       i < MAX_DATE_PARTS-1 && str != end &&
256
 
         my_isdigit(&my_charset_utf8_general_ci,*str);
 
255
         my_isdigit(&my_charset_latin1,*str);
257
256
       i++)
258
257
  {
259
258
    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]) &&
 
259
    uint32_t tmp_value= (uint) (uchar) (*str++ - '0');
 
260
    while (str != end && my_isdigit(&my_charset_latin1,str[0]) &&
262
261
           (!is_internal_format || --field_length))
263
262
    {
264
 
      tmp_value=tmp_value*10 + (uint32_t) (unsigned char) (*str - '0');
 
263
      tmp_value=tmp_value*10 + (uint32_t) (uchar) (*str - '0');
265
264
      str++;
266
265
    }
267
266
    date_len[i]= (uint) (str - start);
297
296
      continue;
298
297
    }
299
298
    while (str != end &&
300
 
           (my_ispunct(&my_charset_utf8_general_ci,*str) ||
301
 
            my_isspace(&my_charset_utf8_general_ci,*str)))
 
299
           (my_ispunct(&my_charset_latin1,*str) ||
 
300
            my_isspace(&my_charset_latin1,*str)))
302
301
    {
303
 
      if (my_isspace(&my_charset_utf8_general_ci,*str))
 
302
      if (my_isspace(&my_charset_latin1,*str))
304
303
      {
305
304
        if (!(allow_space & (1 << i)))
306
305
        {
326
325
            continue;                           /* Not AM/PM */
327
326
          str+= 2;                              /* Skip AM/PM */
328
327
          /* Skip space after AM/PM */
329
 
          while (str != end && my_isspace(&my_charset_utf8_general_ci,*str))
 
328
          while (str != end && my_isspace(&my_charset_latin1,*str))
330
329
            str++;
331
330
        }
332
331
      }
370
369
      date[frac_pos]*= (uint) log_10_int[6 - frac_len];
371
370
    l_time->second_part= date[frac_pos];
372
371
 
373
 
    if (format_position[7] != (unsigned char) 255)
 
372
    if (format_position[7] != (uchar) 255)
374
373
    {
375
374
      if (l_time->hour > 12)
376
375
      {
407
406
    {
408
407
      for (; str != end ; str++)
409
408
      {
410
 
        if (!my_isspace(&my_charset_utf8_general_ci, *str))
 
409
        if (!my_isspace(&my_charset_latin1, *str))
411
410
        {
412
411
          not_zero_date= 1;                     /* Give warning */
413
412
          break;
426
425
 
427
426
  for (; str != end ; str++)
428
427
  {
429
 
    if (!my_isspace(&my_charset_utf8_general_ci,*str))
 
428
    if (!my_isspace(&my_charset_latin1,*str))
430
429
    {
431
430
      *was_cut= 1;
432
431
      break;
468
467
     1  error
469
468
*/
470
469
 
471
 
bool str_to_time(const char *str, uint32_t length, DRIZZLE_TIME *l_time,
 
470
bool str_to_time(const char *str, uint length, DRIZZLE_TIME *l_time,
472
471
                    int *warning)
473
472
{
474
473
  uint32_t date[5];
475
474
  uint64_t value;
476
475
  const char *end=str+length, *end_of_days;
477
476
  bool found_days,found_hours;
478
 
  uint32_t state;
 
477
  uint state;
479
478
 
480
479
  l_time->neg=0;
481
480
  *warning= 0;
482
 
  for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++)
 
481
  for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
483
482
    length--;
484
483
  if (str != end && *str == '-')
485
484
  {
506
505
  }
507
506
 
508
507
  /* 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++)
 
508
  for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
510
509
    value=value*10L + (long) (*str - '0');
511
510
 
512
511
  /* Skip all space after 'days' */
513
512
  end_of_days= str;
514
 
  for (; str != end && my_isspace(&my_charset_utf8_general_ci, str[0]) ; str++)
 
513
  for (; str != end && my_isspace(&my_charset_latin1, str[0]) ; str++)
515
514
    ;
516
515
 
517
516
  found_days=found_hours=0;
518
517
  if ((uint) (end-str) > 1 && str != end_of_days &&
519
 
      my_isdigit(&my_charset_utf8_general_ci, *str))
 
518
      my_isdigit(&my_charset_latin1, *str))
520
519
  {                                             /* Found days part */
521
520
    date[0]= (uint32_t) value;
522
521
    state= 1;                                   /* Assume next is hours */
523
522
    found_days= 1;
524
523
  }
525
524
  else if ((end-str) > 1 &&  *str == time_separator &&
526
 
           my_isdigit(&my_charset_utf8_general_ci, str[1]))
 
525
           my_isdigit(&my_charset_latin1, str[1]))
527
526
  {
528
527
    date[0]= 0;                                 /* Assume we found hours */
529
528
    date[1]= (uint32_t) value;
545
544
  /* Read hours, minutes and seconds */
546
545
  for (;;)
547
546
  {
548
 
    for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++)
 
547
    for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
549
548
      value=value*10L + (long) (*str - '0');
550
549
    date[state++]= (uint32_t) value;
551
550
    if (state == 4 || (end-str) < 2 || *str != time_separator ||
552
 
        !my_isdigit(&my_charset_utf8_general_ci,str[1]))
 
551
        !my_isdigit(&my_charset_latin1,str[1]))
553
552
      break;
554
553
    str++;                                      /* Skip time_separator (':') */
555
554
  }
559
558
    /* Fix the date to assume that seconds was given */
560
559
    if (!found_hours && !found_days)
561
560
    {
562
 
      bmove_upp((unsigned char*) (date+4), (unsigned char*) (date+state),
 
561
      bmove_upp((uchar*) (date+4), (uchar*) (date+state),
563
562
                sizeof(long)*(state-1));
564
563
      memset(date, 0, sizeof(long)*(4-state));
565
564
    }
569
568
 
570
569
fractional:
571
570
  /* Get fractional second part */
572
 
  if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_utf8_general_ci,str[1]))
 
571
  if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1]))
573
572
  {
574
573
    int field_length= 5;
575
 
    str++; value=(uint) (unsigned char) (*str - '0');
576
 
    while (++str != end && my_isdigit(&my_charset_utf8_general_ci, *str))
 
574
    str++; value=(uint) (uchar) (*str - '0');
 
575
    while (++str != end && my_isdigit(&my_charset_latin1, *str))
577
576
    {
578
577
      if (field_length-- > 0)
579
 
        value= value*10 + (uint) (unsigned char) (*str - '0');
 
578
        value= value*10 + (uint) (uchar) (*str - '0');
580
579
    }
581
580
    if (field_length > 0)
582
581
      value*= (long) log_10_int[field_length];
591
590
  /* (may occur as result of %g formatting of time value) */
592
591
  if ((end - str) > 1 &&
593
592
      (*str == 'e' || *str == 'E') &&
594
 
      (my_isdigit(&my_charset_utf8_general_ci, str[1]) ||
 
593
      (my_isdigit(&my_charset_latin1, str[1]) ||
595
594
       ((str[1] == '-' || str[1] == '+') &&
596
595
        (end - str) > 2 &&
597
 
        my_isdigit(&my_charset_utf8_general_ci, str[2]))))
 
596
        my_isdigit(&my_charset_latin1, str[2]))))
598
597
    return 1;
599
598
 
600
599
  if (internal_format_positions[7] != 255)
601
600
  {
602
601
    /* Read a possible AM/PM */
603
 
    while (str != end && my_isspace(&my_charset_utf8_general_ci, *str))
 
602
    while (str != end && my_isspace(&my_charset_latin1, *str))
604
603
      str++;
605
604
    if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
606
605
    {
638
637
  {
639
638
    do
640
639
    {
641
 
      if (!my_isspace(&my_charset_utf8_general_ci,*str))
 
640
      if (!my_isspace(&my_charset_latin1,*str))
642
641
      {
643
642
        *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
644
643
        break;
728
727
    Year between 1970-2069
729
728
*/
730
729
 
731
 
uint32_t year_2000_handling(uint32_t year)
 
730
uint year_2000_handling(uint year)
732
731
{
733
732
  if ((year=year+1900) < 1900+YY_PART_YEAR)
734
733
    year+=100;
751
750
    Days since 0000-00-00
752
751
*/
753
752
 
754
 
long calc_daynr(uint32_t year,uint32_t month,uint32_t day)
 
753
long calc_daynr(uint year,uint month,uint day)
755
754
{
756
755
  long delsum;
757
756
  int temp;
794
793
my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone,
795
794
                  bool *in_dst_time_gap)
796
795
{
797
 
  uint32_t loop;
 
796
  uint loop;
798
797
  time_t tmp= 0;
799
798
  int shift= 0;
800
799
  DRIZZLE_TIME tmp_time;
1004
1003
 
1005
1004
int my_time_to_str(const DRIZZLE_TIME *l_time, char *to)
1006
1005
{
1007
 
  uint32_t extra_hours= 0;
 
1006
  uint extra_hours= 0;
1008
1007
  return sprintf(to, "%s%02u:%02u:%02u",
1009
1008
                         (l_time->neg ? "-" : ""),
1010
1009
                         extra_hours+ l_time->hour,
1090
1089
*/
1091
1090
 
1092
1091
int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res,
1093
 
                            uint32_t flags, int *was_cut)
 
1092
                            uint flags, int *was_cut)
1094
1093
{
1095
1094
  long part1,part2;
1096
1095