39#include "blocxx/BLOCXX_config.h"
49#ifdef BLOCXX_HAVE_SYS_TIME_H
56#ifndef BLOCXX_HAVE_LOCALTIME_R
64 struct tm *p = localtime(timep);
75#ifndef BLOCXX_HAVE_GMTIME_R
80struct 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);
132inline void badDateTime(
const String& str)
137inline void validateRanges(Int32 year, Int32 month, Int32 day, Int32 hour,
138Int32 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)
152inline 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')
248inline bool isLongDOWValid(
const String& s)
250 if ( (s ==
"Sunday") ||
253 (s ==
"Wednesday") ||
264inline 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')
359inline 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") )
415const int LOCAL_TIME_OFFSET = -24;
416bool 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;
652Int32 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;
692void adjustTimeForTimeZone(Int32 timezone_offset, Int32& year, Int32& month,
693Int32& 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);
char * asctime_r(const struct tm *tm, char *result)
struct tm * gmtime_r(const time_t *timep, struct tm *result)
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.
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
V::const_iterator const_iterator
The DateTime class is an abstraction for date time data.
ETimeOffset
The values of this enum are passed to various functions to as a flag to indicate the timezone context...
static char const DEFAULT_FORMAT[]
A default date/time format to use with toString().
void setSecond(int second, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the second component of this DateTime object.
DateTime()
Create a new DateTime object that represents the Epoch (00:00:00 UTC, January 1, 1970)
void addMonths(int months)
Add months to the date represented by this object.
int getHour(ETimeOffset timeOffset=E_LOCAL_TIME) const
Get the hour of the day for this DateTime object 0-23.
UInt32 getMicrosecond() const
Get the microsecond of the second for this DateTime object.
void addYears(int years)
Add years to the date represent by this object.
String toStringGMT() const BLOCXX_DEPRECATED
This is the same as toString(E_UTC_TIME).
void setMicrosecond(UInt32 microsecond)
Set the microsecond component of this DateTime object.
int getMinute(ETimeOffset timeOffset=E_LOCAL_TIME) const
Get the minute of the hour for this DateTime object 0-59.
void setHour(int hour, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the hour component of this DateTime object.
void setMonth(int month, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the month component of this DateTime object.
void setTime(int hour, int minute, int second, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the time component of this DateTime object.
static Int16 localTimeAndOffset(time_t t, struct tm &tt)
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...
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.
int getDow(ETimeOffset timeOffset=E_LOCAL_TIME) const
String toString(ETimeOffset timeOffset=E_LOCAL_TIME) const
int getMonth(ETimeOffset timeOffset=E_LOCAL_TIME) const
void setToCurrent()
Set this DateTime to the current system time.
void setYear(int year, ETimeOffset timeOffset=E_LOCAL_TIME)
Set the year component of this DateTime object.
int getYear(ETimeOffset timeOffset=E_LOCAL_TIME) const
void addDays(int days)
Add days to the date represented by this object.
tm getTm(ETimeOffset timeOffset) const
static DateTime getCurrent()
Gets a DateTime instance set to the current system time.
void set(time_t t, UInt32 microseconds=0)
Set this DateTime object with a time_t value.
int getDay(ETimeOffset timeOffset=E_LOCAL_TIME) const
Get the day of the month (1-31)
This String class is an abstract data type that represents as NULL terminated string of characters.
String substring(size_t beginIndex, size_t length=npos) const
Create another String object that is comprised of a substring of this String 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.
Int32 toInt32(int base=10) const
Char16 operator-(const Char16 &arg1, const Char16 &arg2)