home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR36 / KDC46.ZIP / DATECL46.DOC < prev    next >
Text File  |  1993-08-04  |  23KB  |  535 lines

  1. =======================================================
  2. Documentation for "The Killer Date Class!" Version 4.00
  3. =======================================================
  4.  
  5. History
  6. =======
  7. In the beginning Steve Marcus (CIS 72007,1233) posted a basic date
  8. manipulation/arithmetic class produced with Borland C++ 2.0 in the 
  9. BPROGB forum, with a request for suggestions and enhancements. This was
  10. on 6/19/91.
  11.  
  12. A rather enterprising gentleman by the name of Eric Simon (CIS 70540,1522)
  13. accepted the challenge, and produced a new and improved version in the 
  14. course of a project he was developing at work. He contributed the results
  15. to the forum on 6/29/91, also inviting enhancements and comments.
  16.  
  17. About that time yet another enterprising gentleman named Christopher Hill
  18. developed a need for a universal date conversion routine for use in a
  19. business project he was developing as well.  Browsing the same forum, he
  20. encountered Eric's class, which provided much of the functionality he needed
  21. - the basic julian-gregorian and day of week conversion algorithms -
  22. relieving him of the task of researching or re-inventing them. Eric had also
  23. added overloaded + and - operators for incrementing date objects by integer
  24. days, as well as several print functions.  Chris needed additional features
  25. for his implementations, thus was born versions 3.0 and 3.1(Hill & Simon).
  26.  
  27. Well, almost a year later I sent out an SOS for a date class so _I_ didn't
  28. have to re-invent the wheel and lo-and-behold Chris responded.  Thus begins
  29. the saga of version 4.0!  I would like to take this opportunity to do a
  30. little witnessing: I looked all over for a date class that would suit my
  31. needs!  I reviewed many implementations from strangers and friends alike
  32. and I am here to tell ya' folks, "It don't 'git no bedder 'n dis!"  This
  33. class is _VERY_ cool!  Now I'm not trying to say that there's no more
  34. room for enhancements (I'd really be crazy then!), but I am saying that if
  35. your looking for a _GOOD_ date class (I'd say commercial quality because
  36. I have yet to see a commercial product that implemented a date class to
  37. my satisfaction!) then this is it!  So jump in and add to it, make it
  38. better and we'll SAVE THE WORLD!  (Ok, so I got a little carried away at
  39. the end. Just a little...)
  40.  
  41. No, but really...
  42. This is a truly pleasing example of co-operation among professionals, and
  43. an "object" study in the code reusability of OOP, resulting in three releases
  44. of one class within a single month by three different analysts who have never
  45. met, and yet another upgrade almost a year later by a fourth analyst (myself)
  46. and none of us have yet to meet!  Chris thanks Steve and Eric for their
  47. inspiration and generousity, and I thank all three as well and hereby
  48. contribute my additions to the public domain.
  49.  
  50. I believe any of us would welcome further comments, suggestions and
  51. enhancements as well.
  52.  
  53. Good luck!  May the quest for the perfect date class continue!
  54.  
  55.             v4.6  Ly Minh Trí      - 70641,3127  08/04/93
  56.             v4.5  Ly Minh Trí      - 70641,3127  06/21/93
  57.             v4.4  Ly Minh Trí      - 70641,3127  06/03/93
  58.             v4.3  Ly Minh Trí      - 70641,3127  03/24/93
  59.             v4.2  Ly Minh Trí      - 70641,3127  03/13/93
  60.             v4.1  Kenneth A. Argo  - 71241,3635  03/07/93
  61.             v4.0  Charles Price    - 70541,3651  06/27/92
  62.             v3.1  Hill & Simon     -             08/05/91
  63.             v3.0  Christopher Hill - 72030,2606  07/11/91
  64.             v2.0  Eric Simon       - 70540,1522  06/29/91
  65.             v1.0  Steve Marcus     - 72007,1233  06/16/91
  66.  
  67. ===============================================================================
  68. TML - 08/04/93
  69.  
  70. Version 4.6 fixes the Date::AddMonths() member function.  It does not add or
  71. subtract the number of months correctly.
  72.  
  73. Thanks to Patrick Cunningham for finding this bug!
  74.  
  75. ===============================================================================
  76. TML - 06/21/93
  77.  
  78. Version 4.5 fixes a very serious bug in the code for unary operators ++/--.  I
  79. confused myself with the formats for prefix and postfix operations.  (I got
  80. them reversed.)  Jorge Padron was kind enough to inform me of my mistake.
  81.  
  82. I also removed the 'const' keyword from parameter statements for functions which
  83. require variables to be passed by values (as opposed to pass by reference.)  For
  84. example,
  85.             Date  operator + (const long i);
  86.  
  87. is changed to:
  88.  
  89.             Date  operator + (long i);
  90.  
  91. I did it in the first place because I was trying to be consistent, but I realize
  92. that this can be confusing (especially those that are just learning C++).  Jorge
  93. also pointed this out to me.
  94.  
  95. ===============================================================================
  96. TML - 06/03/93
  97.  
  98. Version 4.4 adds a little validation to the value of the day and month when an
  99. object is created via a string argument.  For example, month must be from
  100. (1..12) and day must be from (1..n) where 'n' is the number of days for the
  101. given month.
  102.  
  103. Thus, the following statements:
  104.  
  105.      Date myDate("02/31/1993");
  106.      cout << myDate.formatDate() << "\n";
  107.  
  108. will result in an "invalid date" output!
  109.  
  110. ===============================================================================
  111.  
  112. TML - 3/15/93
  113.  
  114. Well, I must say, this is quite an impressive Date class!!!  And I must
  115. agree with Mr. Kenneth...it's probably one of the BEST (if not the best) Date
  116. class I've seen so far (but then again, I've not seen too many!).
  117.  
  118. However, I thought it really could take more advantage of some of the better
  119. features of C++ (ie. encapsulation!!!).  Thus, I decided to take on the
  120. challenge set forth by the aforementioned 'Date'-crazed group.
  121.  
  122. My changes are listed below in the Version 4.2 section.  Please let me know
  123. of any updates/changes that will happen in the future!!!
  124.  
  125. And ofcourse, we all welcome any comments/suggestions/participations!!!
  126.  
  127. Ly Minh Trí :)
  128.  
  129. ===============================================================================
  130.  
  131. Implementation Notes
  132. ====================
  133.  
  134.    All versions prior to 4.0 were written specifically for a Borland C++
  135.    compiler.  However, version 4.0 was written specifically for
  136.    Microsoft C++ 7.0.  I too have attempted to optimize the code including
  137.    the specification of const where applicable, the passing of references
  138.    where advisable, and the use of constructor initializers where needed.
  139.    However, I have not made an exhaustive analysis of this subject either.
  140.  
  141.    To get the best overview of the class capabilities run the demo program.
  142.    It may not look pretty, but with a printout of a sample run and the code
  143.    you should be able to get a really good feel for it.  I have included a
  144.    samples run at the end of this file in case someone doesn't want to
  145.    take the time to compile the demo program.
  146.  
  147.    This ZIP file contains:
  148.  
  149.       MAKEFILE      -   make file to compile & link the files for MSC 7.0
  150.       DATEDEMO.PRJ  -   project file for compiling under Borland C++ 3.1
  151.       DATECL43.DOC  -   this file
  152.       DATECL.H      -   the header file
  153.       DATECL.CPP    -   the member functions
  154.       DATEDEMO.CPP  -   a test program (and a messy one at that!)
  155.       DATECL.LIB    -   a lib file so you can use it even if you
  156.                         don't have MSC7.0, or you just don't feel
  157.                         like fussin' with it!  (Added in v4.0)
  158.  
  159.  
  160. Future possibilities for enhancement include
  161. ============================================
  162.     
  163.    1. Adding a derived Time class, for those applications which require
  164.       the ability to track more than just dates. This would allow the
  165.       manipulation of times for all dates (not just since 1980), and
  166.       arithmetic calculations as well.
  167.  
  168. ===============================================================================
  169.  
  170. Additions/Changes to Version 4.5
  171. ================================
  172.  
  173. -   Correct the implementation code for the unary operators ++ and --.  These
  174.     were reversed in version 4.2 to 4.3 (i.e. prefix was coded as postfix, and
  175.     postfix was coded as prefix).
  176.  
  177. -   Removed 'const' keyword from parameter statments that requires variables to
  178.     be passed by value.
  179.  
  180. ===============================================================================
  181.  
  182. Additions/Changes to Version 4.4
  183. ================================
  184.  
  185. -   Add a little validation to value of the day and month when an object is
  186.     created via a string argument.
  187.  
  188. ===============================================================================
  189.  
  190. Additions/Changes to Version 4.3
  191. ================================
  192.  
  193. -   Add more flexibility in the constructor to support the many string formats
  194.     that are used by the Date class.
  195.  
  196. -   Fix Date::Date(char *) and make it accept the string as a 'const' argument.
  197.     Also, make a copy of the string ('dat') before passing it to strtok() since
  198.     this function modifies its argument!
  199.  
  200. -   Remove the smaller buffer ('buf') and make use of only one buffer to save
  201.     memory.
  202.  
  203. -   Re-code the type cast operator to call formatDate() so the current format
  204.     and options will be applied to the resulting string.
  205.  
  206. -   Changed year to 'int' type to support B.C.E. dates.
  207.  
  208. ===============================================================================
  209.  
  210. Additions/Changes to Version 4.2
  211. ================================
  212.  
  213. -   Made it compatible to both Borland C++ (v 3.1) and Microsoft C++ (v 7.0)
  214.     via #define switches.  Define _BCC for Borland and _MSC for Microsoft.
  215.     See the GO.BAT batch file!
  216.  
  217. -   Fix memory problems in Version 4.1.  There were three 'deadly' memory
  218.     threats introduced by Version 4.1:
  219.  
  220.         (a) In the destructor function, it is erroneous to delete buf without
  221.             referring to it as a vector of characters.  The proper method
  222.             would be:
  223.                             delete [] buf;      // Must have the brackets!
  224.  
  225.             Please review the section "The Free Store and Class Arrays" on
  226.             page 95-99 of the _C++ Tutorial_ from Microsoft's C++ package!
  227.  
  228.         (b) In the Date::operator char *() function, variable buf was allocated
  229.             space every time the function was called.  This causes memory leaks
  230.             when the same Date instance calls this operator function more than
  231.             once during its lifetime.
  232.  
  233.         (c) Also in the Date::operator char *() function, variable buf was
  234.             assigned the address of the constant string BadDate without prior
  235.             release of the memory for buf.
  236.  
  237. -   Modified the following functions to return a Date object instead of a
  238.     reference to a Date object!
  239.  
  240.         Date operator + (const long i);
  241.         Date operator +  (const int  i);
  242.         Date operator - (const long i);
  243.         Date operator - (const int  i);
  244.         Date operator ++ ();
  245.         Date operator ++ (int);
  246.         Date operator -- ();
  247.         Date operator -- (int);
  248.  
  249.     This is important because in Version 4.0 and before, the binary operators
  250.     (+ and -) were declared to return references to Date objects since these
  251.     functions dynamically creates a Date object when the function is called.
  252.     However, there were no provisions for deleting these objects once they
  253.     leave the scope of the function.
  254.  
  255.     In Version 4.1, Mr. Kenneth got rid of this problem of allocation by
  256.     forcing the compiler to generate code to allocate stack space to return
  257.     the objects.  However, Mr. Kenneth 'forget?' to remove the references
  258.     declaration.  Why would this cause problem?  Because when the calling
  259.     program is expecting a reference in return (as opposed to a copy of the
  260.     object), then that reference will be invalid since after the function
  261.     terminates, the temporary object (used to return the value to the calling
  262.     program) will also be terminated.  Thus, the reference to the object is
  263.     rendered obsolete.
  264.  
  265.     To test this, I wrote the following program:
  266.  
  267.  
  268.     #include "datecls4.h"
  269.     #include "iostream.h"
  270.  
  271.     void showDate(Date &dt)
  272.     {
  273.         cout << dt;                 // The (char *) type cast operator is in
  274.     }                               // effect here!
  275.  
  276.     void main()
  277.     {
  278.         Date z("04/13/1967");
  279.         showDate(z+3);
  280.     }
  281.  
  282.     RESULT:
  283.     *** destructor called ***       // Temporary oject is destroyed
  284.     237/7/21
  285.     *** destructor called ***       // Object 'z' is destroyed
  286.  
  287.  
  288.     As dictated by the result, the temporary object (created by the + operator)
  289.     is destroyed before its values are displayed.
  290.  
  291.     By declaring the functions to return an actual Date object instead of a
  292.     reference, we force the compiler to make a copy of it and return it to the
  293.     calling program!
  294.  
  295. -   Fix implementation of the prefix/postfix operators to properly reflect the
  296.     before/after syntax of the unary incrementor.  (C++ provides only the
  297.     the facility to determine which type of operator is being used, but the
  298.     implementation is left to the programmer!)
  299.  
  300. -   Moved all buffer variables to the class level and made them private static
  301.     member data.
  302.     . for the Date::formatDate() function, the buffer is renamed to 'cbuf'
  303.     . for the Date::Operator () function, the buffer is named 'buf'
  304.  
  305. -   Move all publically declared variables/enums into the public portion of
  306.     the class.  Also redefine the #define constants to an enum type.  By doing
  307.     this, we are taking advantage of C++'s encapsulation feature and reduce
  308.     pollution of the global variable names.  This concept is based on the ios
  309.     class. (ie. ios::hex, ios::dec, etc.)
  310.  
  311. -   Also redeclare the 'friend' functions to be member functions (again, making
  312.     use of encapsulation!)
  313.  
  314. -   Rewrote the Date::SetOption() function.  (Made it more compact!)
  315.  
  316. -   Made use of the 'const' feature of C++ to ensure the references returned by
  317.     most of the member functions will be non-modifiable by the calling program.
  318.     (ie. force them to make a copy of it if they want to modify it!)
  319.  
  320. -   In the function Date::formatDate(), for the case Date::EUROPEAN and
  321.     Date::EUROPEAN, fix the code (day_of_week < 0) to (day_of_week < 1).  Also
  322.     removed the statement strcat(cbuf, " ") and put the space into the
  323.     sprintf() statement:
  324.  
  325.             sprintf( cbuf+strlen(cbuf), " %d", abs(year) );
  326.  
  327. ===============================================================================
  328.  
  329. Additions/Changes to Version 4.1
  330. ================================
  331.  
  332. Fixed date display when using the * operator to get a string pointer.
  333.   The code would return xx/xx/  xx if you only supplied a 2 digit year.
  334. Optimized the * operator so Invalid Dates would use a common "invalid date"
  335.   text pointer.
  336. Fixed the +, - and * operators to get rid cases where memory leaks would
  337.  occur.
  338. Fixed some variable casts so the code can be compiled with /W4
  339. Added a destructor tp delete items created dynamically on behalf of the
  340.  object (ie. char *).
  341.  
  342. Release Documentation for Version 4.0
  343. =====================================
  344. Most of the modifications made to version 3.1 were to expand the public
  345. interface.  Below is a list of new features in v4.0:
  346.  
  347.     1. Date &Set() - Sets self to current system date; this may also be
  348.          accomplished by passing initializing a date object like so:
  349.          Date oDate1("Today");  // See demo for examples
  350.  
  351.     2. Date &Set(long lJulian) - Sets self to the specified julian date
  352.  
  353.     3. Date &Set(int nMonth, int nDay, int nYear) - Sets self to specified
  354.          month, day, and year.  The year must be 4 numbers long, not 2.
  355.  
  356.     4. Date &AddWeeks(int nCount = 1) - Add or subtract(use a negative int)
  357.          a specified number of weeks to/from self
  358.  
  359.     5. Date &AddMonths(int nCount = 1) - Add or subtract(use a negative int)
  360.          a specified number of months to/from self
  361.  
  362.     6. Date &AddYears(int nCount = 1); - Add or subtract(use a negative int)
  363.          a specified number of years to/from self
  364.  
  365.     7. int   Day() const - Returns numeric day of the month for self
  366.     8. int   DaysInMonth() - Returns number of days in month (1..31)
  367.     9. int   FirstDOM() const - Returns the First Day Of Month for self as a
  368.          numeric (1..7)
  369.  
  370.    10. char *CDOW() - Returns character Day Of Week ('Sunday'..'Saturday')
  371.    11. int   NDOW() const - Returns the numeric day of the week for self(1..7)
  372.  
  373.    12. int   WOM() - Returns numeric Week Of Month  (1..6)
  374.    13. int   WOY() - Returns numeric Week Of Year   (1..52)
  375.  
  376.    14. char *CMonth() - Character Month name ("January")
  377.    15. int   NMonth() const - Month Number (1..12)
  378.  
  379.    16. Date  BOM() - Returns a new date object that is the First Date Of
  380.          the Month in self.  For example:
  381.         Date oDate1;
  382.         Date oDate2("Today");
  383.         oDate1 = oDate2.BOM();
  384.  
  385.    17. Date  EOM() - Returns a new date object that is the Last Date Of
  386.          the Month in self.  (See example in 16 above)
  387.  
  388.    18. int   NYear4() const - Returns the numeric value of the year for self
  389.          in the form 1992.
  390.  
  391.    19. Date  BOY() - Returns a new date object that is the First Date Of
  392.          the Year in self. (See example 16 above)
  393.  
  394.    20. Date  EOY() - Returns a new date object that is the Last Date Of
  395.          the Year in self. (See example 16 above)
  396.  
  397.    21. Added overloaded operators for + and - to accept int's.
  398.    22. Added overloaded operators for ++ and -- for Postfix notation
  399.  
  400.    23. Switched from the Borland style DOS date structure(date) to the
  401.        Microsoft version(_dosdate_t).
  402.  
  403. Suggestions and general comments are always welcome!
  404. Enjoy!  Chuck :-}
  405.  
  406.  
  407.  
  408. Release Documentation for Version 3.1
  409. =====================================
  410. Subsequent to release 3.00, we (Hill & Simon) decided to collaborate on
  411. several further releases of this date class. This, the first, contains two
  412. new features, as well as a few minor bug fixes.
  413.  
  414. 1. There was a minor bug in the original Computer Language julian/gregorian
  415.    date conversion routines having to do with negative years.
  416.  
  417. 2. The isLeapYear function did not take into account that, prior to 1582,
  418.    years ending in 00 were also leap years.
  419.  
  420. 3. The two-dimensional array of the number of days in each month has been
  421.    eliminated in favor of a computational approach.
  422.  
  423. 4. The function Date::setFormat(XXXX) maintains a static variable (one
  424.    occurance for all Date objects, which controls the format which the
  425.    << operator uses to print objects. "XXXX" can be MONTH, MDY, DAY, FULL,
  426.    or EUROPEAN.  The setting defaults to MDY, but once altered, remains
  427.    altered until reset by another call to setFormat.
  428.  
  429.    The function Date::setOption(Option, Action) maintains a similar static
  430.    variable which enables certain print formatting options. Available options
  431.    at this point are:
  432.       NO_CENTURY  --  Suppress the printing of the century when
  433.               in the MDY format (ex: 01/01/91 instead of
  434.               01/01/1991).
  435.  
  436.       DATE_ABBR   --  Abbreviate month and day names when printing
  437.               in the MONTH, DAY, FULL or EUROPEAN formats.
  438.               (ex. MON, TUE, JAN, FEB, etc.) The length
  439.               or the abbreviation is controlled by a
  440.               DEFINED constant in DATECL31.HPP named
  441.               ABBR_LENGTH, preset to 3.
  442.  
  443.    "Action" is either ON or OFF, and defaults to ON. (Example, the call
  444.    Date::setOption(NO_CENTURY) turns on the century suppression option, and
  445.    it remains set until the call Date::setOption(NO_CENTURY, OFF) is made.
  446.  
  447.    More features, including further expanded print formatting features,
  448.    the derived Time class mentioned above, conversion into various calendar
  449.    formats (Jewish, Chinese, Arabic, etc.), ability to increment Date objects
  450.    by years and months instead of merely days, holiday computations, and more
  451.    are planned.
  452.  
  453.  
  454. Sample run of DATEDEMO.EXE v4.0
  455. ===============================
  456.  
  457.  Date Class v4.0 Demo 
  458.  
  459. Saturday, October 20, 1962
  460. Monday
  461. Tuesday, October 10, 1995
  462. Tuesday, October 30, 1962
  463. 5 October 1962
  464. -14
  465. 8/6/1991
  466. Tommorrow= Sunday, July 14, 1991
  467. a1 (7-14-91) < 8-01-91 ? ==> TRUE
  468. a1 (7-14-91) > 8-01-91 ? ==> FALSE
  469. a1 (7-14-91)== 7-14-91 ? ==> TRUE
  470. a1 (7-14-91)== a3 (7-14-91) ? ==> TRUE
  471. a1 (7-14-91)== a4 (7-15-91) ? ==> FALSE
  472. Today is: 6/28/1992
  473. Today (a4) is: 6/28/1992
  474. Today + 4 is: 7/2/1992
  475. Today - 4 is: 6/24/1992
  476. =========== Leap Year Test ===========
  477. Wednesday, January 15, 1992     Leap    day of year:  15
  478. Tuesday, February 16, 1993      non-Leap        day of year:  47
  479. =========== eom test ==============
  480. b1.eom() (s/b 2/28/91) ==> 2/28/1991
  481. ================== getDate test =====================
  482. a1.getDate()  (s/b 2/16/1993) ==> 2/16/1993
  483. ================== string assignment test ====================
  484. a1 as a string (s/b 2/16/1993) ==> 2/16/1993
  485. ================== setFormat test ============================
  486. a1 (s/b FULL format) ==> Tuesday, February 16, 1993
  487. a1 (s/b EUROPEAN format) ==> 16 February 1993
  488. ================== setOption test ============================
  489. Date abbreviation ON
  490. a1 (s/b MONTH format) ==> Feb
  491. a1 (s/b DAY format) ==> Tue
  492. a1 (s/b FULL format) ==> Tue, Feb 16, 1993
  493. a1 (s/b EUROPEAN format) ==> 16 Feb 1993
  494. Century suppression ON
  495. a1 (s/b MDY format) ==> 2/16/93
  496. Century suppression OFF
  497. a1 (s/b MDY format) ==> 2/16/1993
  498. Century suppression ON
  499. a1 (s/b MDY format) ==> 2/16/93
  500. a1 (s/b FULL format) ==> Tue, Feb 16, 1993
  501.  
  502. =============== Version 4.0 Enhancement Test =================
  503.  
  504. ---------- Set Stuff -----------
  505. First, 'Set' to today...
  506. Before 'Set' => Saturday, November 26, 1966
  507. After  'Set' => Sunday, June 28, 1992
  508.  
  509. Set to 11/26/66 => Saturday, November 26, 1966
  510. Current Julian  => 2439455
  511. Set to Julian 2450000L => Tuesday, October 10, 1995
  512. See! => 2450000
  513. ---------- Add Stuff -----------
  514. Start => Tuesday, October 10, 1995
  515. Add 4 Weeks => Tuesday, November 7, 1995
  516. Sub 1 Month => Saturday, October 7, 1995
  517. Add 2 Years => Tuesday, October 7, 1997
  518. ---------- Misc Stuff -----------
  519. The date aboves' day of the month is => 7
  520. There are 31 days in this month.
  521. The first day of this month lands on 4
  522. This day happens to be Tuesday
  523. the 3 day of the week,
  524. on the 41 week of the year,
  525. on the 2 week of the month, 
  526. (which is October)
  527. the 10nth month in the year.
  528. The year alone is 1997
  529. ---------- First and Last Stuff -----------
  530. The first date of this month is Monday, June 1, 1992
  531. The last date of this month is Tuesday, June 30, 1992
  532. The first date of this year is Wednesday, January 1, 1992
  533. The last date of this year is Thursday, December 31, 1992
  534.  
  535.