//
// HtDateTime.cc
//
// HtDateTime: Parse, split, compare and format dates and times.
// Uses locale.
//
// Part of the ht://Dig package
// Copyright (c) 1999-2004 The ht://Dig Group
// For copyright details, see the file COPYING in your distribution
// or the GNU Library General Public License (LGPL) version 2 or later
//
//
// $Id: HtDateTime.cc,v 1.20 2004/05/28 13:15:20 lha Exp $
//
#ifdef HAVE_CONFIG_H
#include "htconfig.h"
#endif /* HAVE_CONFIG_H */
#include "HtDateTime.h"
#include
#include
#include
#ifdef HAVE_STD
#include
#ifdef HAVE_NAMESPACES
using namespace std;
#endif
#else
#include
#endif /* HAVE_STD */
#ifndef HAVE_STRPTIME
// mystrptime() declared in lib.h, defined in htlib/strptime.cc
#define strptime(s,f,t) mystrptime(s,f,t)
#else /* HAVE_STRPTIME */
#ifndef HAVE_STRPTIME_DECL
extern "C" {
extern char *strptime(const char *__s, const char *__fmt, struct tm *__tp);
}
#endif /* HAVE_STRPTIME_DECL */
#endif /* HAVE_STRPTIME */
///////
// Static local variable : Visible only here !!!
///////
#define MAXSTRTIME 256 // Max length of my_strtime
static struct tm Ht_tm;
static char my_strtime[MAXSTRTIME];
///////
// Recognized Date Formats
///////
// RFC1123: Sun, 06 Nov 1994 08:49:37 GMT
#define RFC1123_FORMAT "%a, %d %b %Y %H:%M:%S %Z"
#define LOOSE_RFC1123_FORMAT "%d %b %Y %H:%M:%S"
// RFC850 : Sunday, 06-Nov-94 08:49:37 GMT
#define RFC850_FORMAT "%A, %d-%b-%y %H:%M:%S %Z"
#define LOOSE_RFC850_FORMAT "%d-%b-%y %H:%M:%S"
// ANSI C's asctime() format : Sun Nov 6 08:49:37 1994
#define ASCTIME_FORMAT "%a %b %e %H:%M:%S %Y"
#define LOOSE_ASCTIME_FORMAT "%b %e %H:%M:%S %Y"
// ISO8601 : 1994-11-06 08:49:37 GMT
#define ISO8601_FORMAT "%Y-%m-%d %H:%M:%S %Z"
// ISO8601 (short version): 1994-11-06
#define ISO8601_SHORT_FORMAT "%Y-%m-%d"
// Timestamp : 19941106084937
#define TIMESTAMP_FORMAT "%Y%m%d%H%M%S"
///////
// Initialization
///////
const int HtDateTime::days[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31};
/////// // Input Formats // ///////
///////
// Generalized date/time parser for "LOOSE" formats
// - converts LOOSE RFC850 or RFC1123 date string into a time value
// - converts SHORT ISO8601 date string into a time value
// - autodetects which of these formats is used
// - assumes midnight if time portion omitted
// We've had problems using strptime() and timegm() on a few platforms
// while parsing these formats, so this is an attempt to sidestep them.
//
// Returns 0 if parsing failed, or returns number of characters parsed
// in date string otherwise, and sets Ht_t field to time_t value.
///////
#define EPOCH 1970
int HtDateTime::Parse(const char *date)
{
register const char *s;
register const char *t;
int day, month, year, hour, minute, second;
//
// Three possible time designations:
// Tuesday, 01-Jul-97 16:48:02 GMT (RFC850)
// or
// Thu, 01 May 1997 00:40:42 GMT (RFC1123)
// or
// 1997-05-01 00:40:42 GMT (ISO8601)
//
// We strip off the weekday because we don't need it, and
// because some servers send invalid weekdays!
// (Some don't even send a weekday, but we'll be flexible...)
s = date;
while (*s && *s != ',')
s++;
if (*s)
s++;
else
s = date;
while (isspace(*s))
s++;
// check for ISO8601 format
month = 0;
t = s;
while (isdigit(*t))
t++;
if (t > s && *t == '-' && isdigit(t[1]))
day = -1;
else {
// not ISO8601, so try RFC850 or RFC1123
// get day...
if (!isdigit(*s))
return 0;
day = 0;
while (isdigit(*s))
day = day * 10 + (*s++ - '0');
if (day > 31)
return 0;
while (*s == '-' || isspace(*s))
s++;
// get month...
// (it's ugly, but it works)
switch (*s++) {
case 'J': case 'j':
switch (*s++) {
case 'A': case 'a':
month = 1;
s++;
break;
case 'U': case 'u':
switch (*s++) {
case 'N': case 'n':
month = 6;
break;
case 'L': case 'l':
month = 7;
break;
default:
return 0;
}
break;
default:
return 0;
}
break;
case 'F': case 'f':
month = 2;
s += 2;
break;
case 'M': case 'm':
switch (*s++) {
case 'A': case 'a':
switch (*s++) {
case 'R': case 'r':
month = 3;
break;
case 'Y': case 'y':
month = 5;
break;
default:
return 0;
}
break;
default:
return 0;
}
break;
case 'A': case 'a':
switch (*s++) {
case 'P': case 'p':
month = 4;
s++;
break;
case 'U': case 'u':
month = 8;
s++;
break;
default:
return 0;
}
break;
case 'S': case 's':
month = 9;
s += 2;
break;
case 'O': case 'o':
month = 10;
s += 2;
break;
case 'N': case 'n':
month = 11;
s += 2;
break;
case 'D': case 'd':
month = 12;
s += 2;
break;
default:
return 0;
}
while (*s == '-' || isspace(*s))
s++;
}
// get year...
if (!isdigit(*s))
return 0;
year = 0;
while (isdigit(*s))
year = year * 10 + (*s++ - '0');
if (year < 69)
year += 2000;
else if (year < 1900)
year += 1900;
else if (year >= 19100) // seen some programs do it, why not check?
year -= (19100-2000);
while (*s == '-' || isspace(*s))
s++;
if (day < 0) { // still don't have day, so it's ISO8601 format
// get month...
if (!isdigit(*s))
return 0;
month = 0;
while (isdigit(*s))
month = month * 10 + (*s++ - '0');
if (month < 1 || month > 12)
return 0;
while (*s == '-' || isspace(*s))
s++;
// get day...
if (!isdigit(*s))
return 0;
day = 0;
while (isdigit(*s))
day = day * 10 + (*s++ - '0');
if (day < 1 || day > 31)
return 0;
while (*s == '-' || isspace(*s))
s++;
}
// optionally get hour...
hour = 0;
while (isdigit(*s))
hour = hour * 10 + (*s++ - '0');
if (hour > 23)
return 0;
while (*s == ':' || isspace(*s))
s++;
// optionally get minute...
minute = 0;
while (isdigit(*s))
minute = minute * 10 + (*s++ - '0');
if (minute > 59)
return 0;
while (*s == ':' || isspace(*s))
s++;
// optionally get second...
second = 0;
while (isdigit(*s))
second = second * 10 + (*s++ - '0');
if (second > 59)
return 0;
while (*s == ':' || isspace(*s))
s++;
// Assign the new value to time_t field
//
// Calculate date as seconds since 01 Jan 1970 00:00:00 GMT
// This is based somewhat on the date calculation code in NetBSD's
// cd9660_node.c code, for which I was unable to find a reference.
// It works, though!
//
Ht_t = (time_t) (((((367L*year - 7L*(year+(month+9)/12)/4
- 3L*(((year)+((month)+9)/12-1)/100+1)/4
+ 275L*(month)/9 + day) -
(367L*EPOCH - 7L*(EPOCH+(1+9)/12)/4
- 3L*((EPOCH+(1+9)/12-1)/100+1)/4
+ 275L*1/9 + 1))
* 24 + hour) * 60 + minute) * 60 + second);
// cerr << "Date string '" << date << "' converted to time_t "
// << (int)Ht_t << ", used " << (s-date) << " characters\n";
return s-date;
}
///////
// Personalized format such as C strftime function
// Overloaded version 1
// It ignores, for now, Time Zone values
///////
char *HtDateTime::SetFTime(const char *buf, const char *format)
{
register char *p;
register int r;
ToGMTime(); // This must be set cos strptime always stores in GM
p = (char *) buf;
if (*format == '%') // skip any unexpected white space
while (isspace(*p))
p++;
// Special handling for LOOSE/SHORT formats...
if ((strcmp((char *) format, LOOSE_RFC850_FORMAT) == 0 ||
strcmp((char *) format, LOOSE_RFC1123_FORMAT) == 0 ||
strcmp((char *) format, ISO8601_SHORT_FORMAT) == 0) &&
(r = Parse(p)) > 0)
return p+r;
p = (char *) strptime (p, (char *) format, & Ht_tm);
#ifdef TEST_HTDATETIME
// ViewStructTM(& Ht_tm);
#endif
// Assign the new value to time_t value
SetDateTime(Ht_tm);
return p;
}
///////
// C asctime() standard format
///////
void HtDateTime::SetAscTime(char *s)
{
// Unfortunately, I cannot think of an easy test to
// see if we have a weekday *FIX*
SetFTime(s, ASCTIME_FORMAT);
}
///////
// RFC1123 standard Date format
// Sun, 06 Nov 1994 08:49:37 GMT
///////
void HtDateTime::SetRFC1123(char *s)
{
// abbreviated weekday name;
// day of the month;
// abbreviated month name;
// year as ccyy;
// hour ( 00 - 23);
// minute ( 00 - 59);
// seconds ( 00 - 59);
// time zone name;
// First, if we have it, strip off the weekday
char *stripped;
stripped = strchr(s, ',');
if (stripped)
stripped++;
else
stripped = s;
SetFTime(stripped, LOOSE_RFC1123_FORMAT);
}
///////
// RFC850 standard Date format
// Sunday, 06-Nov-1994 08:49:37 GMT
///////
void HtDateTime::SetRFC850(char *s)
{
// weekday name;
// day of the month;
// abbreviated month name;
// year within century;
// hour ( 00 - 23);
// minute ( 00 - 59);
// seconds ( 00 - 59);
// time zone name;
// First, if we have it, strip off the weekday
char *stripped;
stripped = strchr(s, ',');
if (stripped)
stripped++;
else
stripped = s;
SetFTime(stripped, LOOSE_RFC850_FORMAT);
}
///////
// ISO8601 standard Date format
// 1994-11-06 08:49:37 GMT
///////
void HtDateTime::SetISO8601(char *s)
{
// year as ccyy;
// month ( 01 - 12)
// day of the month
// hour ( 00 - 23)
// minute ( 00 - 59)
// seconds ( 00 - 59);
// time zone name;
SetFTime(s, ISO8601_FORMAT);
}
///////
// Timestamp Date format (MySQL) without timezone
// 19941106084937
///////
void HtDateTime::SetTimeStamp(char *s)
{
// year as ccyy;
// month ( 01 - 12)
// day of the month
// hour ( 00 - 23)
// minute ( 00 - 59)
// seconds ( 00 - 59);
SetFTime(s, TIMESTAMP_FORMAT);
}
///////
// Default date and time format for the locale
///////
void HtDateTime::SetDateTimeDefault(char *s)
{
SetFTime(s, "%c");
}
/////// // Output Formats // ///////
///////
// Personalized format such as C strftime function
// Overloaded version 1
///////
size_t HtDateTime::GetFTime(char *s, size_t max, const char *format) const
{
// Refresh static struct tm variable
RefreshStructTM();
return strftime(s, max, format, & Ht_tm);
}
///////
// Personalized format such as C strftime function
// Overloaded version 2 - The best to be used outside
// for temporary uses
///////
char *HtDateTime::GetFTime(const char *format) const
{
// Invoke GetFTime overloaded method
if(GetFTime(my_strtime, MAXSTRTIME, format))
return (char *)my_strtime;
else return 0;
}
///////
// RFC1123 standard Date format
// Sun, 06 Nov 1994 08:49:37 GMT
///////
char *HtDateTime::GetRFC1123() const
{
// abbreviated weekday name;
// day of the month;
// abbreviated month name;
// year as ccyy;
// hour ( 00 - 23);
// minute ( 00 - 59);
// seconds ( 00 - 59);
// time zone name;
GetFTime(my_strtime, MAXSTRTIME, RFC1123_FORMAT);
return (char *)my_strtime;
}
///////
// RFC850 standard Date format
// Sunday, 06-Nov-94 08:49:37 GMT
///////
char *HtDateTime::GetRFC850() const
{
// full weekday name
// day of the month
// abbreviated month name
// year within century ( 00 - 99 )
// hour ( 00 - 23)
// minute ( 00 - 59)
// seconds ( 00 - 59);
// time zone name;
GetFTime(my_strtime, MAXSTRTIME, RFC850_FORMAT);
return (char *)my_strtime;
}
///////
// C asctime() standard format
///////
char *HtDateTime::GetAscTime() const
{
GetFTime(my_strtime, MAXSTRTIME, ASCTIME_FORMAT);
return (char *)my_strtime;
}
///////
// ISO8601 standard Date format
// 1994-11-06 08:49:37 GMT
///////
char *HtDateTime::GetISO8601() const
{
// year as ccyy;
// month ( 01 - 12)
// day of the month
// hour ( 00 - 23)
// minute ( 00 - 59)
// seconds ( 00 - 59);
// time zone name;
GetFTime(my_strtime, MAXSTRTIME, ISO8601_FORMAT);
return (char *)my_strtime;
}
///////
// ISO8601 standard Date format
// 1994-11-06 08:49:37 GMT
///////
char *HtDateTime::GetShortISO8601() const
{
// year as ccyy;
// month ( 01 - 12)
// day of the month
GetFTime(my_strtime, MAXSTRTIME, ISO8601_SHORT_FORMAT);
return (char *)my_strtime;
}
///////
// Timestamp Date format (MySQL) without timezone
// 19941106084937
///////
char *HtDateTime::GetTimeStamp() const
{
// year as ccyy;
// month ( 01 - 12)
// day of the month
// hour ( 00 - 23)
// minute ( 00 - 59)
// seconds ( 00 - 59);
GetFTime(my_strtime, MAXSTRTIME, TIMESTAMP_FORMAT);
return (char *)my_strtime;
}
///////
// Default date and time format for the locale
///////
char *HtDateTime::GetDateTimeDefault() const
{
GetFTime(my_strtime, MAXSTRTIME, "%c");
return (char *)my_strtime;
}
///////
// Default date format for the locale
///////
char *HtDateTime::GetDateDefault() const
{
GetFTime(my_strtime, MAXSTRTIME, "%x");
return (char *)my_strtime;
}
///////
// Default time format for the locale
///////
char *HtDateTime::GetTimeDefault() const
{
GetFTime(my_strtime, MAXSTRTIME, "%X");
return (char *)my_strtime;
}
///////
// Set the static struct tm depending on localtime status
///////
void HtDateTime::RefreshStructTM() const
{
if(local_time)
// Setting localtime
memcpy(& Ht_tm, localtime(&Ht_t), sizeof(struct tm));
else
// Setting UTC or GM time
memcpy(& Ht_tm , gmtime(&Ht_t), sizeof(struct tm));
}
// Set the date time from a struct tm pointer
void HtDateTime::SetDateTime(struct tm *ptm)
{
if(local_time)
Ht_t = mktime(ptm); // Invoke mktime
else
Ht_t = HtTimeGM(ptm); // Invoke timegm alike function
}
// Set time to now
void HtDateTime::SettoNow()
{
Ht_t = time(0);
}
// Sets date by passing specific values
// The values are reffered to the GM date time
// Return false if failed
bool HtDateTime::SetGMDateTime ( int year, int mon, int mday,
int hour, int min, int sec)
{
struct tm tm_tmp;
// Year
if ( ! isAValidYear (year) ) return false;
if( year < 100)
year=Year_From2To4digits (year); // For further checks it's converted
// Assigning the year
tm_tmp.tm_year=year-1900;
// Month
if( ! isAValidMonth(mon) ) return false;
tm_tmp.tm_mon=mon-1; // Assigning the month to the structure
// Day
if ( ! isAValidDay ( mday, mon, year ) ) return false;
tm_tmp.tm_mday=mday; // Assigning the day of the month
if(hour >= 0 && hour < 24) tm_tmp.tm_hour = hour;
else return false;
if(min >= 0 && min < 60) tm_tmp.tm_min = min;
else return false;
if(sec >= 0 && sec < 60) tm_tmp.tm_sec = sec;
else return false;
tm_tmp.tm_yday = 0; // day of the year (to be ignored)
tm_tmp.tm_isdst = 0; // default for GM (to be ignored)
// Now we are going to insert the new values as time_t value
// This can only be done using GM Time and so ...
if (isLocalTime())
{
ToGMTime(); // Change to GM Time
SetDateTime(&tm_tmp); // commit it
ToLocalTime(); // And then return to Local Time
}
else SetDateTime(&tm_tmp); // only commit it
return true;
}
///////
// Gets a struct tm from the value stored in the object
// It's a protected method. Not visible outside the class
///////
struct tm &HtDateTime::GetStructTM() const
{
RefreshStructTM(); // refresh it
return Ht_tm;
}
struct tm &HtDateTime::GetGMStructTM() const
{
GetGMStructTM (Ht_tm);
return Ht_tm;
}
void HtDateTime::GetGMStructTM(struct tm & t) const
{
// Directly gets gmtime value
memcpy(& t , gmtime(& Ht_t), sizeof(struct tm));
}
///////
// Is a leap year?
///////
bool HtDateTime::LeapYear (int y)
{
if(y % 400 == 0 || ( y % 100 != 0 && y % 4 == 0))
return true; // a leap year
else
return false; // and not
}
///////
// Is a valid year number?
///////
bool HtDateTime::isAValidYear (int y)
{
if(y >= 1970 && y < 2069) return true; // simple check and most likely
if(y >= 0 && y < 100) return true; // 2 digits year number
return false;
}
///////
// Is a valid month number?
///////
bool HtDateTime::isAValidMonth (int m)
{
if( m >= 1 && m <= 12) return true;
else return false;
}
///////
// Is a valid day?
///////
bool HtDateTime::isAValidDay (int d, int m, int y)
{
if ( ! isAValidYear (y) ) return false; // Checks for the year
if ( ! isAValidMonth (m) ) return false; // Checks for the month
if(m == 2)
{
// Expands the 2 digits year number
if ( y < 100 ) y=Year_From2To4digits(y);
if ( LeapYear (y) ) // Checks for the leap year
{
if (d >= 1 && d <= 29) return true;
else return false;
}
}
// Acts as default
if (d >= 1 && d <= days [m -1]) return true;
else return false;
}
///////
// Comparison methods
///////
int HtDateTime::DateTimeCompare (const HtDateTime & right) const
{
int result;
// Let's compare the date
result=DateCompare(right);
if(result) return result;
// Same date. Let's compare the time
result=TimeCompare(right);
return result; // Nothing more to check
}
int HtDateTime::GMDateTimeCompare (const HtDateTime & right) const
{
// We must compare the whole time_t value
if ( * this > right) return 1; // 1st greater than 2nd
if ( * this < right) return 1; // 1st lower than 2nd
return 0;
}
int HtDateTime::DateCompare (const HtDateTime & right) const
{
// We must transform them in 2 struct tm variables
struct tm tm1, tm2;
this->GetGMStructTM (tm1);
right.GetGMStructTM (tm2);
// Let's compare them
return DateCompare (&tm1, &tm2);
}
int HtDateTime::GMDateCompare (const HtDateTime & right) const
{
// We must transform them in 2 struct tm variables
// both referred to GM time
struct tm tm1, tm2;
this->GetGMStructTM (tm1);
right.GetGMStructTM (tm2);
// Let's compare them
return DateCompare (&tm1, &tm2);
}
int HtDateTime::TimeCompare (const HtDateTime & right) const
{
// We must transform them in 2 struct tm variables
struct tm tm1, tm2;
this->GetStructTM (tm1);
right.GetStructTM (tm2);
return TimeCompare (&tm1, &tm2);
}
int HtDateTime::GMTimeCompare (const HtDateTime & right) const
{
// We must transform them in 2 struct tm variables
struct tm tm1, tm2;
// We take the GM value of the time
this->GetGMStructTM (tm1);
right.GetGMStructTM (tm2);
return TimeCompare (&tm1, &tm2);
}
///////
// Static methods of comparison between 2 struct tm pointers
///////
///////
// Compares only the date (ignoring the time)
///////
int HtDateTime::DateCompare(const struct tm *tm1, const struct tm *tm2)
{
// Let's check the year
if (tm1->tm_year < tm2->tm_year) return -1;
if (tm1->tm_year > tm2->tm_year) return 1;
// Same year. Let's check the month
if (tm1->tm_mon < tm2->tm_mon) return -1;
if (tm1->tm_mon > tm2->tm_mon) return 1;
// Same month. Let's check the day of the month
if (tm1->tm_mday < tm2->tm_mday) return -1;
if (tm1->tm_mday > tm2->tm_mday) return 1;
// They are equal for the date
return 0;
}
///////
// Compares only the time (ignoring the date)
///////
int HtDateTime::TimeCompare(const struct tm *tm1, const struct tm *tm2)
{
// Let's check the hour
if (tm1->tm_hour < tm2->tm_hour) return -1;
if (tm1->tm_hour > tm2->tm_hour) return 1;
// Same hour . Let's check the minutes
if (tm1->tm_min < tm2->tm_min) return -1;
if (tm1->tm_min > tm2->tm_min) return 1;
// Ooops !!! Same minute. Let's check the seconds
if (tm1->tm_sec < tm2->tm_sec) return -1;
if (tm1->tm_sec > tm2->tm_sec) return 1;
// They are equal for the time
return 0;
}
///////
// Compares both date and time
///////
int HtDateTime::DateTimeCompare(const struct tm *tm1, const struct tm *tm2)
{
int compare_date = DateCompare(tm1, tm2);
if(compare_date) return compare_date; // Different days
// We are in the same day. Let's check the time
int compare_time = TimeCompare(tm1, tm2);
if(compare_time) return compare_time; // Different time
// Equal
return 0;
}
time_t HtDateTime::HtTimeGM (struct tm *tm)
{
#if HAVE_TIMEGM
return timegm (tm);
#else
return Httimegm (tm); // timegm replacement in timegm.c
// static time_t gmtime_offset;
// tm->tm_isdst = 0;
// return __mktime_internal (tm, gmtime, &gmtime_offset);
#endif
}
// Returns the difference in seconds between two HtDateTime Objects
int HtDateTime::GetDiff(const HtDateTime &d1, const HtDateTime &d2)
{
return (int) ( d1.Ht_t - d2.Ht_t );
}
///////
// Only for test and debug
///////
#ifdef TEST_HTDATETIME
///////
// View of struct tm fields
///////
void HtDateTime::ViewStructTM()
{
// Default viewing: refresh depending on time_t value
RefreshStructTM(); // Refresh static variable
ViewStructTM(&Ht_tm);
}
void HtDateTime::ViewStructTM(struct tm *ptm)
{
cout << "Struct TM fields" << endl;
cout << "================" << endl;
cout << "tm_sec :\t" << ptm->tm_sec << endl;
cout << "tm_min :\t" << ptm->tm_min << endl;
cout << "tm_hour :\t" << ptm->tm_hour << endl;
cout << "tm_mday :\t" << ptm->tm_mday << endl;
cout << "tm_mon :\t" << ptm->tm_mon << endl;
cout << "tm_year :\t" << ptm->tm_year << endl;
cout << "tm_wday :\t" << ptm->tm_wday << endl;
cout << "tm_yday :\t" << ptm->tm_yday << endl;
cout << "tm_isdst :\t" << ptm->tm_isdst<< endl;
}
int HtDateTime::Test(void)
{
int ok=1;
const char *test_dates[] =
{
"1970.01.01 00:00:00",
"1970.01.01 00:00:01",
"1972.02.05 23:59:59",
"1972.02.28 00:59:59",
"1972.02.28 23:59:59",
"1972.02.29 00:00:00",
"1972.03.01 13:00:04",
"1973.03.01 12:00:00",
"1980.01.01 00:00:05",
"1984.12.31 23:00:00",
"1997.06.05 17:55:35",
"1999.12.31 23:00:00",
"2000.01.01 00:00:05",
"2000.02.28 23:00:05",
"2000.02.29 23:00:05",
"2000.03.01 00:00:05",
"2007.06.05 17:55:35",
"2038.01.19 03:14:07",
0
};
const char *test_dates_ISO8601[] =
{
"1970-01-01 00:00:00 GMT",
"1970-01-01 00:00:00 CET",
"1990-02-27 23:30:20 GMT",
"1999-02-28 06:53:40 GMT",
"1975-04-27 06:53:40 CET",
0
};
const char *test_dates_RFC1123[] =
{
"Sun, 06 Nov 1994 08:49:37 GMT",
"Sun, 25 Apr 1999 17:49:37 GMT",
"Sun, 25 Apr 1999 17:49:37 CET",
0
};
const char *test_dates_RFC850[] =
{
"Sunday, 06-Nov-94 08:49:37 GMT",
"Sunday, 25-Apr-99 17:49:37 GMT",
"Sunday, 25-Apr-99 17:49:37 CET",
0
};
const char myformat[]="%Y.%m.%d %H:%M:%S";
// Tests a personal format
cout << endl << "Beginning Test of a personal format such as "
<< myformat << endl << endl;
if (Test((char **)test_dates, (const char *)myformat))
cout << "Test OK." << endl;
else
{
cout << "Test Failed." << endl;
ok=0;
}
// Tests ISO 8601 Format
cout << endl << "Beginning Test of ISO 8601 format" << endl << endl;
if(Test((char **)test_dates_ISO8601, (const char *)ISO8601_FORMAT))
cout << "Test OK." << endl;
else
{
cout << "Test Failed." << endl;
ok=0;
}
// Tests RFC 1123 Format
cout << endl << "Beginning Test of RFC 1123 format" << endl << endl;
if (Test((char **)test_dates_RFC1123, (const char *)RFC1123_FORMAT))
cout << "Test OK." << endl;
else
{
cout << "Test Failed." << endl;
ok=0;
}
// Tests RFC 850 Format
cout << endl << "Beginning Test of RFC 850 format" << endl << endl;
if (Test((char **)test_dates_RFC850, (const char *)RFC850_FORMAT))
cout << "Test OK." << endl;
else
{
cout << "Test Failed." << endl;
ok=0;
}
return(ok ? 1 : 0);
}
int HtDateTime::Test(char **test_dates, const char *format)
{
int i, ok = 1;
HtDateTime orig, conv;
for (i = 0; (test_dates[i]); i++)
{
cout << "\t " << i+1 << "\tDate string parsing of:" << endl;
cout << "\t\t" << test_dates[i] << endl;
cout << "\t\tusing format: " << format << endl << endl;
orig.SetFTime(test_dates[i], format);
orig.ComparisonTest(conv);
conv=orig;
if (orig != conv)
{
cout << "HtDateTime test failed!" << endl;
cout << "\t Original : " << orig.GetRFC1123() << endl;
cout << "\t Converted: " << orig.GetRFC1123() << endl;
ok = 0;
}
else
{
orig.ToLocalTime();
cout << endl << "\t Localtime viewing" << endl;
orig.ViewFormats();
orig.ToGMTime();
cout << endl << "\t GMtime viewing" << endl;
orig.ViewFormats();
//orig.ViewStructTM();
}
cout << endl;
}
return ok;
}
void HtDateTime::ComparisonTest (const HtDateTime &right) const
{
int result;
cout << "Comparison between:" << endl;
cout << " 1. " << this->GetRFC1123() << endl;
cout << " 2. " << right.GetRFC1123() << endl;
cout << endl;
///////
// Complete comparison
///////
cout << "\tComplete comparison (date and time)" << endl;
result = this->DateTimeCompare (right);
cout << "\t\t " << this->GetDateTimeDefault();
if (result > 0 )
cout << " is greater than ";
else if (result < 0 )
cout << " is lower than ";
else cout << " is equal to ";
cout << " " << right.GetDateTimeDefault() << endl;
///////
// Date comparison
///////
cout << "\tDate comparison (ignoring time)" << endl;
result = this->DateCompare (right);
cout << "\t\t " << this->GetDateDefault();
if (result > 0 )
cout << " is greater than ";
else if (result < 0 )
cout << " is lower than ";
else cout << " is equal to ";
cout << " " << right.GetDateDefault() << endl;
///////
// Date comparison (after GM time conversion)
///////
cout << "\tDate comparison (ignoring time) - GM time conversion" << endl;
result = this->GMDateCompare (right);
cout << "\t\t " << this->GetDateDefault();
if (result > 0 )
cout << " is greater than ";
else if (result < 0 )
cout << " is lower than ";
else cout << " is equal to ";
cout << " " << right.GetDateDefault() << endl;
///////
// Time comparison
///////
cout << "\tTime comparison (ignoring date)" << endl;
result = this->TimeCompare (right);
cout << "\t\t " << this->GetTimeDefault();
if (result > 0 )
cout << " is greater than ";
else if (result < 0 )
cout << " is lower than ";
else cout << " is equal to ";
cout << " " << right.GetTimeDefault() << endl;
///////
// Time comparison (after GM time conversion)
///////
cout << "\tTime comparison (ignoring date) - GM time conversion" << endl;
result = this->GMTimeCompare (right);
cout << "\t\t " << this->GetTimeDefault();
if (result > 0 )
cout << " is greater than ";
else if (result < 0 )
cout << " is lower than ";
else cout << " is equal to ";
cout << " " << right.GetTimeDefault() << endl;
}
void HtDateTime::ViewFormats()
{
cout << "\t\t RFC 1123 Format : " << GetRFC1123() << endl;
cout << "\t\t RFC 850 Format : " << GetRFC850() << endl;
cout << "\t\t C Asctime Format: " << GetAscTime() << endl;
cout << "\t\t ISO 8601 Format : " << GetISO8601() << endl;
}
#endif