#error This functionality has been replaced by "ktm.c" //============================================================================= // drt/sys/stm.cpp // DRT primitive date and time class functions. // // History // 0.01, 1998-05-03, David R Tribble. // First cut. // // 0.02, 1998-05-30, David R Tribble. // Changed filename prefix from "j" to "s". // // 0.03, 1998-05-30, David R Tribble. // Moved function .now() into "sdatei.cpp". // // 0.04, 1999-02-27, David R Tribble. // Moved to drt/sys/. // // Copyright ©1998-1999, by David R. Tribble, all rights reserved. // See "drt/sys/copyr.txt" for more information. //----------------------------------------------------------------------------- // Identification static const char id[] = "@(#)drt/sys/stm.cpp 0.04"; // Special includes #include "sdefs.hpp" #include "stime.hpp" // System includes #include #define drt_std_assert_h 1 #include #define drt_std_limits_h 1 #if TEST #include #define drt_std_stdio_h 1 #endif // Local includes #include "sdebug.hpp" // Local wrappers drt_namespace_begin //----------------------------------------------------------------------------- // Shared class constants //----------------------------------------------------------------------------- #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif /*static*/ const int DrtTm::VS = DrtTm_VS; // Class version //----------------------------------------------------------------------------- // Shared class variables //----------------------------------------------------------------------------- #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif /*static*/ DrtTraceGroup DrtTm::s_grp("DrtTm", __FILE__, __DATE__, __TIME__); // Class debugging group //----------------------------------------------------------------------------- // Class member functions //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DrtTm::~DrtTm() // Destructor. //----------------------------------------------------------------------------- /*void*/ DrtTm::~DrtTm() { #if DrtTm_VS != 100 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "~DrtTm", this); // Validate this object validate(); // De-initialize members // (None) } //----------------------------------------------------------------------------- // DrtTm::DrtTm() // Default constructor. //----------------------------------------------------------------------------- /*DrtTm*/ DrtTm::DrtTm(): m_vers(VS), m_year(0), m_mon(0), m_mday(0), m_hour(0), m_min(0), m_sec(0), m_usec(0) { #if DrtTm_VS != 102 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "DrtTm", this); // Initialize other members // (None) } //----------------------------------------------------------------------------- // DrtTm::validate() // Validate this object. // // Notes // Fails an assert() if this object is invalid. //----------------------------------------------------------------------------- void DrtTm::validate() const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif //DrtTrace dbg(s_grp, "validate", this); // Validate this object assert(("DrtTm", this != null)); // Check for null assert(DrtTm::m_magic == MAGIC); // Check magic number assert(DrtTm::m_vs/100 == VS/100); // Check version number } //----------------------------------------------------------------------------- // DrtTm::dump() // Dump the contents of this object to the debugging trace output. //----------------------------------------------------------------------------- void DrtTm::dump() const { #if DrtTm_VS != 102 #error DrtTm_VS has changed #endif //DrtTrace dbg(s_grp, "dump", this); // Validate this object validate(); // Lock the debug output context DrtTrace::enterContext(); // Dump the contents of this (base) object DrtTrace::print(".m_vers ....... %d\n", m_vers); DrtTrace::print(".m_year ....... %+04d\n", m_year); DrtTrace::print(".m_mon ........ %02d\n", m_mon); DrtTrace::print(".m_mday ....... %02d\n", m_mday); DrtTrace::print(".m_hour ....... %02d\n", m_hour); DrtTrace::print(".m_min ........ %02d\n", m_min); DrtTrace::print(".m_sec ........ %02d\n", m_sec); DrtTrace::print(".m_usec ....... %06d\n", m_usec); // Done DrtTrace::leaveContext(); } //----------------------------------------------------------------------------- // DrtTm::isInvalid() // Determines if this date value is invalid, i.e., contains improper // member values. // // Returns // True if this date is invalid, otherwise false. //----------------------------------------------------------------------------- bool DrtTm::isInvalid() const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif #if DEBUG >= 2 DrtTrace dbg(s_grp, "isInvalid", this); #endif // Check this object validate(); // Check for special cases if (m_year == SHRT_MIN) // Is 'unknown' return (true); if (m_year == SHRT_MAX) // Is 'never' return (true); // Check the date fields for normal values if (m_year < -9998 or m_year > +9999) return (true); if (m_mon < 0 or m_mon > 11) return (true); if (m_mday < 1 or m_mday > 31) return (true); if (m_hour < 0 or m_hour > 23) return (true); if (m_min < 0 or m_min > 59) return (true); if (m_sec < 0 or m_sec > 60) return (true); if (m_usec < 0 or m_usec > 999999) return (true); return (false); } //----------------------------------------------------------------------------- // DrtTm::isUnknown() // Determines if this date value is "unknown" (i.e., not set). // // Returns // True if this date is unknown, otherwise false. //----------------------------------------------------------------------------- bool DrtTm::isUnknown() const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif #if DEBUG >= 2 DrtTrace dbg(s_grp, "isUnknown", this); #endif // Check this object validate(); // Check the date fields if (m_year == SHRT_MIN) return (true); return (false); } //----------------------------------------------------------------------------- // DrtTm::isNever() // Determines if this date value is "never" (i.e., a time that will never // transpire). // // Returns // True if this date is never, otherwise false. //----------------------------------------------------------------------------- bool DrtTm::isNever() const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif #if DEBUG >= 2 DrtTrace dbg(s_grp, "isNever", this); #endif // Check this object validate(); // Check the date fields if (m_year == SHRT_MAX) return (true); return (false); } //----------------------------------------------------------------------------- // DrtTm::normalize() // Adjusts the members of this date so that they fall within normal // numeric ranges. // // Returns // True if this date is valid, otherwise false. //----------------------------------------------------------------------------- bool DrtTm::normalize() { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif #if DEBUG >= 2 DrtTrace dbg(s_grp, "normalize", this); #endif // Check this object validate(); // Validate and normalize the date fields, first phase do { if (m_year > +9999) return (false); // Is invalid if (m_year < -9998) return (false); // Is invalid if (m_mon >= 12) { m_year += (m_mon / 12); m_mon %= 12; } else if (m_mon < 0) { m_year -= (-m_mon / 12); m_mon = (-m_mon % 12); } ...adjust mday ...handle days per month[m_mon] and leap days } while (...still need adjustments); if (m_hour >= 24) { m_mday += (m_hour / 24); m_hour %= 24; } else if (m_hour < 0) { m_mday -= (-m_hour / 24); m_hour = (-m_hour % 24); } if (m_min >= 60) { m_hour += (m_min / 60); m_min %= 60; } else if (m_min < 0) { m_hour -= (-m_min / 60); m_min = (-m_min % 60); } if (m_sec >= 60) { m_min += (m_sec / 60); m_sec %= 60; } else if (m_sec < 0) { m_min -= (-m_sec / 60); m_sec = (-m_sec % 60); } // Validate and normalize the date fields, second phase if (m_usec >= 1000000) { m_sec += (m_usec / 1000000); m_usec %= 1000000; } else if (m_usec < 0) { m_sec -= (-m_usec / 1000000); m_usec = (-m_usec % 1000000); } if (m_sec >= 60) { m_min += (m_sec / 60); m_sec %= 60; } else if (m_sec < 0) { m_min -= (-m_sec / 60); m_sec = (-m_sec % 60); } if (m_min >= 60) { m_hour += (m_min / 60); m_min %= 60; } else if (m_min < 0) { m_hour -= (-m_min / 60); m_min = (-m_min % 60); } if (m_hour >= 24) { m_mday += (m_hour / 24); m_hour %= 24; } else if (m_hour < 0) { m_mday -= (-m_hour / 24); m_hour = (-m_hour % 24); } do { ...adjust mday ...handle days per month[m_mon] and leap days if (m_mon >= 12) { m_year += (m_mon / 12); m_mon %= 12; } else if (m_mon < 0) { m_year -= (-m_mon / 12); m_mon = (-m_mon % 12); } if (m_year > +9999) return (false); // Is invalid if (m_year < -9998) return (false); // Is invalid } while (...still need adjustments); return (true); #if notes Test this by taking 'AD1980-12-31 23:59:59.999999' and adding -0001y+01m+01d+00h00m00.000001s. Also try various combinations of pos/neg y/m/d/h/m/s/u values. #endif } //----------------------------------------------------------------------------- // DrtTm::cmp() // Compare this date to date 'r'. // // Returns // A value x, such that: // x < 0 if 'this' < 'r', or // x = 0 if 'this' = 'r', or // x > 0 if 'this' > 'r'. // // An 'unknown' date always compares less than any other date, and a // 'never' date always compares greater than any other date. // // | r // this | unknown valid never // --------+--------------------- // unknown | = < < // valid | > <,=,> < // never | > > = //----------------------------------------------------------------------------- int DrtTm::cmp(const DrtTm &r) const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "cmp", this); // Check this object validate(); // Check args r.validate(); // Compare the dates if (m_year == SHRT_MIN) // Is 'unknown' { if (r.m_year == SHRT_MIN) return (0); // Both are 'unknown' return (-1); } if (m_year == SHRT_MAX) // Is 'never' { if (r.m_year == SHRT_MAX) return (0); // Both are 'never' return (+1); } if (m_year < r.m_year) return (-1); if (m_year > r.m_year) return (+1); if (m_mon < r.m_mon) return (-1); if (m_mon > r.m_mon) return (+1); if (m_mday < r.m_mday) return (-1); if (m_mday > r.m_mday) return (+1); if (m_hour < r.m_hour) return (-1); if (m_hour > r.m_hour) return (+1); if (m_min < r.m_min) return (-1); if (m_min > r.m_min) return (+1); if (m_sec < r.m_sec) return (-1); if (m_sec > r.m_sec) return (+1); if (m_usec < r.m_usec) return (-1); if (m_usec > r.m_usec) return (+1); // Note: Ignore m_yday // Note: Ignore m_wday // Dates are equal return (0); } //----------------------------------------------------------------------------- // DrtTm::operator <() // Compare this date to date 'r'. // // Returns // True if this date is less than 'r'. // // See also // DrtTm::cmp() //----------------------------------------------------------------------------- bool DrtTm::operator <(const DrtTm &r) const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "operator<", this); // Compare the dates return (cmp(r) < 0); } //----------------------------------------------------------------------------- // DrtTm::operator ==() // Compare this date to date 'r'. // // Returns // True if this date is equal to 'r'. // // See also // DrtTm::cmp() //----------------------------------------------------------------------------- bool DrtTm::operator ==(const DrtTm &r) const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "operator==", this); // Compare the dates return (cmp(r) == 0); } ... //----------------------------------------------------------------------------- // DrtTm::gmtime() // Convert time 't' into this date, relative to the GMT (UTC, Zulu) // timezone. // // Returns // True if successful, otherwise false on error. //----------------------------------------------------------------------------- bool DrtTm::gmtime(const DrtTime &t) { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "gmtime", this); // Check this object validate(); // Convert time 't' into this date, relative to GMT/UT/Zulu return (t.expand(this)); } //----------------------------------------------------------------------------- // DrtTm::time() // Convert this date into a time value, relative to the GMT (UTC, Zulu) // timezone. // // Returns // A time value, which will be 'unknown' if an error occurs. //----------------------------------------------------------------------------- DrtTm DrtTm::time() const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "time", this); // Check this object validate(); // Convert this date into a time value, relative to GMT/UT/Zulu DrtTime t; t.make(*this); return (t); } //----------------------------------------------------------------------------- // DrtTm::dateToString() // Convert the date portion of this date into a string representation, // storing it in 'buf'. // The buffer at 'buf' can hold no more than 'len' characters. // // The string is filled with this date converted into a textual string // form of 9 characters (which includes a terminating NUL character): // "CCYYMMDD$" // where: // CC is the century, [19,29] // YY is the year within century, [00,99] // MM is the month, [01,12] // DD is the day of month, [01,31] // $ is a NUL character // // If this date is unknown (i.e., has not been set to a known date), the // string is filled with all zero fields: // "00000000$" // // Returns // Number of characters that were placed into the target string (not // including the terminating NUL character), or -1 on error. // // Caveats // The string at 'buf' should be capable of holding at least 9 // characters, i.e., 'len' should have a value greater than 8. // If 'len' is less than 24, this function fails and returns -1. //----------------------------------------------------------------------------- int DrtTm::dateToString(char *buf, int len /* = 8+1 */) const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "dateToString", this); // Check this object validate(); // Check args ///assert(("DrtTm::dateToString", buf != null)); if (buf == null) return (-1); ///assert(("DrtTm::dateToString", len > 0)); if (len <= 0) return (-1); // Check target string size if (len <= 8+1) return (-1); // Convert this date into a string representation int size = 0; buf[size++] = m_year/1000 % 10 + '0'; // The "CCYY" year part buf[size++] = m_year/100 % 10 + '0'; buf[size++] = m_year/10 % 10 + '0'; buf[size++] = m_year % 10 + '0'; buf[size++] = (m_mon+1)/10 % 10 + '0'; // The "MM" month part buf[size++] = (m_mon+1) % 10 + '0'; buf[size++] = m_mday/10 % 10 + '0'; // The "DD" day part buf[size++] = m_mday % 10 + '0'; buf[size] = '\0'; return (size); } //----------------------------------------------------------------------------- // DrtTm::timeToString() // Convert the time portion of this date into a string representation, // storing it in 'buf'. // The buffer at 'buf' can hold no more than 'len' characters. // // The string is filled with this date converted into a textual string // form of 10 characters (which includes a terminating NUL character): // "hhmmssmmm$" // where: // hh is the hour, [00,23] // mm is the minute, [00,59] // ss is the second, [00,60] // mmm is the millisecond, [000,999] // $ is a NUL character // // If this date is unknown (i.e., has not been set to a known date), the // string is filled with all zero fields: // "000000000$" // // Returns // Number of characters that were placed into the target string (not // including the terminating NUL character), or -1 on error. // // Caveats // The string at 'buf' should be capable of holding at least 10 // characters, i.e., 'len' should have a value greater than 9. // If 'len' is less than 24, this function fails and returns -1. //----------------------------------------------------------------------------- int DrtTm::timeToString(char *buf, int len /* = 9+1 */) const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "timeToString", this); // Check this object validate(); // Check args ///assert(("DrtTm::timeToString", buf != null)); if (buf == null) return (-1); ///assert(("DrtTm::timeToString", len > 0)); if (len <= 0) return (-1); // Check target string size if (len <= 9+1) return (-1); // Convert this date into a string representation int size = 0; buf[size++] = m_hour/10 % 10 + '0'; // The "hh" hour part buf[size++] = m_hour % 10 + '0'; buf[size++] = m_min/10 % 10 + '0'; // The "mm" minute part buf[size++] = m_min % 10 + '0'; buf[size++] = m_sec/10 % 10 + '0'; // The "ss" second part buf[size++] = m_sec % 10 + '0'; buf[size++] = m_usec/100000 % 10 + '0'; // The "mmm" millisecond part buf[size++] = m_usec/10000 % 10 + '0'; buf[size++] = m_usec/1000 % 10 + '0'; buf[size] = '\0'; return (size); } //----------------------------------------------------------------------------- // DrtTm::toString() // Convert this date into a string representation, storing it in 'buf'. // The buffer at 'buf' can hold no more than 'len' characters. // // The string is filled with this date converted into a textual string // form of 19 characters (which includes a terminating NUL character): // "CCYYMMDD hhmmssmmm$" // where: // CC is the century, [19,29] // YY is the year within century, [00,99] // MM is the month, [01,12] // DD is the day of month, [01,31] // hh is the hour, [00,23] // mm is the minute, [00,59] // ss is the second, [00,60] // mmm is the millisecond, [000,999] // $ is a NUL character // // If this date is unknown (i.e., has not been set to a known date), the // string is filled with all zero fields: // "00000000 000000000$" // // Returns // Number of characters that were placed into the target string (not // including the terminating NUL character), or -1 on error. // // Caveats // The string at 'buf' should be capable of holding at least 19 // characters, i.e., 'len' should have a value greater than 18. // If 'len' is less than 24, this function fails and returns -1. //----------------------------------------------------------------------------- int DrtTm::toString(char *buf, int len /* = 18+1 */) const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "toString", this); // Check this object validate(); // Check args ///assert(("DrtTm::toString", buf != null)); if (buf == null) return (-1); ///assert(("DrtTm::toString", len > 0)); if (len <= 0) return (-1); // Check target string size if (len <= 18+1) return (-1); // Convert this date into a string representation int size = 0; size = dateToString(buf, len); buf[size++] = ' '; size += timeToString(buf+size, len-size); return (size); } //----------------------------------------------------------------------------- // DrtTm::toStringISO() // Convert this date into a string representation, storing it in 'buf'. // The buffer at 'buf' can hold no more than 'len' characters. // // The string is filled with this date converted into a textual string // form of 24 characters (which includes a terminating NUL character) // according to the ISO-8601 date representation standard: // "CCYY-MM-DD hh:mm:ss.mmm$" // where: // CC is the century, [19,29] // YY is the year within century, [00,99] // MM is the month, [01,12] // DD is the day of month, [01,31] // hh is the hour, [00,23] // mm is the minute, [00,59] // ss is the second, [00,60] // mmm is the millisecond, [000,999] // $ is a NUL character // // If this date is unknown (i.e., has not been set to a known date), the // string is filled with a special string value: // "-unknown-$xxxxxxxxxxxxx" // // Returns // Number of characters that were placed into the target string (not // including the terminating NUL character), or -1 on error. // // Caveats // The string at 'buf' should be capable of holding at least 24 // characters, i.e., 'len' should have a value greater than 23. // If 'len' is less than 24, this function fails and returns -1. //----------------------------------------------------------------------------- int DrtTm::toStringISO(char *buf, int len /* = 23+1 */) const { #if DrtTm_VS/100 != 1 #error DrtTm_VS has changed #endif DrtTrace dbg(s_grp, "toString", this); // Check this object validate(); // Check args ///assert(("DrtTm::toString", buf != null)); if (buf == null) return (-1); ///assert(("DrtTm::toString", len > 0)); if (len <= 0) return (-1); // Check target string size if (len <= 23+1) return (-1); // Convert this date into a string representation int size = 0; if (isUnknown()) { // Convert to string value "-unknown-" buf[size++] = '-'; buf[size++] = 'u'; buf[size++] = 'n'; buf[size++] = 'k'; buf[size++] = 'n'; buf[size++] = 'o'; buf[size++] = 'w'; buf[size++] = 'n'; buf[size++] = '-'; buf[size] = '\0'; } else { // Convert to an ISO-8601 string value buf[size++] = m_year/1000 % 10 + '0'; // The "CCYY" year part buf[size++] = m_year/100 % 10 + '0'; buf[size++] = m_year/10 % 10 + '0'; buf[size++] = m_year % 10 + '0'; buf[size++] = '-'; buf[size++] = (m_mon+1)/10 % 10 + '0'; // The "MM" month part buf[size++] = (m_mon+1) % 10 + '0'; buf[size++] = '-'; buf[size++] = m_mday/10 % 10 + '0'; // The "DD" day part buf[size++] = m_mday % 10 + '0'; buf[size++] = ' '; buf[size++] = m_hour/10 % 10 + '0'; // The "hh" hour part buf[size++] = m_hour % 10 + '0'; buf[size++] = ':'; buf[size++] = m_min/10 % 10 + '0'; // The "mm" minute part buf[size++] = m_min % 10 + '0'; buf[size++] = ':'; buf[size++] = m_sec/10 % 10 + '0'; // The "ss" second part buf[size++] = m_sec % 10 + '0'; buf[size++] = '.'; buf[size++] = m_usec/100000 % 10 + '0'; // The "mmm" millisecond part buf[size++] = m_usec/10000 % 10 + '0'; buf[size++] = m_usec/1000 % 10 + '0'; buf[size] = '\0'; } return (size); } drt_namespace_end //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #if TEST //----------------------------------------------------------------------------- // ::buf_print() // Print the contents of string 'buf' to stdout. //----------------------------------------------------------------------------- static void buf_print(const char *buf) { #if is_incomplete___ buf[0].print(); #else // Temporary hack ///drt_std::printf("::buf_print() is incomplete\n"); for (int i = 0; buf[i] != '\0'; i++) putc(buf[i], stdout); #endif } //----------------------------------------------------------------------------- // ::main() // Test driver. //----------------------------------------------------------------------------- int main(int argc, char **argv) { printf("Create an DrtTm object...\n"); drt_namespace::DrtTm date; printf("Print its value...\n"); char buf[30]; date.toString(buf, sizeof(buf)); buf_print(buf); printf("\n"); printf("Get the current date and time...\n"); date.setToNow(); date.toString(buf, sizeof(buf)); buf_print(buf); printf("\n"); return (0); } #endif // TEST // End stm.cpp