//============================================================================= // drt/sys/stime.hpp // DRT primitive date and time classes. // // History // 0.01, 1999-02-20, David R Tribble. // First cut. // // [Public] // Copyright ©1999, by David R. Tribble, all rights reserved. // See "drt/sys/copyr.txt" for more information. //----------------------------------------------------------------------------- #ifndef drt_sys_stime_hpp #define drt_sys_stime_hpp 001 // Identification #ifndef NO_H_IDENT static const char drt_sys_stime_hpp_id[] = "@(#)drt/sys/stime.hpp 0.01"; #endif // System includes #ifndef drt_std_time_h #include #define drt_std_time_h 1 #endif // Special includes #ifndef drt_sys_sdefs_hpp #include "sdefs.hpp" #endif // Local includes #ifndef drt_sys_sdebug_hpp #include "sdebug.hpp" #endif // Local wrappers #include "slib1.hpp" drt_namespace_begin // Local forward declarations class DrtTimeZone; class DrtTm; //----------------------------------------------------------------------------- // Class DrtTime // Encodes an absolute system date and time in binary (numeric) form. // // Notes // This type is encoded as a 64-bit signed binary integer representing the // number of ticks since the zero date of the epoch. Leap seconds are not // encoded. The time is relative to Universal (UT) time (a.k.a. Zulu or Z // time). // // This encoding is capable of representing dates spanning a range of over // 58,000 years; however, only a portion of those dates are considered // valid, specifically, those dates that fall within the "epoch" of this // date encoding. All valid dates within the epoch are dates with 4-digit // year numbers, in either the AD/CE or BC/BCE eras. // // Each "tick" is 100 nanoseconds (0.1 microsecond, or 1.0e-07 seconds) // in duration. // // The epoch spans a range of almost 20,000 years, covering all of the // dates from: // BC9999-01-01 00:00:00.0000000 Z, Sun // to: // AD9999-12-31 23:59:59.9999999 Z, Fri // // The "zero date" (or "ZD") of the epoch, i.e., the date that occurs at // the center of the epoch, is: // AD2001-01-01 00:00:00.0000000 Z, Mon // // Dates prior to the ZD are encoded as negative values, and dates after // the ZD are encoded as positive values. // // This type is capable of representing an "unknown" time, or a time that // is indeterminate. Such a value always compares less than any valid // time value. // // This type is also capable of representing a "never" time, or a time // that has never (or not yet) transpired. Such a value always compares // greater than any valid time value. // // Certain bit representations constitute time encodings which do not // represent a well-formed date and time. Such values are considered // "invalid" time values. // // This type is convertible to and from the ISO standard 'time_t' type // (which is declared in the standard header.) // // Caveats // This encoding assumes a Gregorian calendar that repeats every 400 // years. This does not reflect actual historical dates in the past; // e.g., Catholic European countries adopted the Gregorian calendar in // 1585, while most English-speaking countries adopted it in 1752, and // the Orthodox Russians adopted it only in 1917. Thus dates prior to // these will not necessarily correspond to actual historic dates. // // The Gregorian calendar is based on a 400-year cycle, i.e., the calendar // repeats every 400 years. There are 146,097 days in each 400-year // period of the Gregorian calendar (400*365 + 400/4 - 400/100 + 400/400), // which means there are 31,556,952 seconds in a year (365.2425 days, or // 365 days plus 5.82 hours). Thus there are 315,569,520,000,000 ticks in // a standard year. // // Note that year number 1 is AD0001, and year number 0 is BC0001; there // is no year AD0000 or BC0000. Note also that BC9999 is year number // -9998; year number -9999 does not represent a valid date in the epoch // (because it would represent the year BC10000, which has more than four // digits). // // Leap seconds are not accounted for in this encoding. This is mainly // because it is impossible to predict when future leap seconds will // occur, thus properly accounting for time values in the future is simply // not possible. (Note that the first leap second occurred on 1972-06-31, // and that leap seconds tend to be added about once every 500 days // (because the Earth is slow in its rotation by about 2 msec per day); // most leap seconds occur at 23:59:60 on Dec-31 or Jun-31.) // // Some potentially valid timezone-adjusted dates are not considered // valid date values, e.g., AD9999-12-31 23:59:59 in any timezone to the // West of Z (UT), and BC9999-01-01 00:00:00 in any timezone to the East // of Z (UT). Such times occur only within two 23-hour time periods (at // the very beginning and the very end of the epoch), though, so this // should not be considered a problem. // // Converting a value of this class type into a value of 'time_t' type may // result in truncation (i.e., underflow or overflow); this is a // consequence of the fact that this type can usually represent a wider // range of dates than can the 'time_t' type. On the other hand, // converting a 'time_t' value to this class type may result in overflow, // since large 'time_t' types (such as 64-bit 'signed long long int') // could contain dates far outside the range of valid dates for this class // type. // // Comparisons of time values abide by the following truth table, where // '?' indicates an indeterminate ordering: // // | Left operand // Right | unknown valid never invalid // --------+--------------------------------------- // unknown | = < < < // valid | > <,=,> < ? // never | > > = > // invalid | > ? < ? // // History // 100, 1999-02-27, David R Tribble. // First cut. //----------------------------------------------------------------------------- #define DrtTime_VS 100 // Class version number class DRTEXPORT DrtTime { public: // Shared constants static const int VS; // Class version number static const long int TICKS_PER_SEC; // Number of ticks in a second static const long int TICKS_PER_DAY; // Number of ticks in a day static const drt_int64_t TICKS_PER_YEAR; // Number of ticks in a year public: // Shared types typedef DrtTime Type; // This type public: // Shared variables static DrtTraceGroup s_grp; // Class debugging group public: // Shared functions static DrtTime now(); // Get the current system time static DrtTime unknown(); // Get an unknown date static DrtTime never(); // Get a never date public: // Functions /*void*/ ~DrtTime(); // Destructor /*void*/ DrtTime(); // Default constructor /*void*/ DrtTime(const DrtTime &r); // Copy constructor /*void*/ DrtTime(time_t r); // Constructor void validate() const; // Validate this object void dump() const; // Dump object to debugs bool isValid() const; // Is a valid time bool isUnknown() const; // Is unknown bool isNever() const; // Is never time_t time() const; // Convert the time drt_int64_t ticks() const; // Get the ticks count bool set(time_t r); // Set the time bool set(const DrtTime &r); // Set the time bool set(const DrtTm &r); // Set the time void setUnknown(); // Set to unknown void setNever(); // Set to never bool setTicks(drt_int64_t r); // Set the ticks count int toString(char *buf, int len) const; // Convert to a string int fromString(const char *buf); // Convert from a string public: // Operators const DrtTime & operator =(const DrtTime &r); // Assignment const DrtTime & operator =(time_t r); // Assignment const DrtTime & operator +(long r); // Add ticks const DrtTime & operator -(long r); // Subtract ticks drt_int64_t operator -(const DrtTime &r); // Difference (ticks) const DrtTime & operator ++(); // Add a tick const DrtTime & operator ++(int); // Add a tick const DrtTime & operator --(); // Subtract a tick const DrtTime & operator --(int); // Subtract a tick bool operator ==(const DrtTime &r) const; // Comparison bool operator <(const DrtTime &r) const; // Comparison private: // Shared constants static const int ZYEAR; // Zero year of the epoch static const drt_int64_t MIN; // BC9999-01-01 00:00:00.000 Z static const drt_int64_t MAX; // AD9999-12-31 23:59:59.999 Z static const drt_int64_t UNKNOWN; // Unknown date static const drt_int64_t NEVER; // Never date static const drt_int64_t BC4713; // BC4713-01-01 12:00:00 Z static const drt_int64_t BC0001; // BC0001-01-01 00:00:00 Z static const drt_int64_t AD0001; // AD0001-01-01 00:00:00 Z static const drt_int64_t AD1601; // AD1601-01-01 00:00:00 Z static const drt_int64_t AD1858; // AD1858-11-?? 00:00:00 Z static const drt_int64_t AD1900; // AD1900-01-01 00:00:00 Z static const drt_int64_t AD1970; // AD1970-01-01 00:00:00 Z static const drt_int64_t AD1972; // AD1972-01-01 00:00:00 Z static const drt_int64_t AD1980; // AD1980-01-01 00:00:00 Z static const drt_int64_t AD2001; // AD2001-01-01 00:00:00 Z private: // Variables drt_int64_t m_ticks; // Ticks count private: // Functions bool expand(DrtTm *t) const; // Convert to a UT time value bool make(const DrtTm &t); // Convert from a UT time value }; //----------------------------------------------------------------------------- // Class DrtTm // Representation of a date/time in a broken-down form. // Used to represent a full date and time, or a delta time (i.e., the // difference between two date/times). // // An object of this class type contains the following components of a // given date and time: // year [-9 998, +9 999], zero is 1 BC/BCE // month [0, 11], zero is January // week [0, 52] // day [1, 31] // yearday [0, 365], zero is January 1st // weekday [0, 6], zero is Sunday // hour [0, 23] // minute [0, 59] // second [0, 60], can be a leap second // microsecond [0, 999 999] // // An object of this class type can be set to an "unknown" date/time // (which represents an unknown time, and which compares less than any // known time), or to a "never" time (which represents a time that has // never occurred, and which compares greater than any known time). // Extracting the components of an "unknown" or "never" time, or // converting such a value into a string, results in meaningless values. // // History // 100, 1999-02-20, David R Tribble. // First cut. //----------------------------------------------------------------------------- #define DrtTm_VS 100 // Class version number class DRTEXPORT DrtTm { public: // Shared constants static const int VS; // Class version number static const char ISO8601[]; // Default ISO-8601 format enum Weekday // Weekday number names { SUN, MON, TUE, WED, THU, FRI, SAT }; enum Month // Month number names { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC }; public: // Shared types typedef DrtTm Type; // This type public: // Shared variables static DrtTraceGroup s_grp; // Class debugging group public: // Shared functions static const DrtTm & unknown(); // Get an unknown date static const DrtTm & never(); // Get a never date public: // Functions /*void*/ ~DrtTm(); // Destructor /*void*/ DrtTm(); // Default constructor /*void*/ DrtTm(const DrtTm &r); // Copy constructor /*void*/ DrtTm(time_t r); // Constructor /*void*/ DrtTm(const DrtTime &r); // Constructor /*void*/ DrtTm(const struct tm &r); // Constructor bool gmtime(time_t t); // Set the UT time value bool gmtime(const DrtTime &t); // Set the UT time value bool gmtime(const struct tm &t); // Set the UT time value bool localtime(time_t t); // Set the local time value bool localtime(const DrtTime &t); // Set the local time value bool localtime(const struct tm &t); // Set the local time value bool setUnknown(); // Set to unknown bool setNever(); // Set to never bool normalize(); // Normalize the members const DrtTime time() const; // Convert the time bool isUnknown() const; // Is unknown bool isNever() const; // Is never bool isLeap() const; // Is a leap year bool isValid() const; // Is a valid date int year() const; // Get the year, [-9999,+9999] Month month() const; // Get the month of the year int week() const; // Get the week of the year int mday() const; // Get the day of the month Weekday wday() const; // Get the day of the week int yday() const; // Get the day of the year int hour() const; // Get the hour of the day int minute() const; // Get the minute of the hour int sec() const; // Get the second of the minute int msec() const; // Get the millisecond long usec() const; // Get the microsecond int setYear(int v); // Set the year Month setMonth(int v); // Set the month of the year int setWeek(int v); // Set the week of the year int setMday(int v); // Set the day of the month Weekday setWday(int v); // Set the day of the week int setYday(int v); // Set the day of the year int setHour(int v); // Set the hour of the day int setMin(int v); // Set the minute of the hour int setSec(int v); // Set the second of the minute int setMsec(int v); // Set the millisecond int setUsec(long v); // Set the microsecond bool addYear(int v); // Add years bool addMonth(int v); // Add months bool addWeek(int v); // Add weeks bool addDay(int v); // Add days bool addHour(int v); // Add hours bool addMin(int v); // Add minutes bool addSec(int v); // Add seconds bool addMsec(int v); // Add milliseconds bool addUsec(long v); // Add microseconds bool add(const DrtTm &r); // Add a delta time bool diff(const DrtTm &a, const DrtTm &b); // Compute a delta time int toString(const char *fmt, char *buf, size_t len) const; // Convert to formatted string int addTZ(const DrtTimeZone &tz); // Adjust for a timezone int subTZ(const DrtTimeZone &tz); // Un-adjust for a timezone public: // Operators const DrtTm & operator =(const DrtTm &r); // Assignment operator const DrtTm & operator =(const DrtTime &r); // Assignment const DrtTm & operator +(const DrtTm &r); // Add a delta time const DrtTm & operator -(const DrtTm &r); // Compute a delta time bool operator <(const DrtTm &r); // Comparison bool operator >(const DrtTm &r); // Comparison bool operator <=(const DrtTm &r); // Comparison bool operator >=(const DrtTm &r); // Comparison bool operator ==(const DrtTm &r); // Comparison bool operator !=(const DrtTm &r); // Comparison private: // Variables short m_vers; // Class version short m_year; // Year, [-9998,+9999] short m_mon; // Month, [0,11] short m_yday; // Day of year, [0,365] short m_mday; // Day of month, [1,31] short m_wday; // Day of week, [0,6] short m_hour; // Hour, [0,23] short m_min; // Minute, [0,59] short m_sec; // Second, [0,60] drt_int32_t m_usec; // Microseconds, [0,999999] private: // Functions int cmp(const DrtTm &r) const; // Compare dates }; //----------------------------------------------------------------------------- // Class DrtTimeZone // Time zone value. // // History // 100, 1998-03-21, David R Tribble. // First cut. //----------------------------------------------------------------------------- #define DrtTimeZone_VS 100 // Class version number class DRTEXPORT DrtTimeZone { public: // Shared constants static const int VS; // Class version public: // Shared types typedef DrtTimeZone Type; // This type public: // Shared variables static DrtTraceGroup s_grp; // Class debugging group public: // Shared functions static const DrtTimeZone * zero(); // Zulu (Z, UT) timezone value static const DrtTimeZone * local(); // Get local timezone info static const DrtTimeZone * find(const char *tz); // Find timezone info by name public: // Functions /*void*/ ~DrtTimeZone(); // Destructor /*void*/ DrtTimeZone(); // Default constructor const char * name() const; // Get name int hours() const; // Get hours offset int mins() const; // Get minutes offset int secs() const; // Get seconds offset void setName(const char *n); // Set name void setHours(int h); // Set hours offset void setMins(int m); // Set minutes offset void setSecs(int s); // Set seconds offset void set(int h, int m, int s); // Set offset from GMT int toString(char *buf, int len) const; // Convert to a string int fromString(const char *buf); // Convert from a string private: // Variables const char * m_name; // Name short m_hour; // Hours West of GMT short m_min; // Minutes West of GMT short m_sec; // Seconds West of GMT private: // Functions // Constructors and destructors not provided /*void*/ DrtTimeZone(const DrtTimeZone &o); // Copy constructor const DrtTimeZone & operator =(const DrtTimeZone &o); // Assignment operator }; #include "slib2.hpp" drt_namespace_end #endif // drt_sys_stime_hpp // End stime.hpp