39 #include "blocxx/BLOCXX_config.h"
49 #ifdef BLOCXX_HAVE_SYS_TIME_H
56 #ifndef BLOCXX_HAVE_LOCALTIME_R
61 struct tm *
localtime_r(
const time_t *timep,
struct tm *result)
64 struct tm *p = localtime(timep);
75 #ifndef BLOCXX_HAVE_GMTIME_R
80 struct tm *
gmtime_r(
const time_t *timep,
struct tm *result)
83 struct tm *p = gmtime(timep);
94 #ifndef BLOCXX_HAVE_ASCTIME_R
102 char *p = asctime(tm);
107 ::strncpy(result,p,25);
115 namespace BLOCXX_NAMESPACE
132 inline void badDateTime(
const String& str)
137 inline void validateRanges(Int32 year, Int32 month, Int32 day, Int32 hour,
138 Int32 minute, Int32 second, Int32 microseconds,
const String& str)
140 if (year < 0 || year > 9999 ||
141 month < 1 || month > 12 ||
142 day < 1 || day > 31 ||
143 hour < 0 || hour > 23 ||
144 minute < 0 || minute > 59 ||
145 second < 0 || second > 60 ||
146 microseconds < 0 || microseconds > 999999)
152 inline bool isDOWValid(
const char* str)
165 else if (str[1] ==
'a')
177 else if (str[0] ==
'M')
191 else if (str[0] ==
'T')
200 else if (str[1] ==
'h')
212 else if (str[0] ==
'W')
226 else if (str[0] ==
'F')
248 inline bool isLongDOWValid(
const String& s)
250 if ( (s ==
"Sunday") ||
253 (s ==
"Wednesday") ||
264 inline int decodeShortMonth(
const char* str)
276 else if (str[1] ==
'u')
282 else if (str[2] ==
'l')
288 else if (str[0] ==
'F')
290 if (str[1] ==
'e' && str[2] ==
'b')
295 else if (str[0] ==
'M')
303 else if (str[2] ==
'y')
309 else if (str[0] ==
'A')
318 else if (str[1] ==
'u')
326 else if (str[0] ==
'S')
328 if (str[1] ==
'e' && str[2] ==
'p')
333 else if (str[0] ==
'O')
335 if (str[1] ==
'c' && str[2] ==
't')
340 else if (str[0] ==
'N')
342 if (str[1] ==
'o' && str[2] ==
'v')
347 else if (str[0] ==
'D')
349 if (str[1] ==
'e' && str[2] ==
'c')
359 inline int decodeLongMonth(
const String& str)
361 if ( str.equals(
"January") )
365 else if ( str.equals(
"February") )
369 else if ( str.equals(
"March") )
373 else if ( str.equals(
"April") )
377 else if ( str.equals(
"May") )
381 else if ( str.equals(
"June") )
385 else if ( str.equals(
"July") )
389 else if ( str.equals(
"August") )
393 else if ( str.equals(
"September") )
397 else if ( str.equals(
"October") )
401 else if ( str.equals(
"November") )
405 else if ( str.equals(
"December") )
415 const int LOCAL_TIME_OFFSET = -24;
416 bool getTimeZoneOffset(
const String& timezone,
int& offset)
418 int temp_offset = LOCAL_TIME_OFFSET -1;
419 if ( timezone.length() == 1 )
424 switch ( timezone[0] )
502 temp_offset = LOCAL_TIME_OFFSET;
508 else if ( timezone ==
"UTC" )
513 else if ( timezone ==
"GMT" )
517 else if ( timezone ==
"BST" )
521 else if ( timezone ==
"IST" )
525 else if ( timezone ==
"WET" )
529 else if ( timezone ==
"WEST" )
533 else if ( timezone ==
"CET" )
537 else if ( timezone ==
"CEST" )
541 else if ( timezone ==
"EET" )
545 else if ( timezone ==
"EEST" )
549 else if ( timezone ==
"MSK" )
553 else if ( timezone ==
"MSD" )
558 else if ( timezone ==
"AST" )
562 else if ( timezone ==
"ADT" )
566 else if ( timezone ==
"EST" )
572 else if ( timezone ==
"EDT" )
576 else if ( timezone ==
"ET" )
582 else if ( timezone ==
"CST" )
587 else if ( timezone ==
"CDT" )
591 else if ( timezone ==
"CT" )
597 else if ( timezone ==
"MST" )
601 else if ( timezone ==
"MDT" )
605 else if ( timezone ==
"MT" )
611 else if ( timezone ==
"PST" )
615 else if ( timezone ==
"PDT" )
619 else if ( timezone ==
"PT" )
625 else if ( timezone ==
"HST" )
629 else if ( timezone ==
"AKST" )
633 else if ( timezone ==
"AKDT" )
638 else if ( timezone ==
"WST" )
644 if ( temp_offset >= LOCAL_TIME_OFFSET )
646 offset = temp_offset;
652 Int32 getDaysPerMonth(Int32 year, Int32 month)
654 const Int32 normal_days_per_month[12] =
655 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
657 if ( (month >= 1) && (month <= 12) )
661 return normal_days_per_month[month - 1];
664 int leap_year_adjust = 0;
666 if ( (year % 4) == 0 )
669 if ( (year % 100) == 0 )
671 if ( (year % 400) == 0 )
673 leap_year_adjust = 1;
678 leap_year_adjust = 1;
682 return normal_days_per_month[month - 1] + leap_year_adjust;
692 void adjustTimeForTimeZone(Int32 timezone_offset, Int32& year, Int32& month,
693 Int32& day, Int32& hour)
695 if ( timezone_offset < 0 )
697 hour -= timezone_offset;
705 if ( day > getDaysPerMonth(year, month) )
716 else if ( timezone_offset > 0 )
718 hour -= timezone_offset;
729 day += getDaysPerMonth(year, month);
749 if ( !(str[14] !=
'.' || (str[21] !=
'+' && str[21] !=
'-')) )
756 String strNoAsterisks(str);
757 for (
size_t i = 0;
i < strNoAsterisks.
length(); ++
i)
759 if (strNoAsterisks[
i] ==
'*')
761 strNoAsterisks[
i] =
'0';
772 validateRanges(year, month, day, hour, minute, second, microseconds, str);
783 set(year, month, day, hour, minute, second,
805 int timezone_number = LOCAL_TIME_OFFSET - 1;
806 Int32 month_number = -1;
813 date_token != tokenized_date.
end();
817 if ( isDOWValid( date_token->c_str() ) )
819 if ( weekday.
empty() )
821 if ( date_token->length() > 3 )
823 if ( isLongDOWValid( *date_token ) )
825 weekday = *date_token;
835 weekday = *date_token;
845 else if ( (month_number == -1) &&
846 (month_number = decodeShortMonth( date_token->c_str() ) ) != -1 )
848 if ( date_token->length() > 3 )
850 month_number = decodeLongMonth( date_token->c_str() );
852 if ( month_number == -1 )
866 else if ( day.
empty() && isdigit((*date_token)[0]) )
871 else if ( year.
empty() && isdigit((*date_token)[0]) )
875 else if ( (timezone_number <= LOCAL_TIME_OFFSET) &&
876 (date_token->length() >= 1) &&
877 (date_token->length() <= 4) &&
878 getTimeZoneOffset(*date_token, timezone_number) )
891 if ( (month_number >= 1) && !day.
empty() && !time.
empty() && !year.
empty() )
900 if ( (time_fields.
size() < 2) || (time_fields.
size() > 3) )
911 UInt32 microseconds = 0;
912 Int32 year_number = year.
toInt32();
913 Int32 day_number = day.
toInt32();
915 hour = time_fields[0].toInt32();
916 minute = time_fields[1].toInt32();
918 if ( time_fields.
size() == 3 )
920 second = time_fields[2].toInt32();
923 validateRanges(year_number, month_number, day_number,
924 hour, minute, second, microseconds, str);
926 if ( timezone_number <= LOCAL_TIME_OFFSET )
928 set(year_number, month_number, day_number, hour,
937 adjustTimeForTimeZone(timezone_number, year_number, month_number, day_number, hour);
940 validateRanges(year_number, month_number, day_number, hour,
941 minute, second, microseconds, str);
943 set(year_number, month_number, day_number, hour,
967 , m_microseconds(microseconds)
972 int second, UInt32 microseconds,
ETimeOffset timeOffset)
974 set(year, month, day, hour, minute, second, microseconds, timeOffset);
1004 m_time = ::mktime(&tmarg);
1008 #ifdef BLOCXX_HAVE_TIMEGM
1009 m_time = ::timegm(&tmarg);
1014 #ifdef BLOCXX_NETWARE
1015 m_time = ::mktime(&tmarg) - _timezone;
1017 m_time = ::mktime(&tmarg) - ::timezone;
1027 if( tmarg.tm_wday < 0 || tmarg.tm_wday > 6 )
1029 extraError +=
Format(
"Invalid weekday: %1. ", tmarg.tm_wday);
1033 if( tmarg.tm_mon < 0 || tmarg.tm_mon > 11 )
1035 extraError +=
Format(
"Invalid month: %1. ", tmarg.tm_mon);
1048 return getTm(timeOffset).tm_hour;
1054 return getTm(timeOffset).tm_min;
1060 return getTm(timeOffset).tm_sec;
1072 return getTm(timeOffset).tm_mday;
1078 return getTm(timeOffset).tm_wday;
1084 return getTm(timeOffset).tm_mon+1;
1090 return (
getTm(timeOffset).tm_year + 1900);
1102 tm theTime =
getTm(timeOffset);
1103 theTime.tm_hour = hour;
1110 tm theTime =
getTm(timeOffset);
1111 theTime.tm_min = minute;
1118 tm theTime =
getTm(timeOffset);
1119 theTime.tm_sec = second;
1126 if (microseconds > 999999)
1136 tm theTime =
getTm(timeOffset);
1137 theTime.tm_hour = hour;
1138 theTime.tm_min = minute;
1139 theTime.tm_sec = second;
1146 tm theTime =
getTm(timeOffset);
1147 theTime.tm_mday = day;
1159 tm theTime =
getTm(timeOffset);
1160 theTime.tm_mon = month-1;
1167 tm theTime =
getTm(timeOffset);
1168 theTime.tm_year = year - 1900;
1177 memset(&tmarg, 0,
sizeof(tmarg));
1178 tmarg.tm_year = (year >= 1900) ? year - 1900 : year;
1179 tmarg.tm_mon = month-1;
1180 tmarg.tm_mday = day;
1181 tmarg.tm_hour = hour;
1182 tmarg.tm_min = minute;
1183 tmarg.tm_sec = second;
1190 tmarg.tm_isdst = -1;
1199 #ifdef BLOCXX_HAVE_GETTIMEOFDAY
1201 gettimeofday(&tv, NULL);
1209 theTime.tm_hour = st.wHour;
1210 theTime.tm_min = st.wMinute;
1211 theTime.tm_sec = st.wSecond;
1212 theTime.tm_year = st.wYear - 1900;
1213 theTime.tm_mon = st.wMonth - 1;
1214 theTime.tm_mday = st.wDay;
1215 theTime.tm_wday = st.wDayOfWeek;
1216 theTime.tm_yday = 0;
1217 theTime.tm_isdst = -1;
1219 m_time = mktime(&theTime);
1228 theTime.tm_mday += days;
1236 theTime.tm_year += years;
1244 theTime.tm_mon += months;
1251 tm theTime =
getTm(timeOffset);
1261 tm theTime =
getTm(timeOffset);
1262 size_t const BUFSZ = 1024;
1264 size_t n = strftime(buf, BUFSZ, format, &theTime);
1265 buf[n >= BUFSZ ? 0 : n] =
'\0';
1283 struct tm * ptm_utc =
::gmtime_r(&t, &t_utc);
1285 if (!ptm_utc || !ptm_loc)
1290 (t_loc.tm_min - t_utc.tm_min) + 60 * (t_loc.tm_hour - t_utc.tm_hour);
1293 int day_diff = t_loc.tm_mday - t_utc.tm_mday;
1294 int const one_day = 24 * 60;
1299 else if (day_diff == 1 || day_diff < -1)
1303 return min_diff + one_day;
1309 return min_diff - one_day;
1317 if (t == static_cast<time_t>(-1) || microseconds > 999999)
1339 time_t diff = x.
get() - y.
get();
1344 microdiff += 1000000;
1346 return DateTime(diff, (UInt32)microdiff);
String toString(ETimeOffset timeOffset=E_LOCAL_TIME) const
struct tm * gmtime_r(const time_t *timep, struct tm *result)
String substring(size_t beginIndex, size_t length=npos) const
Create another String object that is comprised of a substring of this String object.
UInt32 getMicrosecond() const
Get the microsecond of the second for this DateTime object.
tm getTm(ETimeOffset timeOffset) const
This String class is an abstract data type that represents as NULL terminated string of characters...
int getDow(ETimeOffset timeOffset=E_LOCAL_TIME) const
void addMonths(int months)
Add months to the date represented by this object.
struct tm * localtime_r(const time_t *timep, struct tm *result)
#define BLOCXX_DEFINE_EXCEPTION_WITH_ID(NAME)
Define a new exception class named <NAME>Exception that derives from Exception.
int getDay(ETimeOffset timeOffset=E_LOCAL_TIME) const
Get the day of the month (1-31)
void setDay(int day, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the day component of this DateTime object.
void setMinute(int minute, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the minute component of this DateTime object.
Int32 toInt32(int base=10) const
Char16 operator-(const Char16 &arg1, const Char16 &arg2)
void setMonth(int month, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the month component of this DateTime object.
DateTime()
Create a new DateTime object that represents the Epoch (00:00:00 UTC, January 1, 1970) ...
int getMinute(ETimeOffset timeOffset=E_LOCAL_TIME) const
Get the minute of the hour for this DateTime object 0-59.
static char const DEFAULT_FORMAT[]
A default date/time format to use with toString().
void setTime(int hour, int minute, int second, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the time component of this DateTime object.
void setToCurrent()
Set this DateTime to the current system time.
void setSecond(int second, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the second component of this DateTime object.
ETimeOffset
The values of this enum are passed to various functions to as a flag to indicate the timezone context...
void setMicrosecond(UInt32 microsecond)
Set the microsecond component of this DateTime object.
StringArray tokenize(const char *delims=" \n\r\t\v", EReturnDelimitersFlag returnDelimitersAsTokens=E_DISCARD_DELIMITERS, EEmptyTokenReturnFlag returnEmptyTokens=E_SKIP_EMPTY_TOKENS) const
Tokenize this String object using the given delimeters.
void addDays(int days)
Add days to the date represented by this object.
int getMonth(ETimeOffset timeOffset=E_LOCAL_TIME) const
int getYear(ETimeOffset timeOffset=E_LOCAL_TIME) const
void set(time_t t, UInt32 microseconds=0)
Set this DateTime object with a time_t value.
static Int16 localTimeAndOffset(time_t t, struct tm &tt)
The DateTime class is an abstraction for date time data.
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
V::const_iterator const_iterator
static DateTime getCurrent()
Gets a DateTime instance set to the current system time.
void setYear(int year, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the year component of this DateTime object.
void addYears(int years)
Add years to the date represent by this object.
int getHour(ETimeOffset timeOffset=E_LOCAL_TIME) const
Get the hour of the day for this DateTime object 0-23.
int getSecond(ETimeOffset timeOffset=E_LOCAL_TIME) const
Get the second of the minute for this DateTime object normally in the range 0-59, but can be up to 60...
String toStringGMT() const BLOCXX_DEPRECATED
This is the same as toString(E_UTC_TIME).
char * asctime_r(const struct tm *tm, char *result)
void setHour(int hour, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the hour component of this DateTime object.