00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <config.h>
00017
00018 #include <drizzled/type/time.h>
00019
00020 #include <drizzled/util/gmtime.h>
00021
00022 #include <drizzled/internal/m_string.h>
00023 #include <drizzled/charset_info.h>
00024 #include <drizzled/util/test.h>
00025 #include <drizzled/definitions.h>
00026 #include <drizzled/sql_string.h>
00027
00028 #include <cstdio>
00029 #include <algorithm>
00030
00031 using namespace std;
00032
00033 namespace drizzled
00034 {
00035
00036 static int check_time_range(type::Time *my_time, int *warning);
00037
00038
00039
00040 uint64_t log_10_int[20]=
00041 {
00042 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL,
00043 100000000ULL, 1000000000ULL, 10000000000ULL, 100000000000ULL,
00044 1000000000000ULL, 10000000000000ULL, 100000000000000ULL,
00045 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL,
00046 1000000000000000000ULL, 10000000000000000000ULL
00047 };
00048
00049
00050
00051
00052 static unsigned char internal_format_positions[]=
00053 {0, 1, 2, 3, 4, 5, 6, (unsigned char) 255};
00054
00055 static char time_separator=':';
00056
00057 static uint32_t const days_at_timestart=719528;
00058 unsigned char days_in_month[]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
00059
00060
00061
00062
00063
00064 static long my_time_zone=0;
00065
00066
00067
00068
00069 uint32_t calc_days_in_year(uint32_t year)
00070 {
00071 return ((year & 3) == 0 && (year%100 || (year%400 == 0 && year)) ?
00072 366 : 365);
00073 }
00074
00075
00076 namespace type {
00098 bool Time::check(bool not_zero_date, uint32_t flags, type::cut_t &was_cut) const
00099 {
00100 if (not_zero_date)
00101 {
00102 if ((((flags & TIME_NO_ZERO_IN_DATE) || !(flags & TIME_FUZZY_DATE)) &&
00103 (month == 0 || day == 0)) ||
00104 (not (flags & TIME_INVALID_DATES) &&
00105 month && day > days_in_month[month-1] &&
00106 (month != 2 || calc_days_in_year(year) != 366 ||
00107 day != 29)))
00108 {
00109 was_cut= type::INVALID;
00110 return true;
00111 }
00112 }
00113 else if (flags & TIME_NO_ZERO_DATE)
00114 {
00115
00116
00117
00118
00119 return true;
00120 }
00121 return false;
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 #define MAX_DATE_PARTS 8
00176
00177 type::timestamp_t Time::store(const char *str, uint32_t length, uint32_t flags, type::cut_t &was_cut)
00178 {
00179 uint32_t field_length, year_length=4, digits, i, number_of_fields;
00180 uint32_t date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS];
00181 uint32_t add_hours= 0, start_loop;
00182 uint32_t not_zero_date, allow_space;
00183 bool is_internal_format;
00184 const char *pos, *last_field_pos=NULL;
00185 const char *end=str+length;
00186 const unsigned char *format_position;
00187 bool found_delimitier= 0, found_space= 0;
00188 uint32_t frac_pos, frac_len;
00189
00190 was_cut= type::VALID;
00191
00192
00193 for (; str != end && my_isspace(&my_charset_utf8_general_ci, *str) ; str++)
00194 ;
00195
00196 if (str == end || ! my_isdigit(&my_charset_utf8_general_ci, *str))
00197 {
00198 was_cut= type::CUT;
00199 return(type::DRIZZLE_TIMESTAMP_NONE);
00200 }
00201
00202 is_internal_format= 0;
00203
00204 format_position= internal_format_positions;
00205
00206
00207
00208
00209
00210
00211 for (pos=str;
00212 pos != end && (my_isdigit(&my_charset_utf8_general_ci,*pos) || *pos == 'T');
00213 pos++)
00214 ;
00215
00216 digits= (uint32_t) (pos-str);
00217 start_loop= 0;
00218 date_len[format_position[0]]= 0;
00219 if (pos == end || *pos == '.')
00220 {
00221
00222 year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
00223 field_length= year_length;
00224 is_internal_format= 1;
00225 format_position= internal_format_positions;
00226 }
00227 else
00228 {
00229 if (format_position[0] >= 3)
00230 {
00231
00232
00233
00234
00235
00236
00237 while (pos < end && !my_isspace(&my_charset_utf8_general_ci, *pos))
00238 pos++;
00239 while (pos < end && !my_isdigit(&my_charset_utf8_general_ci, *pos))
00240 pos++;
00241 if (pos == end)
00242 {
00243 if (flags & TIME_DATETIME_ONLY)
00244 {
00245 was_cut= type::CUT;
00246 return(type::DRIZZLE_TIMESTAMP_NONE);
00247 }
00248
00249 date[0]= date[1]= date[2]= date[3]= date[4]= 0;
00250 start_loop= 5;
00251 }
00252 }
00253
00254 field_length= format_position[0] == 0 ? 4 : 2;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 i= max((uint32_t) format_position[0], (uint32_t) format_position[1]);
00266 set_if_bigger(i, (uint32_t) format_position[2]);
00267 allow_space= ((1 << i) | (1 << format_position[6]));
00268 allow_space&= (1 | 2 | 4 | 8);
00269
00270 not_zero_date= 0;
00271 for (i = start_loop;
00272 i < MAX_DATE_PARTS-1 && str != end &&
00273 my_isdigit(&my_charset_utf8_general_ci,*str);
00274 i++)
00275 {
00276 const char *start= str;
00277 uint32_t tmp_value= (uint32_t) (unsigned char) (*str++ - '0');
00278 while (str != end && my_isdigit(&my_charset_utf8_general_ci,str[0]) &&
00279 (!is_internal_format || --field_length))
00280 {
00281 tmp_value=tmp_value*10 + (uint32_t) (unsigned char) (*str - '0');
00282 str++;
00283 }
00284 date_len[i]= (uint32_t) (str - start);
00285 if (tmp_value > 999999)
00286 {
00287 was_cut= type::CUT;
00288 return(type::DRIZZLE_TIMESTAMP_NONE);
00289 }
00290 date[i]=tmp_value;
00291 not_zero_date|= tmp_value;
00292
00293
00294 field_length= format_position[i+1] == 0 ? 4 : 2;
00295
00296 if ((last_field_pos= str) == end)
00297 {
00298 i++;
00299 break;
00300 }
00301
00302 if (i == format_position[2] && *str == 'T')
00303 {
00304 str++;
00305 continue;
00306 }
00307 if (i == format_position[5])
00308 {
00309 if (*str == '.')
00310 {
00311 str++;
00312 field_length= 6;
00313 }
00314 continue;
00315 }
00316 while (str != end &&
00317 (my_ispunct(&my_charset_utf8_general_ci,*str) ||
00318 my_isspace(&my_charset_utf8_general_ci,*str)))
00319 {
00320 if (my_isspace(&my_charset_utf8_general_ci,*str))
00321 {
00322 if (!(allow_space & (1 << i)))
00323 {
00324 was_cut= type::CUT;
00325 return(type::DRIZZLE_TIMESTAMP_NONE);
00326 }
00327 found_space= 1;
00328 }
00329 str++;
00330 found_delimitier= 1;
00331 }
00332
00333 if (i == format_position[6])
00334 {
00335 i++;
00336 if (format_position[7] != 255)
00337 {
00338 if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
00339 {
00340 if (str[0] == 'p' || str[0] == 'P')
00341 add_hours= 12;
00342 else if (str[0] != 'a' || str[0] != 'A')
00343 continue;
00344 str+= 2;
00345
00346 while (str != end && my_isspace(&my_charset_utf8_general_ci,*str))
00347 str++;
00348 }
00349 }
00350 }
00351 last_field_pos= str;
00352 }
00353 if (found_delimitier && !found_space && (flags & TIME_DATETIME_ONLY))
00354 {
00355 was_cut= type::CUT;
00356 return(type::DRIZZLE_TIMESTAMP_NONE);
00357 }
00358
00359 str= last_field_pos;
00360
00361 number_of_fields= i - start_loop;
00362 while (i < MAX_DATE_PARTS)
00363 {
00364 date_len[i]= 0;
00365 date[i++]= 0;
00366 }
00367
00368 do
00369 {
00370 if (not is_internal_format)
00371 {
00372 year_length= date_len[(uint32_t) format_position[0]];
00373 if (!year_length)
00374 {
00375 was_cut= type::CUT;
00376 return(type::DRIZZLE_TIMESTAMP_NONE);
00377 }
00378
00379 this->year= date[(uint32_t) format_position[0]];
00380 this->month= date[(uint32_t) format_position[1]];
00381 this->day= date[(uint32_t) format_position[2]];
00382 this->hour= date[(uint32_t) format_position[3]];
00383 this->minute= date[(uint32_t) format_position[4]];
00384 this->second= date[(uint32_t) format_position[5]];
00385
00386 frac_pos= (uint32_t) format_position[6];
00387 frac_len= date_len[frac_pos];
00388 if (frac_len < 6)
00389 date[frac_pos]*= (uint32_t) log_10_int[6 - frac_len];
00390 this->second_part= date[frac_pos];
00391
00392 if (format_position[7] != (unsigned char) 255)
00393 {
00394 if (this->hour > 12)
00395 {
00396 was_cut= type::CUT;
00397 break;
00398 }
00399 this->hour= this->hour%12 + add_hours;
00400 }
00401 }
00402 else
00403 {
00404 this->year= date[0];
00405 this->month= date[1];
00406 this->day= date[2];
00407 this->hour= date[3];
00408 this->minute= date[4];
00409 this->second= date[5];
00410 if (date_len[6] < 6)
00411 date[6]*= (uint32_t) log_10_int[6 - date_len[6]];
00412 this->second_part=date[6];
00413 }
00414 this->neg= 0;
00415
00416 if (year_length == 2 && not_zero_date)
00417 this->year+= (this->year < YY_PART_YEAR ? 2000 : 1900);
00418
00419 if (number_of_fields < 3 ||
00420 this->year > 9999 || this->month > 12 ||
00421 this->day > 31 || this->hour > 23 ||
00422 this->minute > 59 || this->second > 59)
00423 {
00424
00425 if (!not_zero_date)
00426 {
00427 for (; str != end ; str++)
00428 {
00429 if (!my_isspace(&my_charset_utf8_general_ci, *str))
00430 {
00431 not_zero_date= 1;
00432 break;
00433 }
00434 }
00435 }
00436 was_cut= test(not_zero_date) ? type::CUT : type::VALID;
00437 break;
00438 }
00439
00440 if (check(not_zero_date != 0, flags, was_cut))
00441 {
00442 break;
00443 }
00444
00445 this->time_type= (number_of_fields <= 3 ?
00446 type::DRIZZLE_TIMESTAMP_DATE : type::DRIZZLE_TIMESTAMP_DATETIME);
00447
00448 for (; str != end ; str++)
00449 {
00450 if (!my_isspace(&my_charset_utf8_general_ci,*str))
00451 {
00452 was_cut= type::CUT;
00453 break;
00454 }
00455 }
00456
00457 return(time_type= (number_of_fields <= 3 ? type::DRIZZLE_TIMESTAMP_DATE : type::DRIZZLE_TIMESTAMP_DATETIME));
00458 } while (0);
00459
00460 reset();
00461
00462 return type::DRIZZLE_TIMESTAMP_ERROR;
00463 }
00464
00465 type::timestamp_t Time::store(const char *str, uint32_t length, uint32_t flags)
00466 {
00467 type::cut_t was_cut;
00468 return store(str, length, flags, was_cut);
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 bool Time::store(const char *str, uint32_t length, int &warning, type::timestamp_t arg)
00497 {
00498 uint32_t date[5];
00499 uint64_t value;
00500 const char *end=str+length, *end_of_days;
00501 bool found_days,found_hours;
00502 uint32_t state;
00503
00504 assert(arg == DRIZZLE_TIMESTAMP_TIME);
00505
00506 this->neg=0;
00507 warning= 0;
00508 for (; str != end && my_isspace(&my_charset_utf8_general_ci,*str) ; str++)
00509 length--;
00510 if (str != end && *str == '-')
00511 {
00512 this->neg=1;
00513 str++;
00514 length--;
00515 }
00516 if (str == end)
00517 return true;
00518
00519
00520 if (length >= 12)
00521 {
00522 type::cut_t was_cut;
00523 type::timestamp_t res= this->store(str, length, (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut);
00524 if ((int) res >= (int) type::DRIZZLE_TIMESTAMP_ERROR)
00525 {
00526 if (was_cut != type::VALID)
00527 warning|= DRIZZLE_TIME_WARN_TRUNCATED;
00528
00529 return res == type::DRIZZLE_TIMESTAMP_ERROR;
00530 }
00531 }
00532
00533
00534 for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++)
00535 value=value*10L + (long) (*str - '0');
00536
00537
00538 end_of_days= str;
00539 for (; str != end && my_isspace(&my_charset_utf8_general_ci, str[0]) ; str++)
00540 ;
00541
00542 found_days=found_hours=0;
00543 if ((uint32_t) (end-str) > 1 && str != end_of_days &&
00544 my_isdigit(&my_charset_utf8_general_ci, *str))
00545 {
00546 date[0]= (uint32_t) value;
00547 state= 1;
00548 found_days= 1;
00549 }
00550 else if ((end-str) > 1 && *str == time_separator &&
00551 my_isdigit(&my_charset_utf8_general_ci, str[1]))
00552 {
00553 date[0]= 0;
00554 date[1]= (uint32_t) value;
00555 state=2;
00556 found_hours=1;
00557 str++;
00558 }
00559 else
00560 {
00561
00562 date[0]= 0;
00563 date[1]= (uint32_t) (value/10000);
00564 date[2]= (uint32_t) (value/100 % 100);
00565 date[3]= (uint32_t) (value % 100);
00566 state=4;
00567 goto fractional;
00568 }
00569
00570
00571 for (;;)
00572 {
00573 for (value=0; str != end && my_isdigit(&my_charset_utf8_general_ci,*str) ; str++)
00574 value=value*10L + (long) (*str - '0');
00575 date[state++]= (uint32_t) value;
00576 if (state == 4 || (end-str) < 2 || *str != time_separator ||
00577 !my_isdigit(&my_charset_utf8_general_ci,str[1]))
00578 break;
00579 str++;
00580 }
00581
00582 if (state != 4)
00583 {
00584
00585 if (!found_hours && !found_days)
00586 {
00587 internal::bmove_upp((unsigned char*) (date+4), (unsigned char*) (date+state),
00588 sizeof(long)*(state-1));
00589 memset(date, 0, sizeof(long)*(4-state));
00590 }
00591 else
00592 memset(date+state, 0, sizeof(long)*(4-state));
00593 }
00594
00595 fractional:
00596
00597 if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_utf8_general_ci,str[1]))
00598 {
00599 int field_length= 5;
00600 str++; value=(uint32_t) (unsigned char) (*str - '0');
00601 while (++str != end && my_isdigit(&my_charset_utf8_general_ci, *str))
00602 {
00603 if (field_length-- > 0)
00604 value= value*10 + (uint32_t) (unsigned char) (*str - '0');
00605 }
00606 if (field_length > 0)
00607 {
00608 value*= (long) log_10_int[field_length];
00609 }
00610 else if (field_length < 0)
00611 {
00612 warning|= DRIZZLE_TIME_WARN_TRUNCATED;
00613 }
00614
00615 date[4]= (uint32_t) value;
00616 }
00617 else
00618 {
00619 date[4]=0;
00620 }
00621
00622
00623
00624 if ((end - str) > 1 &&
00625 (*str == 'e' || *str == 'E') &&
00626 (my_isdigit(&my_charset_utf8_general_ci, str[1]) ||
00627 ((str[1] == '-' || str[1] == '+') &&
00628 (end - str) > 2 &&
00629 my_isdigit(&my_charset_utf8_general_ci, str[2]))))
00630 return 1;
00631
00632 if (internal_format_positions[7] != 255)
00633 {
00634
00635 while (str != end && my_isspace(&my_charset_utf8_general_ci, *str))
00636 str++;
00637 if (str+2 <= end && (str[1] == 'M' || str[1] == 'm'))
00638 {
00639 if (str[0] == 'p' || str[0] == 'P')
00640 {
00641 str+= 2;
00642 date[1]= date[1]%12 + 12;
00643 }
00644 else if (str[0] == 'a' || str[0] == 'A')
00645 str+=2;
00646 }
00647 }
00648
00649
00650 if (date[0] > UINT_MAX || date[1] > UINT_MAX ||
00651 date[2] > UINT_MAX || date[3] > UINT_MAX ||
00652 date[4] > UINT_MAX)
00653 return 1;
00654
00655 this->year= 0;
00656 this->month= 0;
00657 this->day= date[0];
00658 this->hour= date[1];
00659 this->minute= date[2];
00660 this->second= date[3];
00661 this->second_part= date[4];
00662 this->time_type= type::DRIZZLE_TIMESTAMP_TIME;
00663
00664
00665 if (check_time_range(this, &warning))
00666 {
00667 return 1;
00668 }
00669
00670
00671 if (str != end)
00672 {
00673 do
00674 {
00675 if (!my_isspace(&my_charset_utf8_general_ci,*str))
00676 {
00677 warning|= DRIZZLE_TIME_WARN_TRUNCATED;
00678 break;
00679 }
00680 } while (++str != end);
00681 }
00682 return 0;
00683 }
00684
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 static int check_time_range(type::Time *my_time, int *warning)
00708 {
00709 int64_t hour;
00710
00711 if (my_time->minute >= 60 || my_time->second >= 60)
00712 return 1;
00713
00714 hour= my_time->hour + (24*my_time->day);
00715 if (hour <= TIME_MAX_HOUR &&
00716 (hour != TIME_MAX_HOUR || my_time->minute != TIME_MAX_MINUTE ||
00717 my_time->second != TIME_MAX_SECOND || !my_time->second_part))
00718 return 0;
00719
00720 my_time->day= 0;
00721 my_time->hour= TIME_MAX_HOUR;
00722 my_time->minute= TIME_MAX_MINUTE;
00723 my_time->second= TIME_MAX_SECOND;
00724 my_time->second_part= 0;
00725 *warning|= DRIZZLE_TIME_WARN_OUT_OF_RANGE;
00726 return 0;
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736 void init_time(void)
00737 {
00738 time_t seconds;
00739 struct tm *l_time,tm_tmp;
00740 type::Time my_time;
00741 type::Time::epoch_t epoch;
00742 bool not_used;
00743
00744 seconds= (time_t) time((time_t*) 0);
00745 localtime_r(&seconds, &tm_tmp);
00746 l_time= &tm_tmp;
00747 my_time_zone= 3600;
00748 my_time.year= (uint32_t) l_time->tm_year+1900;
00749 my_time.month= (uint32_t) l_time->tm_mon+1;
00750 my_time.day= (uint32_t) l_time->tm_mday;
00751 my_time.hour= (uint32_t) l_time->tm_hour;
00752 my_time.minute= (uint32_t) l_time->tm_min;
00753 my_time.second= (uint32_t) l_time->tm_sec;
00754 my_time.time_type= type::DRIZZLE_TIMESTAMP_NONE;
00755 my_time.second_part= 0;
00756 my_time.neg= false;
00757 my_time.convert(epoch, &my_time_zone, ¬_used);
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772 uint32_t year_2000_handling(uint32_t year)
00773 {
00774 if ((year=year+1900) < 1900+YY_PART_YEAR)
00775 year+=100;
00776 return year;
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 long calc_daynr(uint32_t year,uint32_t month,uint32_t day)
00796 {
00797 long delsum;
00798 int temp;
00799
00800 if (year == 0 && month == 0 && day == 0)
00801 return(0);
00802 delsum= (long) (365L * year+ 31*(month-1) +day);
00803 if (month <= 2)
00804 year--;
00805 else
00806 delsum-= (long) (month*4+23)/10;
00807 temp=(int) ((year/100+1)*3)/4;
00808 return(delsum+(int) year/4-temp);
00809 }
00810
00811
00812 namespace type {
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 void Time::convert(epoch_t &epoch, long *my_timezone, bool *in_dst_time_gap, bool skip_timezone) const
00836 {
00837 uint32_t loop;
00838 int shift= 0;
00839 type::Time tmp_time;
00840 type::Time *t= &tmp_time;
00841 struct tm *l_time,tm_tmp;
00842 long diff, current_timezone;
00843
00844
00845
00846
00847
00848 tmp_time= *this;
00849
00850 if (not t->isValidEpoch())
00851 {
00852 epoch= 0;
00853 return;
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 #ifdef TIME_T_UNSIGNED
00907 {
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917 if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1)
00918 && (t->day <= 10))
00919 {
00920 t->day+= 2;
00921 shift= -2;
00922 }
00923
00924 if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12)
00925 && (t->day == 31))
00926 {
00927 t->year++;
00928 t->month= 1;
00929 t->day= 2;
00930 shift= -2;
00931 }
00932 }
00933 #endif
00934
00935 epoch= (type::Time::epoch_t) (((calc_daynr((uint32_t) t->year, (uint32_t) t->month, (uint32_t) t->day) -
00936 (long) days_at_timestart)*86400L + (long) t->hour*3600L +
00937 (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
00938 3600);
00939
00940 current_timezone= my_time_zone;
00941 if (skip_timezone)
00942 {
00943 util::gmtime(epoch, &tm_tmp);
00944 }
00945 else
00946 {
00947 util::localtime(epoch, &tm_tmp);
00948 }
00949
00950 l_time= &tm_tmp;
00951 for (loop=0;
00952 loop < 2 &&
00953 (t->hour != (uint32_t) l_time->tm_hour ||
00954 t->minute != (uint32_t) l_time->tm_min ||
00955 t->second != (uint32_t) l_time->tm_sec);
00956 loop++)
00957 {
00958
00959 int days= t->day - l_time->tm_mday;
00960 if (days < -1)
00961 days= 1;
00962 else if (days > 1)
00963 days= -1;
00964 diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
00965 (long) (60*((int) t->minute - (int) l_time->tm_min)) +
00966 (long) ((int) t->second - (int) l_time->tm_sec));
00967 current_timezone+= diff+3600;
00968 epoch+= (time_t) diff;
00969 if (skip_timezone)
00970 {
00971 util::gmtime(epoch, &tm_tmp);
00972 }
00973 else
00974 {
00975 util::localtime(epoch, &tm_tmp);
00976 }
00977 l_time=&tm_tmp;
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 if (loop == 2 && t->hour != (uint32_t) l_time->tm_hour)
00990 {
00991 int days= t->day - l_time->tm_mday;
00992 if (days < -1)
00993 days=1;
00994 else if (days > 1)
00995 days= -1;
00996 diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour))+
00997 (long) (60*((int) t->minute - (int) l_time->tm_min)) +
00998 (long) ((int) t->second - (int) l_time->tm_sec));
00999 if (diff == 3600)
01000 epoch+=3600 - t->minute*60 - t->second;
01001 else if (diff == -3600)
01002 epoch-=t->minute*60 + t->second;
01003
01004 *in_dst_time_gap= true;
01005 }
01006 *my_timezone= current_timezone;
01007
01008
01009
01010 epoch+= shift*86400L;
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 if (epoch < TIMESTAMP_MIN_VALUE)
01021 {
01022 epoch= 0;
01023 }
01024 }
01025
01026
01027 void Time::store(const struct tm &from)
01028 {
01029 _is_local_time= false;
01030 neg= 0;
01031 second_part= 0;
01032 year= (int32_t) ((from.tm_year+1900) % 10000);
01033 month= (int32_t) from.tm_mon+1;
01034 day= (int32_t) from.tm_mday;
01035 hour= (int32_t) from.tm_hour;
01036 minute= (int32_t) from.tm_min;
01037 second= (int32_t) from.tm_sec;
01038
01039 time_type= DRIZZLE_TIMESTAMP_DATETIME;
01040 }
01041
01042 void Time::store(const struct timeval &from)
01043 {
01044 store(from.tv_sec, (usec_t)from.tv_usec);
01045 time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
01046 }
01047
01048
01049 void Time::store(const type::Time::epoch_t &from, bool use_localtime)
01050 {
01051 store(from, 0, use_localtime);
01052 }
01053
01054 void Time::store(const type::Time::epoch_t &from_arg, const usec_t &from_fractional_seconds, bool use_localtime)
01055 {
01056 epoch_t from= from_arg;
01057
01058 if (use_localtime)
01059 {
01060 util::localtime(from, *this);
01061 _is_local_time= true;
01062 }
01063 else
01064 {
01065 util::gmtime(from, *this);
01066 }
01067
01068
01069
01070 second_part= from_fractional_seconds;
01071 time_type= DRIZZLE_TIMESTAMP_DATETIME;
01072 }
01073
01074
01075 void Time::truncate(const timestamp_t arg)
01076 {
01077 assert(arg == type::DRIZZLE_TIMESTAMP_TIME);
01078 year= month= day= 0;
01079
01080 time_type= arg;
01081 }
01082
01083 void Time::convert(String &str, timestamp_t arg)
01084 {
01085 str.alloc(MAX_STRING_LENGTH);
01086 size_t length= MAX_STRING_LENGTH;
01087
01088 convert(str.c_ptr(), length, arg);
01089
01090 str.length(length);
01091 str.set_charset(&my_charset_bin);
01092 }
01093
01094 void Time::convert(char *str, size_t &to_length, timestamp_t arg)
01095 {
01096 int32_t length= 0;
01097 switch (arg) {
01098 case DRIZZLE_TIMESTAMP_DATETIME:
01099 length= snprintf(str, to_length,
01100 "%04" PRIu32 "-%02" PRIu32 "-%02" PRIu32
01101 " %02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ".%06" PRIu32,
01102 year,
01103 month,
01104 day,
01105 hour,
01106 minute,
01107 second,
01108 second_part);
01109 break;
01110
01111 case DRIZZLE_TIMESTAMP_DATE:
01112 length= snprintf(str, to_length, "%04u-%02u-%02u",
01113 year,
01114 month,
01115 day);
01116 break;
01117
01118 case DRIZZLE_TIMESTAMP_TIME:
01119 {
01120 uint32_t extra_hours= 0;
01121
01122 length= snprintf(str, to_length,
01123 "%s%02u:%02u:%02u",
01124 (neg ? "-" : ""),
01125 extra_hours+ hour,
01126 minute,
01127 second);
01128 }
01129 break;
01130
01131 case DRIZZLE_TIMESTAMP_NONE:
01132 case DRIZZLE_TIMESTAMP_ERROR:
01133 assert(0);
01134 break;
01135 }
01136
01137 if (length < 0)
01138 {
01139 to_length= 0;
01140 return;
01141 }
01142
01143 to_length= length;
01144 }
01145
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 static int64_t number_to_datetime(int64_t nr, type::Time *time_res,
01175 uint32_t flags, type::cut_t &was_cut)
01176 {
01177 long part1,part2;
01178
01179 was_cut= type::VALID;
01180 time_res->reset();
01181 time_res->time_type=type::DRIZZLE_TIMESTAMP_DATE;
01182
01183 if (nr == 0LL || nr >= 10000101000000LL)
01184 {
01185 time_res->time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
01186 goto ok;
01187 }
01188 if (nr < 101)
01189 goto err;
01190 if (nr <= (YY_PART_YEAR-1)*10000L+1231L)
01191 {
01192 nr= (nr+20000000L)*1000000L;
01193 goto ok;
01194 }
01195 if (nr < (YY_PART_YEAR)*10000L+101L)
01196 goto err;
01197 if (nr <= 991231L)
01198 {
01199 nr= (nr+19000000L)*1000000L;
01200 goto ok;
01201 }
01202 if (nr < 10000101L)
01203 goto err;
01204 if (nr <= 99991231L)
01205 {
01206 nr= nr*1000000L;
01207 goto ok;
01208 }
01209 if (nr < 101000000L)
01210 goto err;
01211
01212 time_res->time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
01213
01214 if (nr <= (YY_PART_YEAR-1) * 10000000000LL + 1231235959LL)
01215 {
01216 nr= nr + 20000000000000LL;
01217 goto ok;
01218 }
01219 if (nr < YY_PART_YEAR * 10000000000LL + 101000000LL)
01220 goto err;
01221 if (nr <= 991231235959LL)
01222 nr= nr + 19000000000000LL;
01223
01224 ok:
01225 part1=(long) (nr / 1000000LL);
01226 part2=(long) (nr - (int64_t) part1 * 1000000LL);
01227 time_res->year= (int) (part1/10000L); part1%=10000L;
01228 time_res->month= (int) part1 / 100;
01229 time_res->day= (int) part1 % 100;
01230 time_res->hour= (int) (part2/10000L); part2%=10000L;
01231 time_res->minute=(int) part2 / 100;
01232 time_res->second=(int) part2 % 100;
01233
01234 if (time_res->year <= 9999 && time_res->month <= 12 &&
01235 time_res->day <= 31 && time_res->hour <= 23 &&
01236 time_res->minute <= 59 && time_res->second <= 59 &&
01237 not time_res->check((nr != 0), flags, was_cut))
01238 {
01239 return nr;
01240 }
01241
01242
01243 if (!nr && (flags & TIME_NO_ZERO_DATE))
01244 return -1LL;
01245
01246 err:
01247 was_cut= type::CUT;
01248 return -1LL;
01249 }
01250
01251
01252 namespace type {
01253
01254 void Time::convert(datetime_t &ret, int64_t nr, uint32_t flags)
01255 {
01256 type::cut_t was_cut;
01257 ret= number_to_datetime(nr, this, flags, was_cut);
01258 }
01259
01260 void Time::convert(datetime_t &ret, int64_t nr, uint32_t flags, type::cut_t &was_cut)
01261 {
01262 ret= number_to_datetime(nr, this, flags, was_cut);
01263 }
01264
01265
01266
01267
01268
01269
01270
01271
01272 void Time::convert(datetime_t &datetime, timestamp_t arg)
01273 {
01274 switch (arg)
01275 {
01276
01277 case type::DRIZZLE_TIMESTAMP_DATETIME:
01278 datetime= ((int64_t) (year * 10000UL + month * 100UL + day) * 1000000ULL +
01279 (int64_t) (hour * 10000UL + minute * 100UL + second));
01280 break;
01281
01282
01283 case type::DRIZZLE_TIMESTAMP_DATE:
01284 datetime= (year * 10000UL + month * 100UL + day);
01285 break;
01286
01287
01288 case type::DRIZZLE_TIMESTAMP_TIME:
01289 datetime= (hour * 10000UL + minute * 100UL + second);
01290 break;
01291
01292 case type::DRIZZLE_TIMESTAMP_NONE:
01293 case type::DRIZZLE_TIMESTAMP_ERROR:
01294 datetime= 0;
01295 }
01296 }
01297
01298 }
01299
01300 }