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