00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00036 #include "OWBI1_config.h"
00037 #include "OWBI1_DateTime.hpp"
00038 #include "OWBI1_String.hpp"
00039 #include "OWBI1_Array.hpp"
00040 #include "OW_BinarySerialization.hpp"
00041 #include "OW_Format.hpp"
00042 #include "OW_Mutex.hpp"
00043 #include "OW_MutexLock.hpp"
00044 #include "OW_ExceptionIds.hpp"
00045
00046 #if defined(OWBI1_HAVE_ISTREAM) && defined(OWBI1_HAVE_OSTREAM)
00047 #include <istream>
00048 #include <ostream>
00049 #else
00050 #include <iostream>
00051 #endif
00052
00053 #include <time.h>
00054 #ifdef OWBI1_HAVE_SYS_TIME_H
00055 #include <sys/time.h>
00056 #endif
00057
00058 #include <cctype>
00059
00060
00061 #ifndef OWBI1_HAVE_LOCALTIME_R
00062 namespace
00063 {
00064 OWBI1::Mutex localtimeMutex;
00065 }
00066 struct tm *localtime_r(const time_t *timep, struct tm *result)
00067 {
00068 OWBI1::MutexLock lock(localtimeMutex);
00069 struct tm *p = localtime(timep);
00070
00071 if (p)
00072 {
00073 *(result) = *p;
00074 }
00075
00076 return p;
00077 }
00078 #endif
00079
00080 #ifndef OWBI1_HAVE_GMTIME_R
00081 namespace
00082 {
00083 OWBI1::Mutex gmtimeMutex;
00084 }
00085 struct tm *gmtime_r(const time_t *timep, struct tm *result)
00086 {
00087 OWBI1::MutexLock lock(gmtimeMutex);
00088 struct tm *p = gmtime(timep);
00089
00090 if (p)
00091 {
00092 *(result) = *p;
00093 }
00094
00095 return p;
00096 }
00097 #endif
00098
00099 namespace OWBI1
00100 {
00101
00102 using namespace detail;
00103 using std::istream;
00104 using std::ostream;
00106 OWBI1_DEFINE_EXCEPTION_WITH_ID(DateTime);
00107
00109 DateTime::DateTime()
00110 : m_time(0)
00111 , m_microseconds(0)
00112
00113 {
00114 }
00116 namespace
00117 {
00118
00119 inline void badDateTime(const String& str)
00120 {
00121 OWBI1_THROW(DateTimeException, Format("Invalid DateTime: %1", str).c_str());
00122 }
00123
00124 inline void validateRanges(Int32 year, Int32 month, Int32 day, Int32 hour,
00125 Int32 minute, Int32 second, Int32 microseconds, const String& str)
00126 {
00127 if (year < 0 || year > 9999 ||
00128 month < 1 || month > 12 ||
00129 day < 1 || day > 31 ||
00130 hour < 0 || hour > 23 ||
00131 minute < 0 || minute > 59 ||
00132 second < 0 || second > 60 ||
00133 microseconds < 0 || microseconds > 999999)
00134 {
00135 badDateTime(str);
00136 }
00137 }
00138
00139 inline bool isDOWValid(const char* str)
00140 {
00141
00142 bool good = true;
00143 if (str[0] == 'S')
00144 {
00145 if (str[1] == 'u')
00146 {
00147 if (str[2] != 'n')
00148 {
00149 good = false;
00150 }
00151 }
00152 else if (str[1] == 'a')
00153 {
00154 if (str[2] != 't')
00155 {
00156 good = false;
00157 }
00158 }
00159 else
00160 {
00161 good = false;
00162 }
00163 }
00164 else if (str[0] == 'M')
00165 {
00166 if (str[1] == 'o')
00167 {
00168 if (str[2] != 'n')
00169 {
00170 good = false;
00171 }
00172 }
00173 else
00174 {
00175 good = false;
00176 }
00177 }
00178 else if (str[0] == 'T')
00179 {
00180 if (str[1] == 'u')
00181 {
00182 if (str[2] != 'e')
00183 {
00184 good = false;
00185 }
00186 }
00187 else if (str[1] == 'h')
00188 {
00189 if (str[2] != 'u')
00190 {
00191 good = false;
00192 }
00193 }
00194 else
00195 {
00196 good = false;
00197 }
00198 }
00199 else if (str[0] == 'W')
00200 {
00201 if (str[1] == 'e')
00202 {
00203 if (str[2] != 'd')
00204 {
00205 good = false;
00206 }
00207 }
00208 else
00209 {
00210 good = false;
00211 }
00212 }
00213 else if (str[0] == 'F')
00214 {
00215 if (str[1] == 'r')
00216 {
00217 if (str[2] != 'i')
00218 {
00219 good = false;
00220 }
00221 }
00222 else
00223 {
00224 good = false;
00225 }
00226 }
00227 else
00228 {
00229 good = false;
00230 }
00231
00232 return good;
00233 }
00234
00235 inline bool isLongDOWValid(const String& s)
00236 {
00237 if ( (s == "Sunday") ||
00238 (s == "Monday") ||
00239 (s == "Tuesday") ||
00240 (s == "Wednesday") ||
00241 (s == "Thursday") ||
00242 (s == "Friday") ||
00243 (s == "Saturday") )
00244 {
00245 return true;
00246 }
00247 return false;
00248 }
00249
00250
00251 inline int decodeShortMonth(const char* str)
00252 {
00253
00254 if (str[0] == 'J')
00255 {
00256 if (str[1] == 'a')
00257 {
00258 if (str[2] == 'n')
00259 {
00260 return 1;
00261 }
00262 }
00263 else if (str[1] == 'u')
00264 {
00265 if (str[2] == 'n')
00266 {
00267 return 6;
00268 }
00269 else if (str[2] == 'l')
00270 {
00271 return 7;
00272 }
00273 }
00274 }
00275 else if (str[0] == 'F')
00276 {
00277 if (str[1] == 'e' && str[2] == 'b')
00278 {
00279 return 2;
00280 }
00281 }
00282 else if (str[0] == 'M')
00283 {
00284 if (str[1] == 'a')
00285 {
00286 if (str[2] == 'r')
00287 {
00288 return 3;
00289 }
00290 else if (str[2] == 'y')
00291 {
00292 return 5;
00293 }
00294 }
00295 }
00296 else if (str[0] == 'A')
00297 {
00298 if (str[1] == 'p')
00299 {
00300 if (str[2] == 'r')
00301 {
00302 return 4;
00303 }
00304 }
00305 else if (str[1] == 'u')
00306 {
00307 if (str[2] == 'g')
00308 {
00309 return 8;
00310 }
00311 }
00312 }
00313 else if (str[0] == 'S')
00314 {
00315 if (str[1] == 'e' && str[2] == 'p')
00316 {
00317 return 9;
00318 }
00319 }
00320 else if (str[0] == 'O')
00321 {
00322 if (str[1] == 'c' && str[2] == 't')
00323 {
00324 return 10;
00325 }
00326 }
00327 else if (str[0] == 'N')
00328 {
00329 if (str[1] == 'o' && str[2] == 'v')
00330 {
00331 return 11;
00332 }
00333 }
00334 else if (str[0] == 'D')
00335 {
00336 if (str[1] == 'e' && str[2] == 'c')
00337 {
00338 return 12;
00339 }
00340 }
00341
00342 return -1;
00343 }
00344
00345
00346 inline int decodeLongMonth(const String& str)
00347 {
00348 if ( str.equals("January") )
00349 {
00350 return 1;
00351 }
00352 else if ( str.equals("February") )
00353 {
00354 return 2;
00355 }
00356 else if ( str.equals("March") )
00357 {
00358 return 3;
00359 }
00360 else if ( str.equals("April") )
00361 {
00362 return 4;
00363 }
00364 else if ( str.equals("May") )
00365 {
00366 return 5;
00367 }
00368 else if ( str.equals("June") )
00369 {
00370 return 6;
00371 }
00372 else if ( str.equals("July") )
00373 {
00374 return 7;
00375 }
00376 else if ( str.equals("August") )
00377 {
00378 return 8;
00379 }
00380 else if ( str.equals("September") )
00381 {
00382 return 9;
00383 }
00384 else if ( str.equals("October") )
00385 {
00386 return 10;
00387 }
00388 else if ( str.equals("November") )
00389 {
00390 return 11;
00391 }
00392 else if ( str.equals("December") )
00393 {
00394 return 12;
00395 }
00396 return -1;
00397 }
00398
00399
00400
00401
00402 const int LOCAL_TIME_OFFSET = -24;
00403 bool getTimeZoneOffset(const String& timezone, int& offset)
00404 {
00405 int temp_offset = LOCAL_TIME_OFFSET -1;
00406 if ( timezone.length() == 1 )
00407 {
00408
00409
00410
00411 switch ( timezone[0] )
00412 {
00413 case 'Y':
00414 temp_offset = -12;
00415 break;
00416 case 'X':
00417 temp_offset = -11;
00418 break;
00419 case 'W':
00420 temp_offset = -10;
00421 break;
00422 case 'V':
00423 temp_offset = -9;
00424 break;
00425 case 'U':
00426 temp_offset = -8;
00427 break;
00428 case 'T':
00429 temp_offset = -7;
00430 break;
00431 case 'S':
00432 temp_offset = -6;
00433 break;
00434 case 'R':
00435 temp_offset = -5;
00436 break;
00437 case 'Q':
00438 temp_offset = -4;
00439 break;
00440 case 'P':
00441 temp_offset = -3;
00442 break;
00443 case 'O':
00444 temp_offset = -2;
00445 break;
00446 case 'N':
00447 temp_offset = -1;
00448 break;
00449 case 'Z':
00450 temp_offset = 0;
00451 break;
00452 case 'A':
00453 temp_offset = 1;
00454 break;
00455 case 'B':
00456 temp_offset = 2;
00457 break;
00458 case 'C':
00459 temp_offset = 3;
00460 break;
00461 case 'D':
00462 temp_offset = 4;
00463 break;
00464 case 'E':
00465 temp_offset = 5;
00466 break;
00467 case 'F':
00468 temp_offset = 6;
00469 break;
00470 case 'G':
00471 temp_offset = 7;
00472 break;
00473 case 'H':
00474 temp_offset = 8;
00475 break;
00476 case 'I':
00477 temp_offset = 9;
00478 break;
00479 case 'K':
00480 temp_offset = 10;
00481 break;
00482 case 'L':
00483 temp_offset = 11;
00484 break;
00485 case 'M':
00486 temp_offset = 12;
00487 break;
00488 case 'J':
00489 temp_offset = LOCAL_TIME_OFFSET;
00490 break;
00491 default:
00492 break;
00493 }
00494 }
00495 else if ( timezone == "UTC" )
00496 {
00497 temp_offset = 0;
00498 }
00499
00500 else if ( timezone == "GMT" )
00501 {
00502 temp_offset = 0;
00503 }
00504 else if ( timezone == "BST" )
00505 {
00506 temp_offset = 1;
00507 }
00508 else if ( timezone == "IST" )
00509 {
00510 temp_offset = 1;
00511 }
00512 else if ( timezone == "WET" )
00513 {
00514 temp_offset = 0;
00515 }
00516 else if ( timezone == "WEST" )
00517 {
00518 temp_offset = 1;
00519 }
00520 else if ( timezone == "CET" )
00521 {
00522 temp_offset = 1;
00523 }
00524 else if ( timezone == "CEST" )
00525 {
00526 temp_offset = 2;
00527 }
00528 else if ( timezone == "EET" )
00529 {
00530 temp_offset = 2;
00531 }
00532 else if ( timezone == "EEST" )
00533 {
00534 temp_offset = 3;
00535 }
00536 else if ( timezone == "MSK" )
00537 {
00538 temp_offset = 3;
00539 }
00540 else if ( timezone == "MSD" )
00541 {
00542 temp_offset = 4;
00543 }
00544
00545 else if ( timezone == "AST" )
00546 {
00547 temp_offset = -4;
00548 }
00549 else if ( timezone == "ADT" )
00550 {
00551 temp_offset = -3;
00552 }
00553 else if ( timezone == "EST" )
00554 {
00555
00556
00557 temp_offset = -5;
00558 }
00559 else if ( timezone == "EDT" )
00560 {
00561 temp_offset = -4;
00562 }
00563 else if ( timezone == "ET" )
00564
00565 {
00566
00567 temp_offset = -5;
00568 }
00569 else if ( timezone == "CST" )
00570 {
00571
00572 temp_offset = -6;
00573 }
00574 else if ( timezone == "CDT" )
00575 {
00576 temp_offset = -5;
00577 }
00578 else if ( timezone == "CT" )
00579
00580 {
00581
00582 temp_offset = -6;
00583 }
00584 else if ( timezone == "MST" )
00585 {
00586 temp_offset = -7;
00587 }
00588 else if ( timezone == "MDT" )
00589 {
00590 temp_offset = -6;
00591 }
00592 else if ( timezone == "MT" )
00593
00594 {
00595
00596 temp_offset = -7;
00597 }
00598 else if ( timezone == "PST" )
00599 {
00600 temp_offset = -8;
00601 }
00602 else if ( timezone == "PDT" )
00603 {
00604 temp_offset = -7;
00605 }
00606 else if ( timezone == "PT" )
00607
00608 {
00609
00610 temp_offset = -8;
00611 }
00612 else if ( timezone == "HST" )
00613 {
00614 temp_offset = -10;
00615 }
00616 else if ( timezone == "AKST" )
00617 {
00618 temp_offset = -9;
00619 }
00620 else if ( timezone == "AKDT" )
00621 {
00622 temp_offset = -8;
00623 }
00624
00625 else if ( timezone == "WST" )
00626 {
00627 temp_offset = 8;
00628 }
00629
00630
00631 if ( temp_offset >= LOCAL_TIME_OFFSET )
00632 {
00633 offset = temp_offset;
00634 return true;
00635 }
00636 return false;
00637 }
00638
00639 Int32 getDaysPerMonth(Int32 year, Int32 month)
00640 {
00641 const Int32 normal_days_per_month[12] =
00642 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00643
00644 if ( (month >= 1) && (month <= 12) )
00645 {
00646 if ( month != 2 )
00647 {
00648 return normal_days_per_month[month - 1];
00649 }
00650
00651 int leap_year_adjust = 0;
00652
00653 if ( (year % 4) == 0 )
00654 {
00655
00656 if ( (year % 100) == 0 )
00657 {
00658 if ( (year % 400) == 0 )
00659 {
00660 leap_year_adjust = 1;
00661 }
00662 }
00663 else
00664 {
00665 leap_year_adjust = 1;
00666 }
00667 }
00668
00669 return normal_days_per_month[month - 1] + leap_year_adjust;
00670
00671 }
00672 return 0;
00673 }
00674
00675
00676
00677
00678
00679 void adjustTimeForTimeZone(Int32 timezone_offset, Int32& year, Int32& month,
00680 Int32& day, Int32& hour)
00681 {
00682 if ( timezone_offset < 0 )
00683 {
00684 hour -= timezone_offset;
00685
00686 if ( hour > 23 )
00687 {
00688 ++day;
00689 hour -= 24;
00690 }
00691
00692 if ( day > getDaysPerMonth(year, month) )
00693 {
00694 ++month;
00695 day = 1;
00696 }
00697 if ( month > 12 )
00698 {
00699 month -= 12;
00700 ++year;
00701 }
00702 }
00703 else if ( timezone_offset > 0 )
00704 {
00705 hour -= timezone_offset;
00706
00707 if ( hour < 0 )
00708 {
00709 --day;
00710 hour += 24;
00711 }
00712
00713 if ( day < 1 )
00714 {
00715 --month;
00716 day += getDaysPerMonth(year, month);
00717 }
00718 if ( month < 1 )
00719 {
00720 month += 12;
00721 --year;
00722 }
00723 }
00724 }
00725
00726
00727 }
00728
00730 DateTime::DateTime(const String& str)
00731 {
00732
00733 if ( str.length() == 25 )
00734 {
00735
00736 if ( !(str[14] != '.' || (str[21] != '+' && str[21] != '-')) )
00737 {
00738 try
00739 {
00740
00741
00742
00743 String strNoAsterisks(str);
00744 for (size_t i = 0; i < strNoAsterisks.length(); ++i)
00745 {
00746 if (strNoAsterisks[i] == '*')
00747 {
00748 strNoAsterisks[i] = '0';
00749 }
00750 }
00751 Int32 year = strNoAsterisks.substring(0, 4).toInt32();
00752 Int32 month = strNoAsterisks.substring(4, 2).toInt32();
00753 Int32 day = strNoAsterisks.substring(6, 2).toInt32();
00754 Int32 hour = strNoAsterisks.substring(8, 2).toInt32();
00755 Int32 minute = strNoAsterisks.substring(10, 2).toInt32();
00756 Int32 second = strNoAsterisks.substring(12, 2).toInt32();
00757 Int32 microseconds = strNoAsterisks.substring(15, 6).toInt32();
00758
00759 validateRanges(year, month, day, hour, minute, second, microseconds, str);
00760
00761 Int32 utc = strNoAsterisks.substring(22, 3).toInt32();
00762
00763
00764 if (str[21] == '+')
00765 {
00766 utc = 0 - utc;
00767 }
00768 minute += utc;
00769
00770 set(year, month, day, hour, minute, second,
00771 microseconds, E_UTC_TIME);
00772 return;
00773 }
00774 catch (StringConversionException&)
00775 {
00776
00777
00778 }
00779 }
00780 }
00781
00782
00783
00784 if ( !str.empty() )
00785 {
00786
00787
00788
00789 String weekday;
00790 String day;
00791 String time;
00792 int timezone_number = LOCAL_TIME_OFFSET - 1;
00793 Int32 month_number = -1;
00794 String year;
00795
00796 StringArray tokenized_date = str.tokenize();
00797
00798
00799 for ( StringArray::const_iterator date_token = tokenized_date.begin();
00800 date_token != tokenized_date.end();
00801 ++date_token )
00802 {
00803
00804 if ( isDOWValid( date_token->c_str() ) )
00805 {
00806 if ( weekday.empty() )
00807 {
00808 if ( date_token->length() > 3 )
00809 {
00810 if ( isLongDOWValid( *date_token ) )
00811 {
00812 weekday = *date_token;
00813 }
00814 else
00815 {
00816
00817 badDateTime(str);
00818 }
00819 }
00820 else
00821 {
00822 weekday = *date_token;
00823 }
00824 }
00825 else
00826 {
00827
00828 badDateTime(str);
00829 }
00830 }
00831
00832 else if ( (month_number == -1) &&
00833 (month_number = decodeShortMonth( date_token->c_str() ) ) != -1 )
00834 {
00835 if ( date_token->length() > 3 )
00836 {
00837 month_number = decodeLongMonth( date_token->c_str() );
00838
00839 if ( month_number == -1 )
00840 {
00841
00842 badDateTime(str);
00843 }
00844 }
00845 }
00846
00847 else if ( time.empty() && (date_token->indexOf(":") != String::npos) )
00848 {
00849
00850 time = *date_token;
00851 }
00852
00853 else if ( day.empty() && isdigit((*date_token)[0]) )
00854 {
00855 day = *date_token;
00856 }
00857
00858 else if ( year.empty() && isdigit((*date_token)[0]) )
00859 {
00860 year = *date_token;
00861 }
00862 else if ( (timezone_number <= LOCAL_TIME_OFFSET) &&
00863 (date_token->length() >= 1) &&
00864 (date_token->length() <= 4) &&
00865 getTimeZoneOffset(*date_token, timezone_number) )
00866 {
00867
00868 }
00869 else
00870 {
00871 badDateTime(str);
00872 }
00873
00874 }
00875
00876
00877
00878 if ( (month_number >= 1) && !day.empty() && !time.empty() && !year.empty() )
00879 {
00880
00881
00882
00883 StringArray time_fields = time.tokenize(":");
00884
00885
00886
00887 if ( (time_fields.size() < 2) || (time_fields.size() > 3) )
00888 {
00889 badDateTime(str);
00890 }
00891
00892 try
00893 {
00894
00895 Int32 hour;
00896 Int32 minute;
00897 Int32 second = 0;
00898 UInt32 microseconds = 0;
00899 Int32 year_number = year.toInt32();
00900 Int32 day_number = day.toInt32();
00901
00902 hour = time_fields[0].toInt32();
00903 minute = time_fields[1].toInt32();
00904
00905 if ( time_fields.size() == 3 )
00906 {
00907 second = time_fields[2].toInt32();
00908 }
00909
00910 validateRanges(year_number, month_number, day_number,
00911 hour, minute, second, microseconds, str);
00912
00913 if ( timezone_number <= LOCAL_TIME_OFFSET )
00914 {
00915 set(year_number, month_number, day_number, hour,
00916 minute, second, microseconds, E_LOCAL_TIME);
00917 }
00918 else
00919 {
00920
00921
00922
00923
00924 adjustTimeForTimeZone(timezone_number, year_number, month_number, day_number, hour);
00925
00926
00927 validateRanges(year_number, month_number, day_number, hour,
00928 minute, second, microseconds, str);
00929
00930 set(year_number, month_number, day_number, hour,
00931 minute, second, microseconds, E_UTC_TIME);
00932 }
00933 }
00934 catch (const StringConversionException&)
00935 {
00936 badDateTime(str);
00937 }
00938 }
00939 else
00940 {
00941
00942 badDateTime(str);
00943 }
00944 }
00945 else
00946 {
00947
00948 badDateTime(str);
00949 }
00950 }
00952 DateTime::DateTime(time_t t, UInt32 microseconds)
00953 : m_time(t)
00954 , m_microseconds(microseconds)
00955 {
00956 }
00958 DateTime::DateTime(int year, int month, int day, int hour, int minute,
00959 int second, UInt32 microseconds, ETimeOffset timeOffset)
00960 {
00961 set(year, month, day, hour, minute, second, microseconds, timeOffset);
00962 }
00964 DateTime::DateTime(const DateTimeRepRef& rep)
00965 : m_rep(rep)
00966 {
00967 }
00969 DateTime::~DateTime()
00970 {
00971 }
00973 inline tm
00974 DateTime::getTm(ETimeOffset timeOffset) const
00975 {
00976 if (timeOffset == E_LOCAL_TIME)
00977 {
00978 tm theTime;
00979 localtime_r(&m_time, &theTime);
00980 return theTime;
00981 }
00982 else
00983 {
00984 tm theTime;
00985 gmtime_r(&m_time, &theTime);
00986 return theTime;
00987 }
00988 }
00989
00991 inline void
00992 DateTime::setTime(tm& tmarg, ETimeOffset timeOffset)
00993 {
00994 if (timeOffset == E_LOCAL_TIME)
00995 {
00996 m_time = ::mktime(&tmarg);
00997 }
00998 else
00999 {
01000 #ifdef OWBI1_HAVE_TIMEGM
01001 m_time = ::timegm(&tmarg);
01002 #else
01003
01004
01005
01006 #ifdef OWBI1_NETWARE
01007 m_time = ::mktime(&tmarg) - _timezone;
01008 #else
01009 m_time = ::mktime(&tmarg) - ::timezone;
01010 #endif
01011 #endif
01012 }
01013
01014 if (m_time < 0)
01015 {
01016 #ifdef OWBI1_HAVE_ASCTIME_R
01017 char buff[30];
01018 asctime_r(&tmarg, buff);
01019 #else
01020
01021 char* buff = asctime(&tmarg);
01022 #endif
01023 OWBI1_THROW(DateTimeException, Format("Unable to represent time \"%1\" as a time_t", buff).c_str());
01024 }
01025 }
01027 int
01028 DateTime::getHour(ETimeOffset timeOffset) const
01029 {
01030 return getTm(timeOffset).tm_hour;
01031 }
01033 int
01034 DateTime::getMinute(ETimeOffset timeOffset) const
01035 {
01036 return getTm(timeOffset).tm_min;
01037 }
01039 int
01040 DateTime::getSecond(ETimeOffset timeOffset) const
01041 {
01042 return getTm(timeOffset).tm_sec;
01043 }
01045 UInt32
01046 DateTime::getMicrosecond() const
01047 {
01048 return m_microseconds;
01049 }
01051 int
01052 DateTime::getDay(ETimeOffset timeOffset) const
01053 {
01054 return getTm(timeOffset).tm_mday;
01055 }
01057 int
01058 DateTime::getDow(ETimeOffset timeOffset) const
01059 {
01060 return getTm(timeOffset).tm_wday;
01061 }
01063 int
01064 DateTime::getMonth(ETimeOffset timeOffset) const
01065 {
01066 return getTm(timeOffset).tm_mon+1;
01067 }
01069 int
01070 DateTime::getYear(ETimeOffset timeOffset) const
01071 {
01072 return (getTm(timeOffset).tm_year + 1900);
01073 }
01075 time_t
01076 DateTime::get() const
01077 {
01078 return m_time;
01079 }
01081 void
01082 DateTime::setHour(int hour, ETimeOffset timeOffset)
01083 {
01084 tm theTime = getTm(timeOffset);
01085 theTime.tm_hour = hour;
01086 setTime(theTime, timeOffset);
01087 }
01089 void
01090 DateTime::setMinute(int minute, ETimeOffset timeOffset)
01091 {
01092 tm theTime = getTm(timeOffset);
01093 theTime.tm_min = minute;
01094 setTime(theTime, timeOffset);
01095 }
01097 void
01098 DateTime::setSecond(int second, ETimeOffset timeOffset)
01099 {
01100 tm theTime = getTm(timeOffset);
01101 theTime.tm_sec = second;
01102 setTime(theTime, timeOffset);
01103 }
01105 void
01106 DateTime::setMicrosecond(UInt32 microseconds)
01107 {
01108 if (microseconds > 999999)
01109 {
01110 OWBI1_THROW(DateTimeException, Format("invalid microseconds: %1", microseconds).c_str());
01111 }
01112 m_microseconds = microseconds;
01113 }
01115 void
01116 DateTime::setTime(int hour, int minute, int second, ETimeOffset timeOffset)
01117 {
01118 tm theTime = getTm(timeOffset);
01119 theTime.tm_hour = hour;
01120 theTime.tm_min = minute;
01121 theTime.tm_sec = second;
01122 setTime(theTime, timeOffset);
01123 }
01125 void
01126 DateTime::setDay(int day, ETimeOffset timeOffset)
01127 {
01128 tm theTime = getTm(timeOffset);
01129 theTime.tm_mday = day;
01130 setTime(theTime, timeOffset);
01131 }
01133 void
01134 DateTime::setMonth(int month, ETimeOffset timeOffset)
01135 {
01136 if (month == 0)
01137 {
01138 OWBI1_THROW(DateTimeException, "invalid month: 0");
01139 }
01140
01141 tm theTime = getTm(timeOffset);
01142 theTime.tm_mon = month-1;
01143 setTime(theTime, timeOffset);
01144 }
01146 void
01147 DateTime::setYear(int year, ETimeOffset timeOffset)
01148 {
01149 tm theTime = getTm(timeOffset);
01150 theTime.tm_year = year - 1900;
01151 setTime(theTime, timeOffset);
01152 }
01154 void
01155 DateTime::set(int year, int month, int day, int hour, int minute, int second,
01156 UInt32 microseconds, ETimeOffset timeOffset)
01157 {
01158 tm tmarg;
01159 tmarg.tm_year = (year >= 1900) ? year - 1900 : year;
01160 tmarg.tm_mon = month-1;
01161 tmarg.tm_mday = day;
01162 tmarg.tm_hour = hour;
01163 tmarg.tm_min = minute;
01164 tmarg.tm_sec = second;
01165 if (timeOffset == E_UTC_TIME)
01166 {
01167 tmarg.tm_isdst = 0;
01168 }
01169 else
01170 {
01171 tmarg.tm_isdst = -1;
01172 }
01173 setTime(tmarg, timeOffset);
01174 m_microseconds = microseconds;
01175 }
01177 void
01178 DateTime::setToCurrent()
01179 {
01180 #ifdef OWBI1_HAVE_GETTIMEOFDAY
01181 timeval tv;
01182 gettimeofday(&tv, NULL);
01183 m_time = tv.tv_sec;
01184 m_microseconds = tv.tv_usec;
01185 #else
01186 m_time = time(NULL);
01187 m_microseconds = 0;
01188 #endif
01189 }
01191 void
01192 DateTime::addDays(int days)
01193 {
01194 tm theTime = getTm(E_UTC_TIME);
01195 theTime.tm_mday += days;
01196 setTime(theTime, E_UTC_TIME);
01197 }
01199 void
01200 DateTime::addYears(int years)
01201 {
01202 tm theTime = getTm(E_UTC_TIME);
01203 theTime.tm_year += years;
01204 setTime(theTime, E_UTC_TIME);
01205 }
01207 void
01208 DateTime::addMonths(int months)
01209 {
01210 tm theTime = getTm(E_UTC_TIME);
01211 theTime.tm_mon += months;
01212 setTime(theTime, E_UTC_TIME);
01213 }
01215 String
01216 DateTime::toString(ETimeOffset timeOffset) const
01217 {
01218 tm theTime = getTm(timeOffset);
01219 #ifdef OWBI1_HAVE_ASCTIME_R
01220 char buff[30];
01221 asctime_r(&theTime, buff);
01222 String s(buff);
01223 return s;
01224 #else
01225
01226 return asctime(&theTime);
01227 #endif
01228 }
01229
01231 String DateTime::toString(char const * format, ETimeOffset timeOffset) const
01232 {
01233 tm theTime = getTm(timeOffset);
01234 size_t const BUFSZ = 1024;
01235 char buf[BUFSZ];
01236 size_t n = strftime(buf, BUFSZ, format, &theTime);
01237 buf[n >= BUFSZ ? 0 : n] = '\0';
01238 return String(buf);
01239 }
01240
01242 char const DateTime::DEFAULT_FORMAT[] = "%c";
01243
01245 Int16 DateTime::localTimeAndOffset(time_t t, struct tm & t_loc)
01246 {
01247 struct tm t_utc;
01248 struct tm * ptm_utc = ::gmtime_r(&t, &t_utc);
01249 struct tm * ptm_loc = ::localtime_r(&t, &t_loc);
01250 if (!ptm_utc || !ptm_loc)
01251 {
01252 OWBI1_THROW(DateTimeException, Format("Invalid time_t: %1", t).c_str());
01253 }
01254 int min_diff =
01255 (t_loc.tm_min - t_utc.tm_min) + 60 * (t_loc.tm_hour - t_utc.tm_hour);
01256
01257
01258 int day_diff = t_loc.tm_mday - t_utc.tm_mday;
01259 int const one_day = 24 * 60;
01260 if (day_diff == 0)
01261 {
01262 return min_diff;
01263 }
01264 else if (day_diff == 1 || day_diff < -1)
01265 {
01266
01267
01268 return min_diff + one_day;
01269 }
01270 else
01271 {
01272
01273
01274 return min_diff - one_day;
01275 }
01276 }
01277
01279 void
01280 DateTime::set(time_t t, UInt32 microseconds)
01281 {
01282 if (t == static_cast<time_t>(-1) || microseconds > 999999)
01283 {
01284 OWBI1_THROW(DateTimeException, "Either t == -1 or microseconds > 999999");
01285 }
01286
01287 m_time = t;
01288 m_microseconds = microseconds;
01289 }
01290
01292
01293 DateTime
01294 DateTime::getCurrent()
01295 {
01296 DateTime current;
01297 current.setToCurrent();
01298 return current;
01299 }
01300
01302 DateTimeRepRef
01303 DateTime::getRep() const
01304 {
01305 return m_rep;
01306 }
01307
01308 void addSeconds(long seconds)
01309 {
01310 m_time += seconds;
01311 }
01316 void addMinutes(long minutes)
01317 {
01318 m_time += minutes * 60;
01319 }
01324 void addHours(long hours) { m_time += hours * 60 * 60; }
01330 bool operator< ( const DateTime& tm ) const
01331 {
01332 if (m_time == tm.m_time)
01333 {
01334 return m_microseconds < tm.m_microseconds;
01335 }
01336 return m_time < tm.m_time;
01337 }
01343 bool operator> ( const DateTime& tm ) const
01344 {
01345 return tm < *this;
01346 }
01352 bool operator== ( const DateTime& tm ) const
01353 {
01354 return m_time == tm.m_time && m_microseconds == tm.m_microseconds;
01355 }
01356
01357 bool operator== ( const DateTime& tm ) const
01358 {
01359 return m_time == tm.m_time && m_microseconds == tm.m_microseconds;
01360 }
01361 Int16 toLocal(struct tm & tt) const
01362 {
01363 return DateTime::localTimeAndOffset(m_time, tt);
01364 }
01365
01366 }
01367