You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

534 lines
15 KiB

//
// HtDateTime.h
//
// HtDateTime: Parse, split, compare and format dates and times.
// Uses locale.
//
// Part of the ht://Dig package <http://www.htdig.org/>
// 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
// <http://www.gnu.org/copyleft/lgpl.html>
//
// $Id: HtDateTime.h,v 1.19 2004/05/28 13:15:20 lha Exp $
///////
// Class for Date and Time
// Gabriele Bartolini - Prato - Italia
// Started: 22.04.1999
///////
// Version: 1.0
// Release date: 07.05.1999
//
// General purpose of HtDateTime
// The general purpose of this class, is to provide an interface for
// date and time managing, and to unload the programmer to manage
// time_t, struct tm, time system functions and other related procedures
// locally ... Everything regarding time and date must be put here.
// D'you agree with me? Well, here is a summary of the class capabilities.
// Attributes of the class:
//
// HtDateTime class has only 2 member attributes
// - time_t Ht_t
// - bool local_time
//
// Obviously Ht_t contains the most important piece of information.
// local_time assumes a true value if we wanna consider the date and
// time information as local. False means that our object value is
// referred to the Greenwich Meridian time.
// Interface provided:
//
// Construction:
// - Default: set the date time value to now
// - By passing a time_t value or pointer: Set to it
// - By passing a struct tm value or pointer: Set to it
// The last one could be useful sometimes. But it had better not to
// be used.
//
// Parsing interface:
// Not yet implemented ... :-)
//
// Setting Interface:
// - from time_t: copy the time_t value into the object
// - from struct tm: set the object's time_t value by converting
// the value from the struct tm. If local_time is set to true,
// converts it with mktime, else uses HtTimeGM.
// - set to now
// - from a string, by passing the input format: the method uses
// strptime syntax (and invokes Htstrptime). For now, timezone
// is ignored, and so data are stored as a GM date time value.
// - from an int series, by specifying all the information (year,
// month, day, hour, minute and second). It's all stored as
// GM value.
// - from various standard formats, such as C asctime, RFC 1123,
// RFC 850 (these 3 types are suggested by the HTTP/1.1 standard),
// ISO 8601, date and time default representation for the locale.
// This list could get longer ... It all depends on us.
// - setting the date and time to be represented in a local value
// or universal (GM) one.
//
// Getting Interface
// - in a personalized output format, by passing a string with
// strftime values.
// - in various standard formats, like C asctime, RFC 1123,
// RFC 850, ISO 8601 (short too), date and time default
// representation for the locale.
// - getting the time_t value
// - queries the local time status
// - getting specific piece of information of both the date and the
// the time, like the year, the month, the day of the week, of
// the year or of the month, ... In short, every kind of thing
// a tm structure is able to store ...
//
// Operator overloading
// - Copy
// - Every kind of logical comparison between 2 objects
//
// Comparison interface
// This is divided in 2 sections.
// - Static section:
// comparison are made on a 2 struct tm values basis.
// It's possible to compare the whole date time value, or
// simply the date or the time value.
// - Member functions section:
// comparison are made between 2 HtDateTime objects.
// You can compare either the whole date time, or the date, or the
// time, both as they are or referring their values to the GM value.
//
// System functions interface
// They are all done with previous "configure" checks
// - for strptime
// - for timegm
//
// Static methods
// - check for a leap year
// - check for a valid year number (according with time_t capabilities)
// - check for a valid month number
// - check for a valid day
// - converts a 2 digits year number into a 4 digits one: from 1970 to 2069.
// - converts a 4 digits year number into a 2 digits one.
// - retrieve the difference in seconds between 2 HtDateTime objs
//
// Test Interface (only by defining TEST_HTDATETIME directive).
//
#ifndef _HTDATETIME_H
#define _HTDATETIME_H
#ifdef HAVE_CONFIG_H
# include "htconfig.h"
#endif
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include "htString.h"
// If you wanna do some tests
#define TEST_HTDATETIME
class HtDateTime
{
public:
///////
// Construction
///////
// Default: now and local
HtDateTime() {SettoNow(); ToLocalTime();}
// From an integer (seconds from epoc)
// Causes ambiguity in systems with time_t an integer...
// HtDateTime(const int i) {SetDateTime((time_t)i); ToLocalTime();}
// From a time_t value and pointer
HtDateTime(time_t &t) {SetDateTime(t); ToLocalTime();}
HtDateTime(time_t *t) {SetDateTime(t); ToLocalTime();}
// From a struct tm value and pointer
HtDateTime(struct tm &t) {SetDateTime(t); ToLocalTime();}
HtDateTime(struct tm *t) {SetDateTime(t); ToLocalTime();}
// Copy constructor
inline HtDateTime(const HtDateTime& rhs);
///////
// Interface methods
///////
///////
// "Parsing" interface
///////
int Parse(const char *); // It looks for the similar format
// then sets the date by invoking
// right method
///////
// "Setting" interface
///////
// Setting from a time_t value
void SetDateTime(const time_t &t) { Ht_t = t; } // by reference
void SetDateTime(const time_t *t) { Ht_t = *t; } // by pointer
// Set object time_t value from a struct tm
void SetDateTime(struct tm *); // by pointer
inline void SetDateTime(struct tm &t) { SetDateTime(&t);} // by reference
// Set GM Time from single values input
// Return true if it all went good, false else
bool SetGMDateTime( int year, int mon, int mday,
int hour=0, int min=0, int sec=0);
// Set to Now
void SettoNow();
// Parsing various input string format
// It ignores time Zone value - always stores as GM
char *SetFTime(const char *, const char *); // as strptime
void SetAscTime(char *); // Sun Nov 6 08:49:37 1994
void SetRFC1123(char *); // Sun, 06 Nov 1994 08:49:37 GMT
void SetRFC850(char *); // Sunday, 06-Nov-94 08:49:37 GMT
void SetISO8601(char *); // 1994-11-06 08:49:37 GMT
void SetTimeStamp(char *); // 19941106084937
void SetDateTimeDefault(char *); // Default date and time representation
// for the locale
///////
// Methods for setting Local and GM time formats (Switches)
///////
void ToLocalTime() {local_time=true;}
void ToGMTime() {local_time=false;}
///////
// "Getting" interface
///////
///////
// Output formats
///////
// Personalized output
char *GetFTime(const char *format) const; // as strftime
size_t GetFTime(char *, size_t, const char *) const; // as strftime
char *GetAscTime() const; // Sun Nov 6 08:49:37 1994
char *GetRFC1123() const; // Sun, 06 Nov 1994 08:49:37 GMT
char *GetRFC850() const; // Sunday, 06-Nov-94 08:49:37 GMT
char *GetISO8601() const; // 1994-11-06 08:49:37 GMT
char *GetTimeStamp() const; // 19941106084937
char *GetDateTimeDefault() const; // Default date and time representation
// for the locale
// Partial (only date or only time)
char *GetShortISO8601() const; // 1994-11-06
char *GetDateDefault() const; // Default date form for the locale
char *GetTimeDefault() const; // Default time form for the locale
///////
// Gets the time_t value
///////
time_t GetTime_t() const {return Ht_t;}
///////
// Gets specific date and time values (from a struct tm)
///////
// Gets the year
int GetYear() const { return ( GetStructTM().tm_year + 1900) ;}
// Gets the month
int GetMonth() const { return (GetStructTM().tm_mon + 1);}
// Gets the day of the week (since Sunday)
int GetWDay() const { return (GetStructTM().tm_wday + 1);}
// Gets the day of the month
int GetMDay() const { return GetStructTM().tm_mday;}
// Gets the day since january 1
int GetYDay() const { return (GetStructTM().tm_yday + 1);}
// Gets the hour
int GetHour() const { return GetStructTM().tm_hour;}
// Gets the minute
int GetMinute() const { return GetStructTM().tm_min;}
// Gets the second
int GetSecond() const { return GetStructTM().tm_sec;}
// Daylight saving time is in effect at that time?
int GetIsDst() const { return GetStructTM().tm_isdst;}
///////
// Methods for querying localtime status
///////
bool isLocalTime() const {return local_time;}
bool isGMTime() const {return !local_time;}
///////
// Methods for comparison
///////
// Returns 0 if equal, -1 if tm1 is lower than tm2, 1 if tm1 is greater than tm2
int DateTimeCompare (const HtDateTime &) const; // Compares both date and time
int DateCompare (const HtDateTime &) const; // Compares the date
int TimeCompare (const HtDateTime &) const; // Compares the time
// Refers the date and the time to a GM value, then compares
int GMDateTimeCompare (const HtDateTime &) const; // Compares both date and time
int GMDateCompare (const HtDateTime &) const; // Compares the date
int GMTimeCompare (const HtDateTime &) const; // Compares the time
///////
// Operator overloading
///////
// For comparisons - between objects of the same class
inline bool operator==(const HtDateTime &right) const;
inline bool operator<(const HtDateTime &right) const;
bool operator!=(const HtDateTime &right) const
{return !( *this == right );}
bool operator>=(const HtDateTime &right) const
{return !( *this < right);}
bool operator<=(const HtDateTime &right) const
{return !( right < *this);}
bool operator>(const HtDateTime &right) const
{return right < *this; }
// For comparisons - between HtDateTime objects and int
bool operator==(const int right) const // with an int
{return ( Ht_t == (time_t) right );}
bool operator<(const int right) const // with an int
{return ( Ht_t < (time_t) right );}
bool operator!=(const int right) const // with an int
{return !( *this == right );}
bool operator>=(const int right) const // with an int
{return !( *this < right);}
bool operator<=(const int right) const // with an int
{return !( *this > right);}
bool operator>(const int right) const // with an int
{return (Ht_t > (time_t) right); }
// For Copy
inline HtDateTime &operator=(const HtDateTime &right);
inline HtDateTime &operator=(const int right);
/////// // STATIC METHODS // ///////
// Here we can add static methods as we want more :-)
// Then invoke them with HtDateTime::MethodXXX ()
inline static bool LeapYear(int); // Is a leap year?
// These checks are made for time_t compatibility
inline static bool isAValidYear(int); // Is a valid year number
inline static bool isAValidMonth(int); // Is a valid month number
inline static bool isAValidDay(int, int, int); // Is a valid day
// Converts a 2 digits year in a 4 one - with no checks
static int Year_From2To4digits (int y)
{
if ( y >= 70 ) return y+1900;
else return y+2000;
}
// Converts a 4 digits year in a 2 one - with no checks
static int Year_From4To2digits (int y)
{
if ( y >= 2000 ) return y - 2000;
else return y - 1900;
}
static int GetDiff(const HtDateTime &, const HtDateTime &);
// Check equality from 2 struct tm pointers
// Returns 0 if equal, -1 if tm1 is lower than tm2, 1 if tm1 is greater than tm2
// Compares the whole time information (both date and time)
static int DateTimeCompare(const struct tm *tm1,
const struct tm *tm2);
// Compares only date
static int DateCompare(const struct tm *tm1,
const struct tm *tm2);
// Compares only time
static int TimeCompare(const struct tm *tm1,
const struct tm *tm2);
/////// // HIDDEN ATTRIBUTES & METHODS // ///////
protected: // to permit inheritance
time_t Ht_t;
bool local_time;
static const int days[];
///////
// Sets and gets the struct tm depending on local_time status
///////
void RefreshStructTM() const; // Refresh its content
struct tm &GetStructTM() const; // gets it
void GetStructTM(struct tm & t) const { t=GetStructTM(); } // Gets and copy
///////
// Gets the struct tm ignoring local_time status
///////
struct tm &GetGMStructTM() const; // gets it
void GetGMStructTM(struct tm &) const; // Gets and copy
///////
// Interface for system functions
///////
// Interface for timegm
static time_t HtTimeGM (struct tm*);
#ifdef TEST_HTDATETIME
///////
// Only for debug: view of struct tm fields
///////
public:
static void ViewStructTM(struct tm *); // view of struct tm fields
virtual void ViewStructTM(); // view of struct tm fields
void ViewFormats(); // View of various formats
void ComparisonTest (const HtDateTime &) const; // comparison
// Test of the class
static int Test(void);
static int Test(char **test_dates, const char *format);
#endif
};
///////
// Copy constructor
///////
inline
HtDateTime::HtDateTime (const HtDateTime& rhs)
{
// Copy the contents
Ht_t = rhs.Ht_t;
local_time = rhs.local_time;
}
///////
// Operator overloading
///////
inline
bool HtDateTime::operator==(const HtDateTime &right) const
{
if(Ht_t==right.Ht_t)
return true;
else
return false;
}
inline
bool HtDateTime::operator<(const HtDateTime &right) const
{
if(Ht_t < right.Ht_t) return true;
else return false;
}
///////
// Copy
///////
inline
HtDateTime &HtDateTime::operator=(const HtDateTime &right)
{
if (this != &right)
{
Ht_t=right.Ht_t; // Copy the time_t value
local_time=right.local_time; // Copy the local_time flag
}
return *this;
}
inline
HtDateTime &HtDateTime::operator=(const int right)
{
Ht_t=(time_t)right; // Copy the int as a time_t value
ToLocalTime();
return *this;
}
#endif