18 #include <drizzled/type/time.h>
20 #include <drizzled/util/gmtime.h>
22 #include <drizzled/internal/m_string.h>
23 #include <drizzled/charset.h>
24 #include <drizzled/util/test.h>
26 #include <drizzled/sql_string.h>
35 static int check_time_range(type::Time *my_time,
int *warning);
39 uint64_t log_10_int[20]=
41 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL,
42 100000000ULL, 1000000000ULL, 10000000000ULL, 100000000000ULL,
43 1000000000000ULL, 10000000000000ULL, 100000000000000ULL,
44 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
45 1000000000000000000ULL, 10000000000000000000ULL
51 static unsigned char internal_format_positions[]=
52 {0, 1, 2, 3, 4, 5, 6, (
unsigned char) 255};
54 static char time_separator=
':';
56 static uint32_t
const days_at_timestart=719528;
57 unsigned char days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
63 static long my_time_zone=0;
68 uint32_t calc_days_in_year(uint32_t year)
70 return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ?
97 bool Time::check(
bool not_zero_date, uint32_t flags, type::cut_t &was_cut)
const
101 if ((((flags & TIME_NO_ZERO_IN_DATE) || !(flags & TIME_FUZZY_DATE)) &&
102 (month == 0 || day == 0)) ||
103 (not (flags & TIME_INVALID_DATES) &&
104 month && day > days_in_month[month-1] &&
105 (month != 2 || calc_days_in_year(year) != 366 ||
108 was_cut= type::INVALID;
112 else if (flags & TIME_NO_ZERO_DATE)
174 #define MAX_DATE_PARTS 8
176 type::timestamp_t Time::store(
const char *str, uint32_t length, uint32_t flags, type::cut_t &was_cut)
178 uint32_t field_length, year_length=4, digits, i, number_of_fields;
179 uint32_t date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
180 uint32_t add_hours= 0, start_loop;
181 uint32_t not_zero_date, allow_space;
182 bool is_internal_format;
183 const char *pos, *last_field_pos=NULL;
184 const char *end=str+length;
185 const unsigned char *format_position;
186 bool found_delimitier= 0, found_space= 0;
187 uint32_t frac_pos, frac_len;
189 was_cut= type::VALID;
192 for (; str != end && my_charset_utf8_general_ci.isspace(*str) ; str++)
195 if (str == end || not my_charset_utf8_general_ci.isdigit(*str))
198 return(type::DRIZZLE_TIMESTAMP_NONE);
201 is_internal_format= 0;
203 format_position= internal_format_positions;
211 pos != end && (my_charset_utf8_general_ci.isdigit(*pos) || *pos ==
'T');
215 digits= (uint32_t) (pos-str);
217 date_len[format_position[0]]= 0;
218 if (pos == end || *pos ==
'.')
221 year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
222 field_length= year_length;
223 is_internal_format= 1;
224 format_position= internal_format_positions;
228 if (format_position[0] >= 3)
236 while (pos < end && not my_charset_utf8_general_ci.isspace(*pos))
238 while (pos < end && not my_charset_utf8_general_ci.isdigit(*pos))
242 if (flags & TIME_DATETIME_ONLY)
245 return(type::DRIZZLE_TIMESTAMP_NONE);
248 date[0]= date[1]= date[2]= date[3]= date[4]= 0;
253 field_length= format_position[0] == 0 ? 4 : 2;
264 i= max((uint32_t) format_position[0], (uint32_t) format_position[1]);
265 set_if_bigger(i, (uint32_t) format_position[2]);
266 allow_space= ((1 << i) | (1 << format_position[6]));
267 allow_space&= (1 | 2 | 4 | 8);
271 i < MAX_DATE_PARTS-1 && str != end &&
272 my_charset_utf8_general_ci.isdigit(*str);
275 const char *start= str;
276 uint32_t tmp_value= (uint32_t) (
unsigned char) (*str++ -
'0');
277 while (str != end && my_charset_utf8_general_ci.isdigit(str[0]) &&
278 (!is_internal_format || --field_length))
280 tmp_value=tmp_value*10 + (uint32_t) (
unsigned char) (*str -
'0');
283 date_len[i]= (uint32_t) (str - start);
284 if (tmp_value > 999999)
287 return(type::DRIZZLE_TIMESTAMP_NONE);
290 not_zero_date|= tmp_value;
293 field_length= format_position[i+1] == 0 ? 4 : 2;
295 if ((last_field_pos= str) == end)
301 if (i == format_position[2] && *str ==
'T')
306 if (i == format_position[5])
316 (my_charset_utf8_general_ci.ispunct(*str) ||
317 my_charset_utf8_general_ci.isspace(*str)))
319 if (my_charset_utf8_general_ci.isspace(*str))
321 if (!(allow_space & (1 << i)))
324 return(type::DRIZZLE_TIMESTAMP_NONE);
332 if (i == format_position[6])
335 if (format_position[7] != 255)
337 if (str+2 <= end && (str[1] ==
'M' || str[1] ==
'm'))
339 if (str[0] ==
'p' || str[0] ==
'P')
341 else if (str[0] !=
'a' || str[0] !=
'A')
345 while (str != end && my_charset_utf8_general_ci.isspace(*str))
352 if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
355 return(type::DRIZZLE_TIMESTAMP_NONE);
360 number_of_fields= i - start_loop;
361 while (i < MAX_DATE_PARTS)
369 if (not is_internal_format)
371 year_length= date_len[(uint32_t) format_position[0]];
375 return(type::DRIZZLE_TIMESTAMP_NONE);
378 this->year= date[(uint32_t) format_position[0]];
379 this->month= date[(uint32_t) format_position[1]];
380 this->day= date[(uint32_t) format_position[2]];
381 this->hour= date[(uint32_t) format_position[3]];
382 this->minute= date[(uint32_t) format_position[4]];
383 this->second= date[(uint32_t) format_position[5]];
385 frac_pos= (uint32_t) format_position[6];
386 frac_len= date_len[frac_pos];
388 date[frac_pos]*= (uint32_t) log_10_int[6 - frac_len];
389 this->second_part= date[frac_pos];
391 if (format_position[7] != (
unsigned char) 255)
398 this->hour= this->hour%12 + add_hours;
404 this->month= date[1];
407 this->minute= date[4];
408 this->second= date[5];
410 date[6]*= (uint32_t) log_10_int[6 - date_len[6]];
411 this->second_part=date[6];
415 if (year_length == 2 && not_zero_date)
416 this->year+= (this->year < YY_PART_YEAR ? 2000 : 1900);
418 if (number_of_fields < 3 ||
419 this->year > 9999 || this->month > 12 ||
420 this->day > 31 || this->hour > 23 ||
421 this->minute > 59 || this->second > 59)
426 for (; str != end ; str++)
428 if (not my_charset_utf8_general_ci.isspace(*str))
435 was_cut= test(not_zero_date) ? type::CUT : type::VALID;
439 if (check(not_zero_date != 0, flags, was_cut))
444 this->time_type= (number_of_fields <= 3 ?
445 type::DRIZZLE_TIMESTAMP_DATE : type::DRIZZLE_TIMESTAMP_DATETIME);
447 for (; str != end ; str++)
449 if (not my_charset_utf8_general_ci.isspace(*str))
456 return(time_type= (number_of_fields <= 3 ? type::DRIZZLE_TIMESTAMP_DATE : type::DRIZZLE_TIMESTAMP_DATETIME));
461 return type::DRIZZLE_TIMESTAMP_ERROR;
464 type::timestamp_t Time::store(
const char *str, uint32_t length, uint32_t flags)
467 return store(str, length, flags, was_cut);
495 bool Time::store(
const char *str, uint32_t length,
int &warning, type::timestamp_t arg)
499 const char *end=str+length, *end_of_days;
500 bool found_days,found_hours;
503 assert(arg == DRIZZLE_TIMESTAMP_TIME);
507 for (; str != end && my_charset_utf8_general_ci.isspace(*str) ; str++)
509 if (str != end && *str ==
'-')
522 type::timestamp_t res= this->store(str, length, (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut);
523 if ((
int) res >= (
int) type::DRIZZLE_TIMESTAMP_ERROR)
525 if (was_cut != type::VALID)
526 warning|= DRIZZLE_TIME_WARN_TRUNCATED;
528 return res == type::DRIZZLE_TIMESTAMP_ERROR;
533 for (value=0; str != end && my_charset_utf8_general_ci.isdigit(*str) ; str++)
534 value=value*10L + (
long) (*str -
'0');
538 for (; str != end && my_charset_utf8_general_ci.isspace(str[0]) ; str++)
541 found_days=found_hours=0;
542 if ((uint32_t) (end-str) > 1 && str != end_of_days &&
543 my_charset_utf8_general_ci.isdigit(*str))
545 date[0]= (uint32_t) value;
549 else if ((end-str) > 1 && *str == time_separator &&
550 my_charset_utf8_general_ci.isdigit(str[1]))
553 date[1]= (uint32_t) value;
562 date[1]= (uint32_t) (value/10000);
563 date[2]= (uint32_t) (value/100 % 100);
564 date[3]= (uint32_t) (value % 100);
572 for (value=0; str != end && my_charset_utf8_general_ci.isdigit(*str) ; str++)
573 value=value*10L + (
long) (*str -
'0');
574 date[state++]= (uint32_t) value;
575 if (state == 4 || (end-str) < 2 || *str != time_separator ||
576 !my_charset_utf8_general_ci.isdigit(str[1]))
584 if (!found_hours && !found_days)
586 internal::bmove_upp((
unsigned char*) (date+4), (
unsigned char*) (date+state),
587 sizeof(
long)*(state-1));
588 memset(date, 0,
sizeof(
long)*(4-state));
591 memset(date+state, 0,
sizeof(
long)*(4-state));
596 if ((end-str) >= 2 && *str ==
'.' && my_charset_utf8_general_ci.isdigit(str[1]))
599 str++; value=(uint32_t) (
unsigned char) (*str -
'0');
600 while (++str != end && my_charset_utf8_general_ci.isdigit(*str))
602 if (field_length-- > 0)
603 value= value*10 + (uint32_t) (
unsigned char) (*str -
'0');
605 if (field_length > 0)
607 value*= (long) log_10_int[field_length];
609 else if (field_length < 0)
611 warning|= DRIZZLE_TIME_WARN_TRUNCATED;
614 date[4]= (uint32_t) value;
623 if ((end - str) > 1 &&
624 (*str ==
'e' || *str ==
'E') &&
625 (my_charset_utf8_general_ci.isdigit(str[1]) ||
626 ((str[1] ==
'-' || str[1] ==
'+') &&
628 my_charset_utf8_general_ci.isdigit(str[2]))))
631 if (internal_format_positions[7] != 255)
634 while (str != end && my_charset_utf8_general_ci.isspace(*str))
636 if (str+2 <= end && (str[1] ==
'M' || str[1] ==
'm'))
638 if (str[0] ==
'p' || str[0] ==
'P')
641 date[1]= date[1]%12 + 12;
643 else if (str[0] ==
'a' || str[0] ==
'A')
649 if (date[0] > UINT_MAX || date[1] > UINT_MAX ||
650 date[2] > UINT_MAX || date[3] > UINT_MAX ||
658 this->minute= date[2];
659 this->second= date[3];
660 this->second_part= date[4];
661 this->time_type= type::DRIZZLE_TIMESTAMP_TIME;
664 if (check_time_range(
this, &warning))
674 if (not my_charset_utf8_general_ci.isspace(*str))
676 warning|= DRIZZLE_TIME_WARN_TRUNCATED;
679 }
while (++str != end);
706 static int check_time_range(type::Time *my_time,
int *warning)
710 if (my_time->minute >= 60 || my_time->second >= 60)
713 hour= my_time->hour + (24*my_time->day);
714 if (hour <= TIME_MAX_HOUR &&
715 (hour != TIME_MAX_HOUR || my_time->minute != TIME_MAX_MINUTE ||
716 my_time->second != TIME_MAX_SECOND || !my_time->second_part))
720 my_time->hour= TIME_MAX_HOUR;
721 my_time->minute= TIME_MAX_MINUTE;
722 my_time->second= TIME_MAX_SECOND;
723 my_time->second_part= 0;
724 *warning|= DRIZZLE_TIME_WARN_OUT_OF_RANGE;
740 time_t seconds= time(NULL);
742 localtime_r(&seconds, &tm_tmp);
745 my_time.year= (uint32_t) l_time->tm_year+1900;
746 my_time.month= (uint32_t) l_time->tm_mon+1;
747 my_time.day= (uint32_t) l_time->tm_mday;
748 my_time.hour= (uint32_t) l_time->tm_hour;
749 my_time.minute= (uint32_t) l_time->tm_min;
750 my_time.second= (uint32_t) l_time->tm_sec;
751 my_time.time_type= type::DRIZZLE_TIMESTAMP_NONE;
752 my_time.second_part= 0;
754 my_time.convert(epoch, &my_time_zone);
769 uint32_t year_2000_handling(uint32_t year)
771 if ((year=year+1900) < 1900+YY_PART_YEAR)
792 long calc_daynr(uint32_t year,uint32_t month,uint32_t day)
797 if (year == 0 && month == 0 && day == 0)
799 delsum= (long) (365L * year+ 31*(month-1) +day);
803 delsum-= (long) (month*4+23)/10;
804 temp=(int) ((year/100+1)*3)/4;
805 return(delsum+(
int) year/4-temp);
832 void Time::convert(epoch_t &epoch,
long *my_timezone)
const
835 struct tm *l_time,tm_tmp;
842 type::Time tmp_time= *
this;
843 type::Time* t= &tmp_time;
845 if (not t->isValidEpoch())
901 #ifdef TIME_T_UNSIGNED
912 if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1)
919 if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12)
930 epoch= (type::epoch_t) (((calc_daynr((uint32_t) t->year, (uint32_t) t->month, (uint32_t) t->day) -
931 (
long) days_at_timestart)*86400L + (
long) t->hour*3600L +
932 (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
935 long current_timezone= my_time_zone;
936 util::gmtime(epoch, &tm_tmp);
940 (t->hour != (uint32_t) l_time->tm_hour ||
941 t->minute != (uint32_t) l_time->tm_min ||
942 t->second != (uint32_t) l_time->tm_sec);
946 int days= t->day - l_time->tm_mday;
951 diff=(3600L*(long) (days*24+((
int) t->hour - (
int) l_time->tm_hour)) +
952 (
long) (60*((
int) t->minute - (
int) l_time->tm_min)) +
953 (
long) ((
int) t->second - (
int) l_time->tm_sec));
954 current_timezone+= diff+3600;
955 epoch+= (time_t) diff;
956 util::gmtime(epoch, &tm_tmp);
969 if (loop == 2 && t->hour != (uint32_t) l_time->tm_hour)
971 int days= t->day - l_time->tm_mday;
976 diff=(3600L*(long) (days*24+((
int) t->hour - (
int) l_time->tm_hour))+
977 (
long) (60*((int) t->minute - (
int) l_time->tm_min)) +
978 (long) ((
int) t->second - (int) l_time->tm_sec));
980 epoch+=3600 - t->minute*60 - t->second;
981 else if (diff == -3600)
982 epoch-=t->minute*60 + t->second;
984 *my_timezone= current_timezone;
988 epoch+= shift*86400L;
998 if (epoch < TIMESTAMP_MIN_VALUE)
1005 void Time::store(
const struct tm &from)
1009 year= (int32_t) ((from.tm_year+1900) % 10000);
1010 month= (int32_t) from.tm_mon+1;
1011 day= (int32_t) from.tm_mday;
1012 hour= (int32_t) from.tm_hour;
1013 minute= (int32_t) from.tm_min;
1014 second= (int32_t) from.tm_sec;
1016 time_type= DRIZZLE_TIMESTAMP_DATETIME;
1019 void Time::store(
const struct timeval &from)
1021 store(from.tv_sec, (usec_t)from.tv_usec);
1022 time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
1026 void Time::store(type::epoch_t from)
1031 void Time::store(type::epoch_t from_arg, usec_t from_fractional_seconds)
1033 epoch_t from= from_arg;
1034 util::gmtime(from, *
this);
1038 second_part= from_fractional_seconds;
1039 time_type= DRIZZLE_TIMESTAMP_DATETIME;
1043 void Time::truncate(
const timestamp_t arg)
1045 assert(arg == type::DRIZZLE_TIMESTAMP_TIME);
1046 year= month= day= 0;
1051 void Time::convert(String &str, timestamp_t arg)
1053 str.alloc(MAX_STRING_LENGTH);
1054 size_t length= MAX_STRING_LENGTH;
1056 convert(str.c_ptr(), length, arg);
1059 str.set_charset(&my_charset_bin);
1062 void Time::convert(
char *str,
size_t &to_length, timestamp_t arg)
1066 case DRIZZLE_TIMESTAMP_DATETIME:
1067 length= snprintf(str, to_length,
1068 "%04" PRIu32
"-%02" PRIu32
"-%02" PRIu32
1069 " %02" PRIu32
":%02" PRIu32
":%02" PRIu32
".%06" PRIu32,
1079 case DRIZZLE_TIMESTAMP_DATE:
1080 length= snprintf(str, to_length,
"%04u-%02u-%02u",
1086 case DRIZZLE_TIMESTAMP_TIME:
1088 uint32_t extra_hours= 0;
1090 length= snprintf(str, to_length,
1099 case DRIZZLE_TIMESTAMP_NONE:
1100 case DRIZZLE_TIMESTAMP_ERROR:
1142 static int64_t number_to_datetime(int64_t nr, type::Time *time_res,
1143 uint32_t flags, type::cut_t &was_cut)
1147 was_cut= type::VALID;
1149 time_res->time_type=type::DRIZZLE_TIMESTAMP_DATE;
1151 if (nr == 0LL || nr >= 10000101000000LL)
1153 time_res->time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
1158 if (nr <= (YY_PART_YEAR-1)*10000L+1231L)
1160 nr= (nr+20000000L)*1000000L;
1163 if (nr < (YY_PART_YEAR)*10000L+101L)
1167 nr= (nr+19000000L)*1000000L;
1172 if (nr <= 99991231L)
1177 if (nr < 101000000L)
1180 time_res->time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
1182 if (nr <= (YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
1184 nr= nr + 20000000000000LL;
1187 if (nr < YY_PART_YEAR * 10000000000LL + 101000000LL)
1189 if (nr <= 991231235959LL)
1190 nr= nr + 19000000000000LL;
1193 part1=(long) (nr / 1000000LL);
1194 part2=(long) (nr - (int64_t) part1 * 1000000LL);
1195 time_res->year= (int) (part1/10000L); part1%=10000L;
1196 time_res->month= (int) part1 / 100;
1197 time_res->day= (int) part1 % 100;
1198 time_res->hour= (int) (part2/10000L); part2%=10000L;
1199 time_res->minute=(int) part2 / 100;
1200 time_res->second=(int) part2 % 100;
1202 if (time_res->year <= 9999 && time_res->month <= 12 &&
1203 time_res->day <= 31 && time_res->hour <= 23 &&
1204 time_res->minute <= 59 && time_res->second <= 59 &&
1205 not time_res->check((nr != 0), flags, was_cut))
1211 if (!nr && (flags & TIME_NO_ZERO_DATE))
1222 void Time::convert(datetime_t &ret, int64_t nr, uint32_t flags)
1224 type::cut_t was_cut;
1225 ret= number_to_datetime(nr,
this, flags, was_cut);
1228 void Time::convert(datetime_t &ret, int64_t nr, uint32_t flags, type::cut_t &was_cut)
1230 ret= number_to_datetime(nr,
this, flags, was_cut);
1240 void Time::convert(datetime_t &datetime, timestamp_t arg)
1245 case type::DRIZZLE_TIMESTAMP_DATETIME:
1246 datetime= ((int64_t) (year * 10000UL + month * 100UL + day) * 1000000ULL +
1247 (int64_t) (hour * 10000UL + minute * 100UL + second));
1251 case type::DRIZZLE_TIMESTAMP_DATE:
1252 datetime= (year * 10000UL + month * 100UL + day);
1256 case type::DRIZZLE_TIMESTAMP_TIME:
1257 datetime= (hour * 10000UL + minute * 100UL + second);
1260 case type::DRIZZLE_TIMESTAMP_NONE:
1261 case type::DRIZZLE_TIMESTAMP_ERROR:
static const uint32_t * days_in_month(uint32_t y, enum calendar c)