~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/my_time.c

Giant merge.

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 <m_string.h>
18
 
#include <m_ctype.h>
 
17
#include <mystrings/m_string.h>
 
18
#include <mystrings/m_ctype.h>
19
19
/* Windows version of localtime_r() is declared in my_ptrhead.h */
20
 
#include <my_pthread.h>
 
20
#include <mysys/my_pthread.h>
21
21
 
22
22
uint64_t log_10_int[20]=
23
23
{
75
75
    1  error
76
76
*/
77
77
 
78
 
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
 
78
bool check_date(const DRIZZLE_TIME *ltime, bool not_zero_date,
79
79
                   ulong flags, int *was_cut)
80
80
{
81
81
  if (not_zero_date)
104
104
 
105
105
 
106
106
/*
107
 
  Convert a timestamp string to a MYSQL_TIME value.
 
107
  Convert a timestamp string to a DRIZZLE_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
 
    MYSQL_TIMESTAMP_NONE        String wasn't a timestamp, like
 
148
    DRIZZLE_TIMESTAMP_NONE        String wasn't a timestamp, like
149
149
                                [DD [HH:[MM:[SS]]]].fraction.
150
150
                                l_time is not changed.
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.
 
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.
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_mysql_timestamp_type
160
 
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
 
159
enum enum_drizzle_timestamp_type
 
160
str_to_datetime(const char *str, uint length, DRIZZLE_TIME *l_time,
161
161
                uint flags, int *was_cut)
162
162
{
163
163
  uint field_length, year_length=4, digits, i, number_of_fields;
164
164
  uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
165
165
  uint add_hours= 0, start_loop;
166
166
  ulong not_zero_date, allow_space;
167
 
  my_bool is_internal_format;
 
167
  bool is_internal_format;
168
168
  const char *pos, *last_field_pos=NULL;
169
169
  const char *end=str+length;
170
170
  const uchar *format_position;
171
 
  my_bool found_delimitier= 0, found_space= 0;
 
171
  bool found_delimitier= 0, found_space= 0;
172
172
  uint frac_pos, frac_len;
173
173
 
174
174
  *was_cut= 0;
179
179
  if (str == end || ! my_isdigit(&my_charset_latin1, *str))
180
180
  {
181
181
    *was_cut= 1;
182
 
    return(MYSQL_TIMESTAMP_NONE);
 
182
    return(DRIZZLE_TIMESTAMP_NONE);
183
183
  }
184
184
 
185
185
  is_internal_format= 0;
226
226
        if (flags & TIME_DATETIME_ONLY)
227
227
        {
228
228
          *was_cut= 1;
229
 
          return(MYSQL_TIMESTAMP_NONE);   /* Can't be a full datetime */
 
229
          return(DRIZZLE_TIMESTAMP_NONE);   /* Can't be a full datetime */
230
230
        }
231
231
        /* Date field.  Set hour, minutes and seconds to 0 */
232
232
        date[0]= date[1]= date[2]= date[3]= date[4]= 0;
268
268
    if (tmp_value > 999999)                     /* Impossible date part */
269
269
    {
270
270
      *was_cut= 1;
271
 
      return(MYSQL_TIMESTAMP_NONE);
 
271
      return(DRIZZLE_TIMESTAMP_NONE);
272
272
    }
273
273
    date[i]=tmp_value;
274
274
    not_zero_date|= tmp_value;
305
305
        if (!(allow_space & (1 << i)))
306
306
        {
307
307
          *was_cut= 1;
308
 
          return(MYSQL_TIMESTAMP_NONE);
 
308
          return(DRIZZLE_TIMESTAMP_NONE);
309
309
        }
310
310
        found_space= 1;
311
311
      }
336
336
  if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
337
337
  {
338
338
    *was_cut= 1;
339
 
    return(MYSQL_TIMESTAMP_NONE);          /* Can't be a datetime */
 
339
    return(DRIZZLE_TIMESTAMP_NONE);          /* Can't be a datetime */
340
340
  }
341
341
 
342
342
  str= last_field_pos;
354
354
    if (!year_length)                           /* Year must be specified */
355
355
    {
356
356
      *was_cut= 1;
357
 
      return(MYSQL_TIMESTAMP_NONE);
 
357
      return(DRIZZLE_TIMESTAMP_NONE);
358
358
    }
359
359
 
360
360
    l_time->year=               date[(uint) format_position[0]];
422
422
    goto err;
423
423
 
424
424
  l_time->time_type= (number_of_fields <= 3 ?
425
 
                      MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);
 
425
                      DRIZZLE_TIMESTAMP_DATE : DRIZZLE_TIMESTAMP_DATETIME);
426
426
 
427
427
  for (; str != end ; str++)
428
428
  {
434
434
  }
435
435
 
436
436
  return(l_time->time_type=
437
 
              (number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE :
438
 
                                       MYSQL_TIMESTAMP_DATETIME));
 
437
              (number_of_fields <= 3 ? DRIZZLE_TIMESTAMP_DATE :
 
438
                                       DRIZZLE_TIMESTAMP_DATETIME));
439
439
 
440
440
err:
441
 
  bzero((char*) l_time, sizeof(*l_time));
442
 
  return(MYSQL_TIMESTAMP_ERROR);
 
441
  memset((char*) l_time, 0, sizeof(*l_time));
 
442
  return(DRIZZLE_TIMESTAMP_ERROR);
443
443
}
444
444
 
445
445
 
446
446
/*
447
 
 Convert a time string to a MYSQL_TIME struct.
 
447
 Convert a time string to a DRIZZLE_TIME struct.
448
448
 
449
449
  SYNOPSIS
450
450
   str_to_time()
454
454
                        There may be an optional [.second_part] after seconds
455
455
   length               Length of str
456
456
   l_time               Store result here
457
 
   warning              Set MYSQL_TIME_WARN_TRUNCATED flag if the input string
 
457
   warning              Set DRIZZLE_TIME_WARN_TRUNCATED flag if the input string
458
458
                        was cut during conversion, and/or
459
 
                        MYSQL_TIME_WARN_OUT_OF_RANGE flag, if the value is
 
459
                        DRIZZLE_TIME_WARN_OUT_OF_RANGE flag, if the value is
460
460
                        out of range.
461
461
 
462
462
   NOTES
468
468
     1  error
469
469
*/
470
470
 
471
 
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
 
471
bool str_to_time(const char *str, uint length, DRIZZLE_TIME *l_time,
472
472
                    int *warning)
473
473
{
474
474
  ulong date[5];
475
475
  uint64_t value;
476
476
  const char *end=str+length, *end_of_days;
477
 
  my_bool found_days,found_hours;
 
477
  bool found_days,found_hours;
478
478
  uint state;
479
479
 
480
480
  l_time->neg=0;
494
494
  if (length >= 12)
495
495
  {                                             /* Probably full timestamp */
496
496
    int was_cut;
497
 
    enum enum_mysql_timestamp_type
 
497
    enum enum_drizzle_timestamp_type
498
498
      res= str_to_datetime(str, length, l_time,
499
499
                           (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
500
 
    if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
 
500
    if ((int) res >= (int) DRIZZLE_TIMESTAMP_ERROR)
501
501
    {
502
502
      if (was_cut)
503
 
        *warning|= MYSQL_TIME_WARN_TRUNCATED;
504
 
      return res == MYSQL_TIMESTAMP_ERROR;
 
503
        *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
 
504
      return res == DRIZZLE_TIMESTAMP_ERROR;
505
505
    }
506
506
  }
507
507
 
561
561
    {
562
562
      bmove_upp((uchar*) (date+4), (uchar*) (date+state),
563
563
                sizeof(long)*(state-1));
564
 
      bzero((uchar*) date, sizeof(long)*(4-state));
 
564
      memset((uchar*) date, 0, sizeof(long)*(4-state));
565
565
    }
566
566
    else
567
 
      bzero((uchar*) (date+state), sizeof(long)*(4-state));
 
567
      memset((uchar*) (date+state), 0, sizeof(long)*(4-state));
568
568
  }
569
569
 
570
570
fractional:
581
581
    if (field_length > 0)
582
582
      value*= (long) log_10_int[field_length];
583
583
    else if (field_length < 0)
584
 
      *warning|= MYSQL_TIME_WARN_TRUNCATED;
 
584
      *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
585
585
    date[4]= (ulong) value;
586
586
  }
587
587
  else
627
627
  l_time->minute=       date[2];
628
628
  l_time->second=       date[3];
629
629
  l_time->second_part=  date[4];
630
 
  l_time->time_type= MYSQL_TIMESTAMP_TIME;
 
630
  l_time->time_type= DRIZZLE_TIMESTAMP_TIME;
631
631
 
632
 
  /* Check if the value is valid and fits into MYSQL_TIME range */
 
632
  /* Check if the value is valid and fits into DRIZZLE_TIME range */
633
633
  if (check_time_range(l_time, warning))
634
634
    return 1;
635
635
  
636
 
  /* Check if there is garbage at end of the MYSQL_TIME specification */
 
636
  /* Check if there is garbage at end of the DRIZZLE_TIME specification */
637
637
  if (str != end)
638
638
  {
639
639
    do
640
640
    {
641
641
      if (!my_isspace(&my_charset_latin1,*str))
642
642
      {
643
 
        *warning|= MYSQL_TIME_WARN_TRUNCATED;
 
643
        *warning|= DRIZZLE_TIME_WARN_TRUNCATED;
644
644
        break;
645
645
      }
646
646
    } while (++str != end);
650
650
 
651
651
 
652
652
/*
653
 
  Check 'time' value to lie in the MYSQL_TIME range
 
653
  Check 'time' value to lie in the DRIZZLE_TIME range
654
654
 
655
655
  SYNOPSIS:
656
656
    check_time_range()
657
 
    time     pointer to MYSQL_TIME value
658
 
    warning  set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of 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
659
 
660
660
  DESCRIPTION
661
661
  If the time value lies outside of the range [-838:59:59, 838:59:59],
662
662
  set it to the closest endpoint of the range and set
663
 
  MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
 
663
  DRIZZLE_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
664
664
 
665
665
  RETURN
666
666
    0        time value is valid, but was possibly truncated
667
667
    1        time value is invalid
668
668
*/
669
669
 
670
 
int check_time_range(struct st_mysql_time *my_time, int *warning) 
 
670
int check_time_range(DRIZZLE_TIME *my_time, int *warning) 
671
671
{
672
672
  int64_t hour;
673
673
 
685
685
  my_time->minute= TIME_MAX_MINUTE;
686
686
  my_time->second= TIME_MAX_SECOND;
687
687
  my_time->second_part= 0;
688
 
  *warning|= MYSQL_TIME_WARN_OUT_OF_RANGE;
 
688
  *warning|= DRIZZLE_TIME_WARN_OUT_OF_RANGE;
689
689
  return 0;
690
690
}
691
691
 
700
700
{
701
701
  time_t seconds;
702
702
  struct tm *l_time,tm_tmp;
703
 
  MYSQL_TIME my_time;
 
703
  DRIZZLE_TIME my_time;
704
704
  bool not_used;
705
705
 
706
706
  seconds= (time_t) time((time_t*) 0);
769
769
 
770
770
 
771
771
/*
772
 
  Convert time in MYSQL_TIME representation in system time zone to its
 
772
  Convert time in DRIZZLE_TIME representation in system time zone to its
773
773
  my_time_t form (number of seconds in UTC since begginning of Unix Epoch).
774
774
 
775
775
  SYNOPSIS
791
791
    Time in UTC seconds since Unix Epoch representation.
792
792
*/
793
793
my_time_t
794
 
my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
 
794
my_system_gmt_sec(const DRIZZLE_TIME *t_src, long *my_timezone,
795
795
                  bool *in_dst_time_gap)
796
796
{
797
797
  uint loop;
798
798
  time_t tmp= 0;
799
799
  int shift= 0;
800
 
  MYSQL_TIME tmp_time;
801
 
  MYSQL_TIME *t= &tmp_time;
 
800
  DRIZZLE_TIME tmp_time;
 
801
  DRIZZLE_TIME *t= &tmp_time;
802
802
  struct tm *l_time,tm_tmp;
803
803
  long diff, current_timezone;
804
804
 
806
806
    Use temp variable to avoid trashing input data, which could happen in
807
807
    case of shift required for boundary dates processing.
808
808
  */
809
 
  memcpy(&tmp_time, t_src, sizeof(MYSQL_TIME));
 
809
  memcpy(&tmp_time, t_src, sizeof(DRIZZLE_TIME));
810
810
 
811
811
  if (!validate_timestamp_range(t))
812
812
    return 0;
980
980
} /* my_system_gmt_sec */
981
981
 
982
982
 
983
 
/* Set MYSQL_TIME structure to 0000-00-00 00:00:00.000000 */
 
983
/* Set DRIZZLE_TIME structure to 0000-00-00 00:00:00.000000 */
984
984
 
985
 
void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
 
985
void set_zero_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type time_type)
986
986
{
987
 
  bzero((void*) tm, sizeof(*tm));
 
987
  memset((void*) tm, 0, sizeof(*tm));
988
988
  tm->time_type= time_type;
989
989
}
990
990
 
992
992
/*
993
993
  Functions to convert time/date/datetime value to a string,
994
994
  using default format.
995
 
  This functions don't check that given MYSQL_TIME structure members are
 
995
  This functions don't check that given DRIZZLE_TIME structure members are
996
996
  in valid range. If they are not, return value won't reflect any
997
997
  valid date either. Additionally, make_time doesn't take into
998
998
  account time->day member: it's assumed that days have been converted
1002
1002
    number of characters written to 'to'
1003
1003
*/
1004
1004
 
1005
 
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
 
1005
int my_time_to_str(const DRIZZLE_TIME *l_time, char *to)
1006
1006
{
1007
1007
  uint extra_hours= 0;
1008
1008
  return sprintf(to, "%s%02u:%02u:%02u",
1012
1012
                         l_time->second);
1013
1013
}
1014
1014
 
1015
 
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
 
1015
int my_date_to_str(const DRIZZLE_TIME *l_time, char *to)
1016
1016
{
1017
1017
  return sprintf(to, "%04u-%02u-%02u",
1018
1018
                         l_time->year,
1020
1020
                         l_time->day);
1021
1021
}
1022
1022
 
1023
 
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
 
1023
int my_datetime_to_str(const DRIZZLE_TIME *l_time, char *to)
1024
1024
{
1025
1025
  return sprintf(to, "%04u-%02u-%02u %02u:%02u:%02u",
1026
1026
                         l_time->year,
1043
1043
    The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
1044
1044
*/
1045
1045
 
1046
 
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to)
 
1046
int my_TIME_to_str(const DRIZZLE_TIME *l_time, char *to)
1047
1047
{
1048
1048
  switch (l_time->time_type) {
1049
 
  case MYSQL_TIMESTAMP_DATETIME:
 
1049
  case DRIZZLE_TIMESTAMP_DATETIME:
1050
1050
    return my_datetime_to_str(l_time, to);
1051
 
  case MYSQL_TIMESTAMP_DATE:
 
1051
  case DRIZZLE_TIMESTAMP_DATE:
1052
1052
    return my_date_to_str(l_time, to);
1053
 
  case MYSQL_TIMESTAMP_TIME:
 
1053
  case DRIZZLE_TIMESTAMP_TIME:
1054
1054
    return my_time_to_str(l_time, to);
1055
 
  case MYSQL_TIMESTAMP_NONE:
1056
 
  case MYSQL_TIMESTAMP_ERROR:
 
1055
  case DRIZZLE_TIMESTAMP_NONE:
 
1056
  case DRIZZLE_TIMESTAMP_ERROR:
1057
1057
    to[0]='\0';
1058
1058
    return 0;
1059
1059
  default:
1078
1078
 
1079
1079
  DESCRIPTION
1080
1080
    Convert a datetime value of formats YYMMDD, YYYYMMDD, YYMMDDHHMSS,
1081
 
    YYYYMMDDHHMMSS to broken-down MYSQL_TIME representation. Return value in
 
1081
    YYYYMMDDHHMMSS to broken-down DRIZZLE_TIME representation. Return value in
1082
1082
    YYYYMMDDHHMMSS format as side-effect.
1083
1083
 
1084
1084
    This function also checks if datetime value fits in DATETIME range.
1089
1089
    Datetime value in YYYYMMDDHHMMSS format.
1090
1090
*/
1091
1091
 
1092
 
int64_t number_to_datetime(int64_t nr, MYSQL_TIME *time_res,
 
1092
int64_t number_to_datetime(int64_t nr, DRIZZLE_TIME *time_res,
1093
1093
                            uint flags, int *was_cut)
1094
1094
{
1095
1095
  long part1,part2;
1096
1096
 
1097
1097
  *was_cut= 0;
1098
 
  bzero((char*) time_res, sizeof(*time_res));
1099
 
  time_res->time_type=MYSQL_TIMESTAMP_DATE;
 
1098
  memset((char*) time_res, 0, sizeof(*time_res));
 
1099
  time_res->time_type=DRIZZLE_TIMESTAMP_DATE;
1100
1100
 
1101
1101
  if (nr == 0LL || nr >= 10000101000000LL)
1102
1102
  {
1103
 
    time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
 
1103
    time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
1104
1104
    goto ok;
1105
1105
  }
1106
1106
  if (nr < 101)
1127
1127
  if (nr < 101000000L)
1128
1128
    goto err;
1129
1129
 
1130
 
  time_res->time_type=MYSQL_TIMESTAMP_DATETIME;
 
1130
  time_res->time_type=DRIZZLE_TIMESTAMP_DATETIME;
1131
1131
 
1132
1132
  if (nr <= (YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
1133
1133
  {
1167
1167
 
1168
1168
/* Convert time value to integer in YYYYMMDDHHMMSS format */
1169
1169
 
1170
 
uint64_t TIME_to_uint64_t_datetime(const MYSQL_TIME *my_time)
 
1170
uint64_t TIME_to_uint64_t_datetime(const DRIZZLE_TIME *my_time)
1171
1171
{
1172
1172
  return ((uint64_t) (my_time->year * 10000UL +
1173
1173
                       my_time->month * 100UL +
1178
1178
}
1179
1179
 
1180
1180
 
1181
 
/* Convert MYSQL_TIME value to integer in YYYYMMDD format */
 
1181
/* Convert DRIZZLE_TIME value to integer in YYYYMMDD format */
1182
1182
 
1183
 
uint64_t TIME_to_uint64_t_date(const MYSQL_TIME *my_time)
 
1183
uint64_t TIME_to_uint64_t_date(const DRIZZLE_TIME *my_time)
1184
1184
{
1185
1185
  return (uint64_t) (my_time->year * 10000UL + my_time->month * 100UL +
1186
1186
                      my_time->day);
1188
1188
 
1189
1189
 
1190
1190
/*
1191
 
  Convert MYSQL_TIME value to integer in HHMMSS format.
 
1191
  Convert DRIZZLE_TIME value to integer in HHMMSS format.
1192
1192
  This function doesn't take into account time->day member:
1193
1193
  it's assumed that days have been converted to hours already.
1194
1194
*/
1195
1195
 
1196
 
uint64_t TIME_to_uint64_t_time(const MYSQL_TIME *my_time)
 
1196
uint64_t TIME_to_uint64_t_time(const DRIZZLE_TIME *my_time)
1197
1197
{
1198
1198
  return (uint64_t) (my_time->hour * 10000UL +
1199
1199
                      my_time->minute * 100UL +
1202
1202
 
1203
1203
 
1204
1204
/*
1205
 
  Convert struct MYSQL_TIME (date and time split into year/month/day/hour/...
 
1205
  Convert struct DRIZZLE_TIME (date and time split into year/month/day/hour/...
1206
1206
  to a number in format YYYYMMDDHHMMSS (DATETIME),
1207
1207
  YYYYMMDD (DATE)  or HHMMSS (TIME).
1208
1208
 
1216
1216
    SELECT ?+1;
1217
1217
 
1218
1218
  NOTE
1219
 
    This function doesn't check that given MYSQL_TIME structure members are
 
1219
    This function doesn't check that given DRIZZLE_TIME structure members are
1220
1220
    in valid range. If they are not, return value won't reflect any
1221
1221
    valid date either.
1222
1222
*/
1223
1223
 
1224
 
uint64_t TIME_to_uint64_t(const MYSQL_TIME *my_time)
 
1224
uint64_t TIME_to_uint64_t(const DRIZZLE_TIME *my_time)
1225
1225
{
1226
1226
  switch (my_time->time_type) {
1227
 
  case MYSQL_TIMESTAMP_DATETIME:
 
1227
  case DRIZZLE_TIMESTAMP_DATETIME:
1228
1228
    return TIME_to_uint64_t_datetime(my_time);
1229
 
  case MYSQL_TIMESTAMP_DATE:
 
1229
  case DRIZZLE_TIMESTAMP_DATE:
1230
1230
    return TIME_to_uint64_t_date(my_time);
1231
 
  case MYSQL_TIMESTAMP_TIME:
 
1231
  case DRIZZLE_TIMESTAMP_TIME:
1232
1232
    return TIME_to_uint64_t_time(my_time);
1233
 
  case MYSQL_TIMESTAMP_NONE:
1234
 
  case MYSQL_TIMESTAMP_ERROR:
 
1233
  case DRIZZLE_TIMESTAMP_NONE:
 
1234
  case DRIZZLE_TIMESTAMP_ERROR:
1235
1235
    return 0ULL;
1236
1236
  default:
1237
1237
    assert(0);