home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / math / date.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  50.9 KB  |  1,914 lines

  1.  
  2. --::::::::::
  3. --000_read_me.info
  4. --::::::::::
  5. --------------------------------------------------------------------------
  6. --
  7. -- Considerations For Porting date_package Onto Your System:
  8. --
  9. --    1) This Pager file is in correct compilation order and may
  10. --       be given to a compiler as it stands (see number 2 below).
  11. --       The software documentation is in comments.
  12. --
  13. --    2) The generic date_package takes two parameters.
  14. --       The first parameter, short_value, must be at least a 16
  15. --       bit signed value.  The second parameter, long_value,
  16. --       must be at least a 32 bit signed value.
  17. --
  18. --       With our compiler the type short_integer is a 16 bit signed
  19. --       value and integer is a 32 bit signed value.
  20. --
  21. --       To run the demo programs you will modify the instantiations
  22. --       of date_package to use the 16 and 32 bit type names which
  23. --       are supported by your compiler.
  24. --
  25. --------------------------------------------------------------------------
  26. --
  27. -- Software Development Environment:
  28. --
  29. --     Operating System:    VAX/VMS version 4.4
  30. --     Compiler:        DEC Ada version 1.3  
  31. --
  32. --    The generic date_package and demo programs have been compiled and
  33. --    run on an IBM PC/AT.  The environment consists of MS/DOS version
  34. --    2.1 and version 1.2 of Alsys Ada.
  35. --
  36. --------------------------------------------------------------------------
  37. --
  38. -- Compilation Order:
  39. --
  40. --    date_package_.ada
  41. --    date_package.ada
  42. --    month_print.ada
  43. --    days_till.ada
  44. --    friday_13th.ada
  45. --    test_ranges.ada
  46. --
  47. --------------------------------------------------------------------------
  48. --
  49. -- File Information:
  50. --
  51. -- File Name        Description
  52. --
  53. -- date_package_.ada    Specification of the generic date_package.
  54. -- date_package.ada    Body of date_package.
  55. -- month_print.ada    Demo to print a month in calendar-like style.
  56. -- days_till.ada    Demo similar to month_print but a lot more fun.
  57. -- friday_13th.ada    Demo to find every Friday the 13th in the year range.
  58. -- test_ranges.ada    Demo to test the error trapping of date arithmetic.
  59. --
  60. --------------------------------------------------------------------------
  61. --::::::::::
  62. --date_package_.ada
  63. --::::::::::
  64.  
  65. -------- SIMTEL20 Ada Software Repository Prologue ------------
  66. --
  67. -- Unit name    : generic package specification date_package
  68. -- Version      : 1.0
  69. -- Authors      : David G. Gawron
  70. --              : Dr. Mars J. Gralia
  71. --              : The Johns Hopkins University
  72. --              : Applied Physics Laboratory
  73. --              : Johns Hopkins Road
  74. --              : Laurel, Maryland  20707
  75. -- DDN Address  : dgg@aplvax gralia@aplvax
  76. -- Copyright    : (c) 1986 David G. Gawron, Dr. Mars J. Gralia
  77. -- Date created :  October  1986
  78. -- Release date :  November 1986
  79. -- Last update  :  Gawron, October 1986
  80. -- Machine/System Compiled/Run on : DEC VAX 11/750, DEC Ada v1.3
  81. --
  82. ---------------------------------------------------------------
  83. --
  84. -- Keywords     :  Calendar, Date, Julian Date
  85. --
  86. -- Abstract     :  
  87. --
  88. --  Please refer to the prologue file for a description of the
  89. -- date package.
  90. --
  91. ------------------ Revision history ---------------------------
  92. --
  93. -- DATE         VERSION    AUTHOR                  HISTORY
  94. -- 10/86        1.0     Gawron/Gralia           Initial release
  95. --
  96. ------------------ Distribution and Copyright -----------------
  97. --
  98. -- This prologue must be included in all copies of this software.
  99. --
  100. -- This software is copyright by the authors.
  101. --
  102. -- This software is released to the Ada community.
  103. -- Restrictions on use or distribution:  NONE
  104. --
  105. ------------------ Disclaimer ---------------------------------
  106. --
  107. -- This software and its documentation are provided "AS IS" and
  108. -- without any expressed or implied warranties whatsoever.
  109. -- No warranties as to performance, merchantability, or fitness
  110. -- for a particular purpose exist.
  111. --
  112. -- Because of the diversity of conditions and hardware under
  113. -- which this software may be used, no warranty of fitness for
  114. -- a particular purpose is offered.  The user is advised to
  115. -- test the software thoroughly before relying on it.  The user
  116. -- must assume the entire risk and liability of using this
  117. -- software.
  118. --
  119. -- In no event shall any person or organization of people be
  120. -- held responsible for any direct, indirect, consequential
  121. -- or inconsequential damages or lost profits.
  122. --
  123. -------------------END-PROLOGUE--------------------------------
  124.  
  125.  
  126.  
  127. generic
  128.     type short_value is range <>;   -- at least a 16 bit signed value
  129.     type long_value  is range <>;   -- at least a 32 bit signed value
  130.  
  131.  
  132.  
  133. package date_package is
  134.  
  135.  
  136.  
  137.     -- date_type is the main object dealt with by all of
  138.     -- the routines in this package.
  139.     --
  140.     type date_type is private;
  141.  
  142.  
  143.  
  144.     -- These types constrain the values
  145.     -- used to compose dates.
  146.     --
  147.     -- The lower bound of the year range is set at 1753 to
  148.     -- get around a glitch in the calendar that happened in
  149.     -- September 1752.  The internal routines used for date
  150.     -- calculations don't account for this glitch.  The upper
  151.     -- bound of the year range corresponds to the upper bound
  152.     -- of the year number used in CALERDAR.
  153.     --
  154.     subtype year_number_type  is short_value range 1753..2099;
  155.     subtype month_number_type is short_value range 1..12;
  156.     subtype day_number_type   is short_value range 1..31;
  157.     subtype julian_day_type   is short_value range 1..366;
  158.  
  159.  
  160.  
  161.     -- day_delta_type reflects the number of days from
  162.     -- January 1, year_number_type'first to December 31, year_number_type'last.
  163.     -- The range spans the values possible as a result of the 
  164.     -- subtraction operator when applied to two dates.
  165.     --
  166.     subtype day_delta_type is long_value range -126_739..126_739;
  167.  
  168.  
  169.  
  170.     -- day_name_type provides the standard names for the
  171.     -- days of the week.
  172.     --
  173.     type day_name_type is
  174.     (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday);
  175.  
  176.  
  177.  
  178.  
  179.     -- Description:
  180.     --    current_date returns the current date.
  181.     --  Note: that the range of dates returned is dependent upon
  182.     --  the range of the system date.  The current range is todays
  183.     --  date to December 31, year_number_type'last.
  184.     --
  185.     -- Raises:
  186.     --  nothing
  187.     --
  188.     function current_date
  189.     return date_type;
  190.  
  191.  
  192.  
  193.     -- Description:
  194.     --  year returns the year number of the given date.
  195.     --
  196.     -- Raises:
  197.     --  nothing.
  198.     --
  199.     function year (date : in date_type)
  200.     return year_number_type;
  201.  
  202.  
  203.  
  204.     -- Description:
  205.     --  month returns the month number of the given date.
  206.     --
  207.     -- Raises:
  208.     --  nothing.
  209.     --
  210.     function month (date : in date_type)
  211.     return month_number_type;
  212.  
  213.  
  214.  
  215.     -- Description:
  216.     --  day returns the day number of the given date.
  217.     --
  218.     -- Raises:
  219.     --  nothing.
  220.     --
  221.     function day (date : in date_type)
  222.     return day_number_type;
  223.  
  224.  
  225.  
  226.     -- Description:
  227.     --  day_of_year returns the annual Julian day
  228.     --  number of the given date.
  229.     --
  230.     -- Raises:
  231.     --  nothing.
  232.     --
  233.     function day_of_year (date : in date_type)
  234.     return julian_day_type;
  235.  
  236.  
  237.  
  238.     -- Description:
  239.     --  day_name returns the day name of the given date.
  240.     --
  241.     -- Raises:
  242.     --  nothing.
  243.     --
  244.     function day_name (date : in date_type)
  245.     return day_name_type;
  246.  
  247.  
  248.  
  249.     -- Description:
  250.     --  split breaks apart a date into the year, month, day, and
  251.     --  day name components.
  252.     --
  253.     -- Raises:
  254.     --  nothing.
  255.     --
  256.     procedure split (date     : in date_type;
  257.              year     : out year_number_type;
  258.              month    : out month_number_type;
  259.              day      : out day_number_type;
  260.              day_name : out day_name_type);
  261.  
  262.  
  263.     -- Description:
  264.     --    split break apart a date into the year and
  265.     --    annual Julian day number components.
  266.     --
  267.     -- Raises:
  268.     --  nothing.
  269.     --
  270.     procedure split (date        : in date_type;
  271.              year        : out year_number_type;
  272.              julian_day  : out julian_day_type);
  273.  
  274.  
  275.  
  276.     -- Description:
  277.     --  date_of takes a year, month, and day then converts
  278.     --  them into a date.
  279.     --
  280.     -- Raises:
  281.     --  date_is_not_valid when the day given is larger than
  282.     --  the maximum number of days in the given month.
  283.     --    For example, February 30 or September 31.
  284.     --
  285.     function date_of (year  : in year_number_type;
  286.               month : in month_number_type;
  287.               day   : in day_number_type)
  288.     return date_type;
  289.  
  290.  
  291.     -- Description:
  292.     --  date_of takes a year and annual Julian day number
  293.     --  then converts them into a date.
  294.     --
  295.     -- Raises:
  296.     --  date_is_not_valid when the day number given is
  297.     --  366 for non-leap years.
  298.     --
  299.     function date_of (year        : in year_number_type;
  300.               julian_day  : in julian_day_type)
  301.     return date_type;
  302.  
  303.  
  304.  
  305.     -- Description:
  306.     --  + adds days to a date.  This is one form of + where
  307.     --  the date is on the left side of the operator.
  308.     --
  309.     -- Raises:
  310.     --  result_out_of_range when the resulting date does
  311.     --    not fall in the year range
  312.     --    year_number_type'first to year_number_type'last.
  313.     --
  314.     function "+" (left  : in date_type;
  315.           right : in day_delta_type)
  316.     return date_type;
  317.  
  318.  
  319.     -- Description:
  320.     --  + adds days to a date.  This another form of + where
  321.     --  the date is on the right side of the operator.
  322.     --
  323.     -- Raises:
  324.     --  result_out_of_range when the resulting date does
  325.     --    not fall in the year range
  326.     --    year_number_type'first to year_number_type'last.
  327.     --
  328.     function "+" (left  : in day_delta_type;
  329.           right : in date_type)
  330.     return date_type;
  331.  
  332.  
  333.  
  334.     -- Description:
  335.     --  - subtracts days days from a date.  This is one form
  336.     --  of - where the date is on the left side of the operator
  337.     --  and the days are on the right.
  338.     --
  339.     -- Raises:
  340.     --  result_out_of_range when the resulting date does
  341.     --    not fall in the year range
  342.     --    year_number_type'first to year_number_type'last.
  343.     --
  344.     function "-" (left  : in date_type;
  345.           right : in day_delta_type)
  346.     return date_type;
  347.  
  348.  
  349.     -- Description:
  350.     --  - subtracts a date from a date.  This is another form
  351.     --  of - where the result is expreseed in days.
  352.     --
  353.     -- Raises:
  354.     --  nothing.
  355.     --
  356.     function "-" (left  : in date_type;
  357.           right : in date_type)
  358.     return day_delta_type;
  359.  
  360.  
  361.  
  362.     -- Description:
  363.     --  The following functions provide logical
  364.     --  operations on dates.
  365.     --
  366.     -- Raises:
  367.     --  exceptions are not raised by any of
  368.     --    these routines.
  369.  
  370.     function "<" (left, right : in date_type)
  371.     return boolean;
  372.  
  373.     function "<=" (left, right : in date_type)
  374.     return boolean;
  375.  
  376.  
  377.  
  378.     function ">" (left, right : in date_type)
  379.     return boolean;
  380.  
  381.     function ">=" (left, right : in date_type)
  382.     return boolean;
  383.  
  384.  
  385.  
  386.     -- Raised when the used gives a date that is not valid.
  387.     -- For example, February 30 for any year would cause this
  388.     -- exception to be raised.
  389.     --
  390.     -- Raised by both versions of the date_of function.
  391.     --
  392.     date_is_not_valid        : exception;
  393.  
  394.  
  395.     -- Raised when the result of date arithmetic is not in the
  396.     -- range for dates.  For example, 1/1/1753 minus 2 days
  397.     -- would cause this exception to be raised.
  398.     --
  399.     -- Raised by both versions of "+" and by "-" which handles
  400.     -- date_type and day_delta_type.
  401.     --
  402.     result_out_of_range        : exception;
  403.  
  404.  
  405.  
  406.     private
  407.     type date_type is
  408.         record
  409.         year        : year_number_type;
  410.         month        : month_number_type;
  411.         day        : day_number_type;
  412.         day_name    : day_name_type;
  413.         julian_date : long_value;
  414.         end record;
  415.  
  416.  
  417.  
  418. end date_package;
  419. --::::::::::
  420. --date_package.ada
  421. --::::::::::
  422.  
  423. -------- SIMTEL20 Ada Software Repository Prologue ------------
  424. --
  425. -- Unit name    : package body date_package
  426. -- Version      : 1.0
  427. -- Authors      : David G. Gawron
  428. --              : Dr. Mars J. Gralia
  429. --              : The Johns Hopkins University
  430. --              : Applied Physics Laboratory
  431. --              : Johns Hopkins Road
  432. --              : Laurel, Maryland  20707
  433. -- DDN Address  : dgg@aplvax gralia@aplvax
  434. -- Copyright    : (c) 1986 David G. Gawron, Dr. Mars J. Gralia
  435. -- Date created :  October  1986
  436. -- Release date :  November 1986
  437. -- Last update  :  Gawron, October 1986
  438. -- Machine/System Compiled/Run on : DEC VAX 11/750, DEC Ada v1.3
  439. --
  440. ---------------------------------------------------------------
  441. --
  442. -- Keywords     :  Calendar, Date, Julian Date
  443. --
  444. -- Abstract     :  
  445. --
  446. --  Please refer to the prologue file for a description of the
  447. -- date package.
  448. --
  449. ------------------ Revision history ---------------------------
  450. --
  451. -- DATE         VERSION    AUTHOR                  HISTORY
  452. -- 10/86        1.0     Gawron/Gralia           Initial release
  453. --
  454. ------------------ Distribution and Copyright -----------------
  455. --
  456. -- This prologue must be included in all copies of this software.
  457. --
  458. -- This software is copyright by the authors.
  459. --
  460. -- This software is released to the Ada community.
  461. -- Restrictions on use or distribution:  NONE
  462. --
  463. ------------------ Disclaimer ---------------------------------
  464. --
  465. -- This software and its documentation are provided "AS IS" and
  466. -- without any expressed or implied warranties whatsoever.
  467. -- No warranties as to performance, merchantability, or fitness
  468. -- for a particular purpose exist.
  469. --
  470. -- Because of the diversity of conditions and hardware under
  471. -- which this software may be used, no warranty of fitness for
  472. -- a particular purpose is offered.  The user is advised to
  473. -- test the software thoroughly before relying on it.  The user
  474. -- must assume the entire risk and liability of using this
  475. -- software.
  476. --
  477. -- In no event shall any person or organization of people be
  478. -- held responsible for any direct, indirect, consequential
  479. -- or inconsequential damages or lost profits.
  480. --
  481. -------------------END-PROLOGUE--------------------------------
  482.  
  483.  
  484.  
  485. with text_io;
  486. with calendar;
  487.  
  488.  
  489. package body date_package is
  490.  
  491.  
  492.  
  493.  
  494.  
  495. ------------ START OF NON EXPORTED TYPES AND VARIABLES ------------
  496.  
  497.  
  498.     -- These types will be used to construct tables that will
  499.     -- hold information about the days of the months.
  500.     --
  501.     subtype day_span_type is short_value range 0..334;
  502.  
  503.     type month_table_type is
  504.     array(month_number_type) of day_span_type;
  505.  
  506.  
  507.  
  508.     -- days_in_month_table holds a count of the number of days
  509.     -- in each month.  The table is set up for a non-leap year.
  510.     -- In a leap year a local copy of the table is modified to
  511.     -- reflect the 29 days in February.
  512.     --
  513.     days_in_month_table : constant month_table_type :=
  514.     (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  515.  
  516.  
  517. ------------ END OF NON EXPORTED TYPES AND VARIABLES  ------------
  518.  
  519.  
  520.  
  521.  
  522.  
  523. ------------ START OF NON EXPORTED ROUTINES ------------
  524.  
  525.  
  526.     -- Description:
  527.     --  leap_year will return true when the given year is
  528.     --  a leap year.
  529.     --
  530.     -- Raises:
  531.     --  nothing.
  532.     --
  533.     function leap_year (year : in year_number_type)
  534.     return boolean is
  535.     begin
  536.         if ((year mod 4 = 0)    and
  537.            (year mod 100 /= 0)) or
  538.            (year mod 400 = 0)
  539.         then
  540.         return true;
  541.         else
  542.         return false;
  543.         end if;
  544.     end leap_year;
  545.  
  546.  
  547.  
  548.     -- Description:
  549.     --  valid_date will return true if the given day is less-than
  550.     --  or equal-to the number of days in the given month.
  551.     --  days_in_month_table will be modified when a leap year
  552.     --  is encountered.
  553.     --
  554.     -- Raises:
  555.     --  nothing.
  556.     --
  557.     function valid_date (year  : in year_number_type;
  558.              month : in month_number_type;
  559.              day   : in day_number_type)
  560.     return boolean is
  561.  
  562.     days_in_month        : short_value;
  563.  
  564.     begin
  565.         days_in_month := days_in_month_table(month);
  566.  
  567.         if (leap_year (year) and month = 2) then
  568.         days_in_month := 29;
  569.         end if;
  570.  
  571.         if (day <= days_in_month) then
  572.         return true;
  573.         else
  574.         return false;
  575.         end if;
  576.     end valid_date;
  577.  
  578.  
  579.  
  580.     -- Description:
  581.     --  This version of valid_date will return true if the
  582.     --  given julian day number is less-than or equal-to 365
  583.     --  for a non-leap year.  When a lear year is encountered
  584.     --  true is returned automatically since the range constraint
  585.     --  on julian_day_type will prevent the value from being
  586.     --  greater-than 366.
  587.     --
  588.     -- Raises:
  589.     --  nothing.
  590.     --
  591.     function valid_date (year        : in year_number_type;
  592.              julian_day  : in julian_day_type)
  593.     return boolean is
  594.  
  595.     begin
  596.         if (leap_year (year)) then
  597.         return true;
  598.         elsif (julian_day <= 365) then
  599.         return true;
  600.         else
  601.         return false;
  602.         end if;
  603.     end valid_date;
  604.  
  605.  
  606.  
  607.     -- Description:
  608.     --  calculate_date will take an internal julian date and
  609.     --  convert it into a date_type.
  610.     --
  611.     --  The code of this function is a modified version of algorithm
  612.     --  199 from the Collected Algorithms of the ACM.
  613.     --  The author of algorithm 199 is Robert G. Tantzen.
  614.     --
  615.     -- Raises:
  616.     --  nothing.
  617.     --
  618.     function calculate_date (julian_date : in long_value)
  619.     return date_type is
  620.  
  621.     a    : long_value;
  622.     b    : long_value;
  623.     c    : long_value;
  624.     d    : long_value;
  625.     date    : date_type;
  626.  
  627.     begin
  628.         a := julian_date - 1_721_119;
  629.         b := (4 * a - 1) / 146_097;    
  630.         a := 4 * a - 1 - 146_097 * b;    
  631.         d := a / 4;
  632.         a := (4 * d + 3) / 1_461;
  633.         d := 4 * d + 3 - 1_461 * a;
  634.         d := (d + 4) / 4;
  635.         c := (5 * d - 3) / 153;
  636.         d := 5 * d - 3 - 153 * c;
  637.         d := (d + 5) / 5;
  638.         b := 100 * b + a;
  639.  
  640.         if (c < 10) then
  641.         c := c + 3;
  642.         else
  643.         c := c - 9;
  644.         b := b + 1;
  645.         end if;
  646.  
  647.         date.year        := year_number_type(b);
  648.         date.month       := month_number_type(c);
  649.         date.day         := day_number_type(d);
  650.         date.day_name    := day_name_type'val((julian_date + 1) mod 7);
  651.         date.julian_date := julian_date;
  652.  
  653.         return date;
  654.     end calculate_date;
  655.  
  656.  
  657.  
  658.     -- Description:
  659.     --  calculate_julian will take a year, month, and day and
  660.     --  convert it into an internal julian date.
  661.     --
  662.     --  The code of this function is a modified version of algorithm
  663.     --  199 from the Collected Algorithms of the ACM.
  664.     --  The author of algorithm 199 is Robert G. Tantzen.
  665.     --
  666.     -- Raises:
  667.     --  nothing.
  668.     --
  669.     function calculate_julian (year  : in year_number_type;
  670.                    month : in month_number_type;
  671.                    day   : in day_number_type)
  672.     return long_value is
  673.  
  674.     internal_year    : long_value;
  675.     internal_month    : long_value;
  676.     internal_day    : long_value;
  677.     julian_date    : long_value;
  678.     c        : long_value;
  679.     ya        : long_value;
  680.  
  681.     begin
  682.         internal_year  := long_value(year);
  683.         internal_month := long_value(month);
  684.         internal_day   := long_value(day);
  685.  
  686.         if (internal_month > 2) then
  687.         internal_month := internal_month - 3;
  688.         else
  689.         internal_month := internal_month + 9;
  690.         internal_year  := internal_year - 1;
  691.         end if;
  692.  
  693.         c  := internal_year / 100;
  694.         ya := internal_year - (100 * c);
  695.         julian_date := (146_097 * c) / 4 +
  696.                (1_461 * ya) / 4 +
  697.                (153 * internal_month + 2) / 5 +
  698.                internal_day + 1_721_119;
  699.  
  700.         return julian_date;
  701.     end calculate_julian;
  702.  
  703.  
  704. ------------ END OF NON EXPORTED ROUTINES ------------
  705.  
  706.  
  707.  
  708.  
  709.  
  710. ------------ START OF EXPORTED ROUTINES ------------
  711.  
  712.  
  713.     function current_date
  714.     return date_type is
  715.  
  716.     date        : date_type;
  717.     current_time    : calendar.time;
  718.  
  719.     begin
  720.         -- The range of the dates the will be returned by
  721.         -- this function depend upon the CALENDAR package.
  722.         -- Currently the largest date CALENDAR handles is
  723.         -- December 31 2099.
  724.         --
  725.         current_time := calendar.clock;
  726.  
  727.         date.year  := year_number_type(calendar.year (current_time));
  728.         date.month := month_number_type(calendar.month (current_time));
  729.         date.day   := day_number_type(calendar.day (current_time));
  730.  
  731.         date.julian_date :=
  732.         calculate_julian (date.year, date.month, date.day);
  733.  
  734.         date.day_name := day_name_type'val((date.julian_date + 1) mod 7);
  735.  
  736.         return date;
  737.     end current_date;
  738.  
  739.  
  740.  
  741.     function year (date : in date_type)
  742.     return year_number_type is
  743.     begin
  744.         return date.year;
  745.     end year;
  746.  
  747.  
  748.  
  749.     function month (date : in date_type)
  750.     return month_number_type is
  751.     begin
  752.         return date.month;
  753.     end month;
  754.  
  755.  
  756.  
  757.     function day (date : in date_type)
  758.     return day_number_type is
  759.     begin
  760.         return date.day;
  761.     end day;
  762.  
  763.  
  764.  
  765.     function day_of_year (date : in date_type)
  766.     return julian_day_type is
  767.  
  768.     -- day_count_table holds a count, for each month, of the total
  769.     -- number of days in the preceeding months.  For example,
  770.     -- there are 59 days before March in a non-leap year.
  771.     --
  772.     day_count_table : constant month_table_type :=
  773.         (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
  774.  
  775.     days_since_first_of_year    : julian_day_type;
  776.  
  777.     begin
  778.         days_since_first_of_year :=
  779.         day_count_table(date.month) + date.day;
  780.  
  781.         -- When a date in a leap year is given and the date
  782.         -- falls after February the count is adjusted to
  783.         -- account for the extra day in February.
  784.         --
  785.         if (leap_year (date.year) and (date.month > 2)) then
  786.         days_since_first_of_year := days_since_first_of_year + 1;
  787.         end if;
  788.  
  789.         return days_since_first_of_year;
  790.     end day_of_year;
  791.  
  792.  
  793.  
  794.     function day_name (date : in date_type)
  795.     return day_name_type is
  796.     begin
  797.         return date.day_name;
  798.     end day_name;
  799.  
  800.  
  801.  
  802.     procedure split (date     : in date_type;
  803.              year     : out year_number_type;
  804.              month    : out month_number_type;
  805.              day      : out day_number_type;
  806.              day_name : out day_name_type) is
  807.     begin
  808.         year     := date.year;
  809.         month    := date.month;
  810.         day      := date.day;
  811.         day_name := date.day_name;
  812.     end split;
  813.  
  814.  
  815.     procedure split (date       : in date_type;
  816.              year       : out year_number_type;
  817.              julian_day : out julian_day_type) is
  818.     begin
  819.         year       := date.year;
  820.         julian_day := day_of_year (date);
  821.     end split;
  822.  
  823.  
  824.  
  825.     function date_of (year  : in year_number_type;
  826.               month : in month_number_type;
  827.               day   : in day_number_type)
  828.     return date_type is
  829.  
  830.     date    : date_type;
  831.  
  832.     begin
  833.         if (valid_date (year, month, day)) then
  834.         date.year  := year;
  835.         date.month := month;
  836.         date.day   := day;
  837.  
  838.         date.julian_date := calculate_julian (year, month, day);
  839.  
  840.         date.day_name :=
  841.             day_name_type'val((date.julian_date + 1) mod 7);
  842.         return date;
  843.         else
  844.         raise date_is_not_valid;
  845.         end if;
  846.     end date_of;
  847.  
  848.  
  849.     function date_of (year       : in year_number_type;
  850.               julian_day : in julian_day_type)
  851.     return date_type is
  852.  
  853.     month        : month_number_type;
  854.     date        : date_type;
  855.  
  856.     day_table   : month_table_type;
  857.     days        : short_value;
  858.  
  859.     begin
  860.         if (valid_date (year, julian_day)) then
  861.  
  862.         day_table := days_in_month_table;
  863.  
  864.         -- When the given date is in a leap year the table
  865.         -- is adjusted to account for the extra day in February.
  866.         --
  867.         if (leap_year (year)) then
  868.             day_table(2) := 29;
  869.         end if;
  870.  
  871.         -- The months are looped through and the annual
  872.         -- julian day number reduced until it falls into
  873.         -- a month.
  874.         --
  875.         days := julian_day;
  876.         for i in month_number_type loop
  877.             month := i;
  878.             exit when (days - day_table(i)) <= 0;
  879.             days := days - day_table(i);
  880.         end loop;
  881.  
  882.         date.year  := year;
  883.         date.month := month;
  884.         date.day   := day_number_type(days);
  885.  
  886.         date.julian_date :=
  887.             calculate_julian (date.year, date.month, date.day);
  888.  
  889.         date.day_name :=
  890.             day_name_type'val((date.julian_date + 1) mod 7);
  891.         return date;
  892.         else
  893.         raise date_is_not_valid;
  894.         end if;
  895.     end date_of;
  896.  
  897.  
  898.  
  899.     function "+" (left  : in date_type;
  900.           right : in day_delta_type)
  901.     return date_type is
  902.     begin
  903.         return calculate_date (left.julian_date + right);
  904.  
  905.         -- A constraint error in this case would originate in
  906.         -- calculate_date and indicate that the range constraint
  907.         -- on year_number_type was violated by the result of
  908.         -- left.julian_date + right.
  909.         --
  910.         exception
  911.         when constraint_error =>
  912.             raise result_out_of_range;
  913.     end "+";
  914.  
  915.  
  916.     function "+" (left  : in day_delta_type;
  917.           right : in date_type)
  918.     return date_type is
  919.     begin
  920.         return calculate_date (right.julian_date + left);
  921.  
  922.         -- A constraint error in this case would originate in
  923.         -- calculate_date and indicate that the range constraint
  924.         -- on year_number_type was violated by the result of
  925.         -- right.julian_date + left.
  926.         --
  927.         exception
  928.         when constraint_error =>
  929.             raise result_out_of_range;
  930.     end "+";
  931.  
  932.  
  933.  
  934.     function "-" (left  : in date_type;
  935.           right : in day_delta_type)
  936.     return date_type is
  937.     begin
  938.         return calculate_date (left.julian_date - right);
  939.  
  940.         -- A constraint error in this case would originate in
  941.         -- calculate_date and indicate that the range constraint
  942.         -- on year_number_type was violated by the result of
  943.         -- left.julian_date - right.
  944.         --
  945.         exception
  946.         when constraint_error =>
  947.             raise result_out_of_range;
  948.     end "-";
  949.  
  950.  
  951.     function "-" (left  : in date_type;
  952.           right : in date_type)
  953.     return day_delta_type is
  954.     begin
  955.         return left.julian_date - right.julian_date;
  956.     end "-";
  957.  
  958.  
  959.  
  960.     function "<" (left, right : in date_type)
  961.     return boolean is
  962.     begin
  963.         return (left.julian_date < right.julian_date);
  964.     end "<";
  965.  
  966.  
  967.     function "<=" (left, right : in date_type)
  968.     return boolean is
  969.     begin
  970.         return (left.julian_date <= right.julian_date);
  971.     end "<=";
  972.  
  973.  
  974.  
  975.     function ">" (left, right : in date_type)
  976.     return boolean is
  977.     begin
  978.         return (left.julian_date > right.julian_date);
  979.     end ">";
  980.  
  981.  
  982.     function ">=" (left, right : in date_type)
  983.     return boolean is
  984.     begin
  985.         return (left.julian_date >= right.julian_date);
  986.     end ">=";
  987.  
  988.  
  989. ------------ END OF EXPORTED ROUTINES ------------
  990.  
  991.  
  992.  
  993. end date_package;
  994. --::::::::::
  995. --month_print.ada
  996. --::::::::::
  997.  
  998. -------- SIMTEL20 Ada Software Repository Prologue ------------
  999. --
  1000. -- Unit name    : procedure month_print
  1001. -- Version      : 1.0
  1002. -- Authors      : David G. Gawron
  1003. --              : The Johns Hopkins University
  1004. --              : Applied Physics Laboratory
  1005. --              : Johns Hopkins Road
  1006. --              : Laurel, Maryland  20707
  1007. -- DDN Address  : dgg@aplvax
  1008. -- Copyright    : (c) 1986 David G. Gawron
  1009. -- Date created :  October  1986
  1010. -- Release date :  November 1986
  1011. -- Last update  :  Gawron, October  1986
  1012. -- Machine/System Compiled/Run on : DEC VAX 11/750, DEC Ada v1.3
  1013. --
  1014. ---------------------------------------------------------------
  1015. --
  1016. -- Keywords     :  Demonstration of date_package
  1017. --
  1018. -- Abstract     :  
  1019. --
  1020. --  This procedure demonstrates the use of several date_package
  1021. -- entry points.  The procedure generates a calendar-like listing
  1022. -- of a month that includes the annual Julian day number for each
  1023. -- day of the month.  Try it for a leap year.
  1024. --
  1025. ------------------ Revision history ---------------------------
  1026. --
  1027. -- DATE         VERSION    AUTHOR                  HISTORY
  1028. -- 10/86        1.0     Gawron                  Initial release
  1029. --
  1030. ------------------ Distribution and Copyright -----------------
  1031. --
  1032. -- This prologue must be included in all copies of this software.
  1033. --
  1034. -- This software is copyright by the author.
  1035. --
  1036. -- This software is released to the Ada community.
  1037. -- Restrictions on use or distribution:  NONE
  1038. --
  1039. ------------------ Disclaimer ---------------------------------
  1040. --
  1041. -- This software and its documentation are provided "AS IS" and
  1042. -- without any expressed or implied warranties whatsoever.
  1043. -- No warranties as to performance, merchantability, or fitness
  1044. -- for a particular purpose exist.
  1045. --
  1046. -- Because of the diversity of conditions and hardware under
  1047. -- which this software may be used, no warranty of fitness for
  1048. -- a particular purpose is offered.  The user is advised to
  1049. -- test the software thoroughly before relying on it.  The user
  1050. -- must assume the entire risk and liability of using this
  1051. -- software.
  1052. --
  1053. -- In no event shall any person or organization of people be
  1054. -- held responsible for any direct, indirect, consequential
  1055. -- or inconsequential damages or lost profits.
  1056. --
  1057. -------------------END-PROLOGUE--------------------------------
  1058.  
  1059.  
  1060.  
  1061. with text_io;
  1062. with date_package;
  1063.  
  1064.  
  1065.  
  1066. procedure month_print is
  1067.  
  1068.  
  1069.     package date is new date_package(short_value => short_integer,
  1070.                      long_value  => integer);
  1071.  
  1072.  
  1073.     use text_io;
  1074.     use date;
  1075.  
  1076.  
  1077.     -- The date package doesn't provide the month names
  1078.     -- so this type is used.
  1079.     --
  1080.     type month_name_type is
  1081.     (January, February, March, April, May, June,
  1082.      July, August, September, October, November, December);
  1083.  
  1084.  
  1085.  
  1086.     -- These will specify the year and month to be printed.
  1087.     --
  1088.     base_year            : year_number_type;
  1089.     base_month            : month_number_type;
  1090.  
  1091.  
  1092.  
  1093.     -- These dates will be used to print the month
  1094.     -- in calerdar form.
  1095.     --
  1096.     base_date_1            : date_type;
  1097.     base_date_2            : date_type;
  1098.  
  1099.  
  1100.  
  1101.     -- These are used in the layout of the values
  1102.     -- printed for a month.
  1103.     --
  1104.     column_setting_1        : positive_count;
  1105.     column_setting_2        : positive_count;
  1106.  
  1107.  
  1108.  
  1109.     -- This will be used to tell if the user wants to continue
  1110.     -- running the demo.
  1111.     --
  1112.     user_response        : character;
  1113.  
  1114.  
  1115.  
  1116.     -- The I/O for each type we deal with.
  1117.     --
  1118.     package year_io       is new integer_io(year_number_type);
  1119.     package month_io      is new integer_io(month_number_type);
  1120.     package day_io        is new integer_io(day_number_type);
  1121.     package day_name_io   is new enumeration_io(day_name_type);
  1122.     package month_name_io is new enumeration_io(month_name_type);
  1123.     package julian_day_io is new integer_io(julian_day_type);
  1124.  
  1125.  
  1126.  
  1127.     begin
  1128.  
  1129.     loop
  1130.     new_line (25);
  1131.     put_line ("This demo takes one date as input.");
  1132.     put_line ("The date given will specify the year and month");
  1133.     put_line ("to be printed in a style similar to a calendar.");
  1134.     new_line;
  1135.     put_line ("The printout will include the annual Julian day");
  1136.     put_line ("number for each day of the month.  The annual Julian");
  1137.     put_line ("day is a count of the number of days into a year.");
  1138.     put_line ("For example, December 31 has an annual Julian day");
  1139.     put_line ("number of 365 in non-leap years and 366 in leap years.");
  1140.     new_line (2);
  1141.  
  1142.     put ("Valid year numbers are within the range ");
  1143.     year_io.put (year_number_type'first);
  1144.     put (" to ");
  1145.     year_io.put (year_number_type'last);
  1146.     new_line;
  1147.     put ("and valid month numbers are within the range ");
  1148.     month_io.put (month_number_type'first);
  1149.     put (" to ");
  1150.     month_io.put (month_number_type'last);
  1151.     put (".");
  1152.     new_line (2);
  1153.  
  1154.  
  1155.     put ("Please enter the month to be printed out: ");
  1156.     month_io.get(base_month);
  1157.     new_line;
  1158.     put ("and the year: ");
  1159.     year_io.get(base_year);
  1160.  
  1161.     -- The dates are set up to be the first
  1162.     -- of the given month.
  1163.     --
  1164.     base_date_1 := date_of (base_year, base_month, 1);
  1165.     base_date_2 := base_date_1;
  1166.  
  1167.  
  1168.     -- The month name and year are printed at
  1169.     -- the top.
  1170.     --
  1171.     new_line (25);
  1172.     text_io.set_col (35);
  1173.     month_name_io.put (month_name_type'val(base_month - 1));
  1174.     year_io.put (base_year);
  1175.     text_io.new_line (2);
  1176.  
  1177.  
  1178.     -- The weekday names are printed.
  1179.     --
  1180.     column_setting_1 := 1;
  1181.     for day_name in day_name_type loop
  1182.         set_col (column_setting_1);
  1183.         day_name_io.put (day_name);
  1184.         column_setting_1 := column_setting_1 + 12;
  1185.     end loop;
  1186.     text_io.new_line (2);
  1187.  
  1188.  
  1189.     -- An offset into the week is calculated.  The offset
  1190.     -- places the start of the month on the correct day.
  1191.     --
  1192.     column_setting_1 :=
  1193.         (day_name_type'pos(day_name (base_date_1)) * 12) + 1;
  1194.  
  1195.     column_setting_2 := column_setting_1;
  1196.  
  1197.  
  1198.     loop
  1199.         -- The days of the month are printed.
  1200.         --
  1201.         loop
  1202.         exit when (base_month /= month (base_date_1));
  1203.         set_col (column_setting_1);
  1204.         day_io.put (day (base_date_1));
  1205.         exit when (day_name (base_date_1) = Saturday) or
  1206.               ((base_month = 12) and (day (base_date_1) = 31));
  1207.         column_setting_1 := column_setting_1 + 12;
  1208.         base_date_1 := base_date_1 + 1;
  1209.         end loop;
  1210.  
  1211.  
  1212.         -- And the annual Julian day is printed below the
  1213.         -- day number.
  1214.         --
  1215.         loop
  1216.         exit when (base_month /= month (base_date_2));
  1217.         set_col (column_setting_2);
  1218.         text_io.put ("(");
  1219.         julian_day_io.put (item  => day_of_year (base_date_2),
  1220.                           width => 1);
  1221.         text_io.put (")");
  1222.         exit when (day_name (base_date_2) = Saturday) or
  1223.               ((base_month = 12) and (day (base_date_2) = 31));
  1224.         column_setting_2 := column_setting_2 + 12;
  1225.         base_date_2 := base_date_2 + 1;
  1226.         end loop;
  1227.  
  1228.  
  1229.         -- When the month flips over or at the end of the
  1230.         -- year we know the printing is done.
  1231.         --
  1232.         exit when (base_month /= month (base_date_1)) or
  1233.               ((base_month = 12) and (day (base_date_1) = 31));
  1234.  
  1235.         -- Setup for the next week to be printed.
  1236.         --
  1237.         text_io.new_line (2);
  1238.         column_setting_1 := 1;
  1239.         column_setting_2 := 1;
  1240.         base_date_1 := base_date_1 + 1;
  1241.         base_date_2 := base_date_1;
  1242.     end loop;
  1243.  
  1244.  
  1245.     new_line (2);
  1246.     put ("Enter a Q to quit or any other character to continue: ");
  1247.     get (user_response);
  1248.     exit when (user_response = 'Q');
  1249.  
  1250.  
  1251.     end loop;
  1252.  
  1253.  
  1254.     exception
  1255.         when data_error =>
  1256.         new_line (2);
  1257.         put_line ("Input data out of range.  Bye!");
  1258.  
  1259.     end month_print;
  1260. --::::::::::
  1261. --days_till.ada
  1262. --::::::::::
  1263.  
  1264. -------- SIMTEL20 Ada Software Repository Prologue ------------
  1265. --
  1266. -- Unit name    : procedure days_till
  1267. -- Version      : 1.0
  1268. -- Authors      : David G. Gawron
  1269. --              : The Johns Hopkins University
  1270. --              : Applied Physics Laboratory
  1271. --              : Johns Hopkins Road
  1272. --              : Laurel, Maryland  20707
  1273. -- DDN Address  : dgg@aplvax
  1274. -- Copyright    : (c) 1986 David G. Gawron
  1275. -- Date created :  October  1986
  1276. -- Release date :  November 1986
  1277. -- Last update  :  Gawron, October  1986
  1278. -- Machine/System Compiled/Run on : DEC VAX 11/750, DEC Ada v1.3
  1279. --
  1280. ---------------------------------------------------------------
  1281. --
  1282. -- Keywords     :  Demonstration of date_package
  1283. --
  1284. -- Abstract     :  
  1285. --
  1286. --  This procedure demonstrates the use of several date_package
  1287. -- entry points.  The procedure generates a calendar-like listing
  1288. -- of a month that includes a countdown by days to some date
  1289. -- specified by the user.  Try it for a 'days till Christmas'
  1290. -- listing.
  1291. --
  1292. ------------------ Revision history ---------------------------
  1293. --
  1294. -- DATE         VERSION    AUTHOR                  HISTORY
  1295. -- 10/86        1.0     Gawron                  Initial release
  1296. --
  1297. ------------------ Distribution and Copyright -----------------
  1298. --
  1299. -- This prologue must be included in all copies of this software.
  1300. --
  1301. -- This software is copyright by the author.
  1302. --
  1303. -- This software is released to the Ada community.
  1304. -- Restrictions on use or distribution:  NONE
  1305. --
  1306. ------------------ Disclaimer ---------------------------------
  1307. --
  1308. -- This software and its documentation are provided "AS IS" and
  1309. -- without any expressed or implied warranties whatsoever.
  1310. -- No warranties as to performance, merchantability, or fitness
  1311. -- for a particular purpose exist.
  1312. --
  1313. -- Because of the diversity of conditions and hardware under
  1314. -- which this software may be used, no warranty of fitness for
  1315. -- a particular purpose is offered.  The user is advised to
  1316. -- test the software thoroughly before relying on it.  The user
  1317. -- must assume the entire risk and liability of using this
  1318. -- software.
  1319. --
  1320. -- In no event shall any person or organization of people be
  1321. -- held responsible for any direct, indirect, consequential
  1322. -- or inconsequential damages or lost profits.
  1323. --
  1324. -------------------END-PROLOGUE--------------------------------
  1325.  
  1326.  
  1327.  
  1328. with text_io;
  1329. with date_package;
  1330.  
  1331.  
  1332.  
  1333. procedure days_till is
  1334.  
  1335.  
  1336.     package date is new date_package(short_value => short_integer,
  1337.                      long_value  => integer);
  1338.  
  1339.  
  1340.     use text_io;
  1341.     use date;
  1342.  
  1343.  
  1344.     -- The date package doesn't provide the month names
  1345.     -- so this type is used.
  1346.     --
  1347.     type month_name_type is
  1348.     (January, February, March, April, May, June,
  1349.      July, August, September, October, November, December);
  1350.  
  1351.  
  1352.  
  1353.     -- These will specify the fixed date that will be counted
  1354.     -- down to.
  1355.     --
  1356.     target_year            : year_number_type;
  1357.     target_month        : month_number_type;
  1358.     target_day            : day_number_type;
  1359.  
  1360.  
  1361.  
  1362.     -- These will specify the year and month
  1363.     -- that will be printed.
  1364.     --
  1365.     base_year            : year_number_type;
  1366.     base_month            : month_number_type;
  1367.  
  1368.  
  1369.  
  1370.     -- These dates will be used to print the month
  1371.     -- in calendar form.
  1372.     --
  1373.     base_date_1            : date_type;
  1374.     base_date_2            : date_type;
  1375.     fixed_target_date        : date_type;
  1376.  
  1377.  
  1378.  
  1379.     -- days_till is the difference in days between the fixed
  1380.     -- date and the day of the month.
  1381.     --
  1382.     days_till            : day_delta_type;
  1383.  
  1384.  
  1385.  
  1386.     -- These are used in the layout of the values
  1387.     -- printed for a month.
  1388.     --
  1389.     column_setting_1        : positive_count;
  1390.     column_setting_2        : positive_count;
  1391.  
  1392.  
  1393.  
  1394.     -- This will be used to tell if the user wants to continue
  1395.     -- running the demo.
  1396.     --
  1397.     user_response        : character;
  1398.  
  1399.  
  1400.  
  1401.     -- The I/O for each type we deal with.
  1402.     --
  1403.     package year_io       is new integer_io(year_number_type);
  1404.     package month_io      is new integer_io(month_number_type);
  1405.     package day_io        is new integer_io(day_number_type);
  1406.     package day_name_io   is new enumeration_io(day_name_type);
  1407.     package month_name_io is new enumeration_io(month_name_type);
  1408.     package till_io       is new integer_io(day_delta_type);
  1409.  
  1410.  
  1411.  
  1412.     begin
  1413.  
  1414.     loop
  1415.     new_line (25);
  1416.     put_line ("This demo takes two dates as input.");
  1417.     put_line ("The first date given will be a target date of some");
  1418.     put_line ("future or past event.");
  1419.     put_line ("The second date given will specify the year and month");
  1420.     put_line ("to be printed in a style similar to a calendar.");
  1421.     new_line;
  1422.     put_line ("The printout will include a days-till count down to the");
  1423.     put_line ("target date.  For example, if you entered 12 25 1986 for");
  1424.     put_line ("the first date and 11 1986 for the second, then a");
  1425.     put_line ("print out of November 1986 will be generated and include");
  1426.     put_line ("a days-till Christmas count down.");
  1427.     new_line (2);
  1428.  
  1429.     put ("Valid year numbers are within the range ");
  1430.     year_io.put (year_number_type'first);
  1431.     put (" to ");
  1432.     year_io.put (year_number_type'last);
  1433.     put (",");
  1434.     new_line;
  1435.     put ("valid month numbers are within the range ");
  1436.     month_io.put (month_number_type'first);
  1437.     put (" to ");
  1438.     month_io.put (month_number_type'last);
  1439.     put (",");
  1440.     new_line;
  1441.     put ("and valid day numbers are within the range ");
  1442.     day_io.put (day_number_type'first);
  1443.     put (" to ");
  1444.     day_io.put (day_number_type'last);
  1445.     put (".");
  1446.     new_line (2);
  1447.  
  1448.  
  1449.     put ("Please enter a target month: ");
  1450.     month_io.get (target_month);
  1451.     new_line;
  1452.     put ("Please enter a target day: ");
  1453.     day_io.get (target_day);
  1454.     new_line;
  1455.     put ("Please enter a target year: ");
  1456.     year_io.get (target_year);
  1457.     new_line (2);
  1458.  
  1459.     -- The fixed date stays the same through out
  1460.     -- the procedure.
  1461.     --
  1462.     fixed_target_date := date_of (target_year, target_month, target_day);
  1463.  
  1464.  
  1465.     put ("Now enter the month to be printed out: ");
  1466.     month_io.get (base_month);
  1467.     new_line;
  1468.     put ("and the year : ");
  1469.     year_io.get (base_year);
  1470.  
  1471.     -- The dates are set up to be the first
  1472.     -- of the given month.
  1473.     --
  1474.     base_date_1 := date_of (base_year, base_month, 1);
  1475.     base_date_2 := base_date_1;
  1476.  
  1477.  
  1478.     -- The month name and year are printed at
  1479.     -- the top.
  1480.     --
  1481.     new_line (25);
  1482.     text_io.set_col (35);
  1483.     month_name_io.put (month_name_type'val(base_month - 1));
  1484.     year_io.put (base_year);
  1485.     text_io.new_line (2);
  1486.  
  1487.  
  1488.     -- The weekday names are printed.
  1489.     --
  1490.     column_setting_1 := 1;
  1491.     for day_name in day_name_type loop
  1492.         set_col (column_setting_1);
  1493.         day_name_io.put (day_name);
  1494.         column_setting_1 := column_setting_1 + 12;
  1495.     end loop;
  1496.     text_io.new_line (2);
  1497.  
  1498.  
  1499.     -- An offset into the week is calculated.  The offset
  1500.     -- places the start of the month on the correct day.
  1501.     --
  1502.     column_setting_1 :=
  1503.         (day_name_type'pos(day_name (base_date_1)) * 12) + 1;
  1504.  
  1505.     column_setting_2 := column_setting_1;
  1506.  
  1507.  
  1508.     loop
  1509.         -- The days of the month are printed.
  1510.         --
  1511.         loop
  1512.         exit when (base_month /= month (base_date_1));
  1513.         set_col (column_setting_1);
  1514.         day_io.put (day (base_date_1));
  1515.         exit when (day_name (base_date_1) = Saturday) or
  1516.               ((base_month = 12) and (day (base_date_1) = 31));
  1517.         column_setting_1 := column_setting_1 + 12;
  1518.         base_date_1 := base_date_1 + 1;
  1519.         end loop;
  1520.  
  1521.  
  1522.         -- An the count down is printed below the
  1523.         -- day number.
  1524.         --
  1525.         loop
  1526.         exit when (base_month /= month (base_date_2));
  1527.         set_col (column_setting_2);
  1528.         days_till := fixed_target_date - base_date_2;
  1529.         text_io.put ("(");
  1530.         till_io.put (item  => days_till,
  1531.                  width => 1);
  1532.         text_io.put (")");
  1533.         exit when (day_name (base_date_2) = Saturday) or
  1534.               ((base_month = 12) and (day (base_date_2) = 31));
  1535.         column_setting_2 := column_setting_2 + 12;
  1536.         base_date_2 := base_date_2 + 1;
  1537.         end loop;
  1538.  
  1539.  
  1540.         -- When the month flips over or at the end of the
  1541.         -- year we know the printing is done.
  1542.         --
  1543.         exit when (base_month /= month (base_date_1)) or
  1544.               ((base_month = 12) and (day (base_date_1) = 31));
  1545.  
  1546.  
  1547.         -- Setup for the next week to be printed.
  1548.         --
  1549.         text_io.new_line (2);
  1550.         column_setting_1 := 1;
  1551.         column_setting_2 := 1;
  1552.         base_date_1 := base_date_1 + 1;
  1553.         base_date_2 := base_date_1;
  1554.     end loop;
  1555.  
  1556.  
  1557.     new_line (2);
  1558.     put ("Enter a Q to quit or any other character to continue: ");
  1559.     get (user_response);
  1560.     exit when (user_response = 'Q');
  1561.  
  1562.  
  1563.     end loop;
  1564.  
  1565.  
  1566.     exception
  1567.         when date_is_not_valid =>
  1568.         new_line (2);
  1569.         month_name_io.put (month_name_type'val(target_month - 1));
  1570.         put (" doesn't have that many days");
  1571.         if ((target_month = 2) and (target_day = 29)) then
  1572.             put (" in ");
  1573.             year_io.put (target_year);
  1574.         end if;
  1575.         put_line (".");
  1576.  
  1577.         when data_error =>
  1578.         new_line (2);
  1579.         put_line ("Input data out of range.  Bye!");
  1580.  
  1581.  
  1582.     end days_till;
  1583. --::::::::::
  1584. --friday_13th.ada
  1585. --::::::::::
  1586.  
  1587. -------- SIMTEL20 Ada Software Repository Prologue ------------
  1588. --
  1589. -- Unit name    : procedure days_till
  1590. -- Version      : 1.0
  1591. -- Authors      : David G. Gawron
  1592. --              : The Johns Hopkins University
  1593. --              : Applied Physics Laboratory
  1594. --              : Johns Hopkins Road
  1595. --              : Laurel, Maryland  20707
  1596. -- DDN Address  : dgg@aplvax
  1597. -- Copyright    : (c) 1986 David G. Gawron
  1598. -- Date created :  October  1986
  1599. -- Release date :  November 1986
  1600. -- Last update  :  Gawron, October  1986
  1601. -- Machine/System Compiled/Run on : DEC VAX 11/750, DEC Ada v1.3
  1602. --
  1603. ---------------------------------------------------------------
  1604. --
  1605. -- Keywords     :  Demonstration of date_package
  1606. --
  1607. -- Abstract     :  
  1608. --
  1609. --  This procedure demonstrates the use of several date_package
  1610. -- entry points.  The procedure generates a listing which contains
  1611. -- every Friday the 13th in the year range defined by the date
  1612. -- package.  In the end, each month is printed showing the number
  1613. -- of Friday the 13th's found for that month.
  1614. --
  1615. ------------------ Revision history ---------------------------
  1616. --
  1617. -- DATE         VERSION    AUTHOR                  HISTORY
  1618. -- 10/86        1.0     Gawron                  Initial release
  1619. --
  1620. ------------------ Distribution and Copyright -----------------
  1621. --
  1622. -- This prologue must be included in all copies of this software.
  1623. --
  1624. -- This software is copyright by the author.
  1625. --
  1626. -- This software is released to the Ada community.
  1627. -- Restrictions on use or distribution:  NONE
  1628. --
  1629. ------------------ Disclaimer ---------------------------------
  1630. --
  1631. -- This software and its documentation are provided "AS IS" and
  1632. -- without any expressed or implied warranties whatsoever.
  1633. -- No warranties as to performance, merchantability, or fitness
  1634. -- for a particular purpose exist.
  1635. --
  1636. -- Because of the diversity of conditions and hardware under
  1637. -- which this software may be used, no warranty of fitness for
  1638. -- a particular purpose is offered.  The user is advised to
  1639. -- test the software thoroughly before relying on it.  The user
  1640. -- must assume the entire risk and liability of using this
  1641. -- software.
  1642. --
  1643. -- In no event shall any person or organization of people be
  1644. -- held responsible for any direct, indirect, consequential
  1645. -- or inconsequential damages or lost profits.
  1646. --
  1647. -------------------END-PROLOGUE--------------------------------
  1648.  
  1649.  
  1650.  
  1651. with text_io;
  1652. with date_package;
  1653.  
  1654.  
  1655.  
  1656. procedure friday_13th is
  1657.  
  1658.  
  1659.     package date is new date_package(short_value => short_integer,
  1660.                      long_value  => integer);
  1661.  
  1662.  
  1663.     use text_io;
  1664.     use date;
  1665.  
  1666.  
  1667.     -- The date package doesn't provide the month names
  1668.     -- so this type is used.
  1669.     --
  1670.     type month_name_type is
  1671.     (January, February, March, April, May, June,
  1672.      July, August, September, October, November, December);
  1673.  
  1674.  
  1675.  
  1676.     -- These will keep track of stats for the number of times
  1677.     -- Friday the 13th shows up in a month.
  1678.     --
  1679.     type month_stats_type is
  1680.     array (month_name_type) of natural;
  1681.  
  1682.     month_stats            : month_stats_type;
  1683.     month_name            : month_name_type;
  1684.     total            : natural := 0;
  1685.  
  1686.  
  1687.  
  1688.  
  1689.  
  1690.     -- These will specify a possible date for Friday the 13th.
  1691.     --
  1692.     target_year            : year_number_type;
  1693.     target_month        : month_number_type;
  1694.  
  1695.  
  1696.  
  1697.     -- This will be used to find all Friday 13th.
  1698.     -- dates.
  1699.     --
  1700.     base_date            : date_type;
  1701.  
  1702.  
  1703.  
  1704.     -- The I/O for each type we deal with.
  1705.     --
  1706.     package year_io       is new integer_io(year_number_type);
  1707.     package month_name_io is new enumeration_io(month_name_type);
  1708.     package stats_io      is new integer_io(natural);
  1709.  
  1710.  
  1711.  
  1712.     begin
  1713.  
  1714.     new_line (25);
  1715.     put_line ("This demo finds all Friday the 13th's from");
  1716.     year_io.put (year_number_type'first);
  1717.     put (" to ");
  1718.     year_io.put (year_number_type'last);
  1719.     put (".");
  1720.     new_line (2);
  1721.  
  1722.  
  1723.     for i in month_name_type loop
  1724.         month_stats(i) := 0;
  1725.     end loop;
  1726.  
  1727.  
  1728.     for base_year in year_number_type loop
  1729.         for base_month in month_number_type loop
  1730.         base_date := date_of (base_year, base_month, 13);
  1731.         if (day_name (base_date) = Friday) then
  1732.             month_name := month_name_type'val(base_month - 1);
  1733.             month_stats(month_name) := month_stats(month_name) + 1;
  1734.  
  1735.             month_name_io.put (month_name);
  1736.             set_col (12);
  1737.             year_io.put (base_year);
  1738.             new_line;
  1739.         end if;
  1740.         end loop;
  1741.     end loop;
  1742.  
  1743.  
  1744.     for i in month_name_type loop
  1745.         total := total + month_stats(i);
  1746.     end loop;
  1747.  
  1748.     new_line;
  1749.     put_line ("These are the statistics for Friday the 13th");
  1750.     put_line ("density per month.");
  1751.     new_line;
  1752.     put ("There were ");
  1753.     stats_io.put (item => total, width => 1);
  1754.     put_line (" Friday the 13th's.");
  1755.     new_line;
  1756.  
  1757.  
  1758.     for i in month_name_type loop
  1759.         month_name_io.put (i);
  1760.         set_col (12);
  1761.         stats_io.put (item => month_stats(i), width => 1);
  1762.         new_line;
  1763.     end loop;
  1764.  
  1765.  
  1766.     end friday_13th;
  1767. --::::::::::
  1768. --test_ranges.ada
  1769. --::::::::::
  1770.  
  1771. -------- SIMTEL20 Ada Software Repository Prologue ------------
  1772. --
  1773. -- Unit name    : procedure test_ranges
  1774. -- Version      : 1.0
  1775. -- Authors      : David G. Gawron
  1776. --              : The Johns Hopkins University
  1777. --              : Applied Physics Laboratory
  1778. --              : Johns Hopkins Road
  1779. --              : Laurel, Maryland  20707
  1780. -- DDN Address  : dgg@aplvax
  1781. -- Copyright    : (c) 1986 David G. Gawron
  1782. -- Date created :  October  1986
  1783. -- Release date :  November 1986
  1784. -- Last update  :  Gawron, October  1986
  1785. -- Machine/System Compiled/Run on : DEC VAX 11/750, DEC Ada v1.3
  1786. --
  1787. ---------------------------------------------------------------
  1788. --
  1789. -- Keywords     :  Demonstration of date_package
  1790. --
  1791. -- Abstract     :  
  1792. --
  1793. --  This procedure demonstrates error trapping when using date
  1794. -- arithmetic.
  1795. --
  1796. ------------------ Revision history ---------------------------
  1797. --
  1798. -- DATE         VERSION    AUTHOR                  HISTORY
  1799. -- 10/86        1.0     Gawron                  Initial release
  1800. --
  1801. ------------------ Distribution and Copyright -----------------
  1802. --
  1803. -- This prologue must be included in all copies of this software.
  1804. --
  1805. -- This software is copyright by the author.
  1806. --
  1807. -- This software is released to the Ada community.
  1808. -- Restrictions on use or distribution:  NONE
  1809. --
  1810. ------------------ Disclaimer ---------------------------------
  1811. --
  1812. -- This software and its documentation are provided "AS IS" and
  1813. -- without any expressed or implied warranties whatsoever.
  1814. -- No warranties as to performance, merchantability, or fitness
  1815. -- for a particular purpose exist.
  1816. --
  1817. -- Because of the diversity of conditions and hardware under
  1818. -- which this software may be used, no warranty of fitness for
  1819. -- a particular purpose is offered.  The user is advised to
  1820. -- test the software thoroughly before relying on it.  The user
  1821. -- must assume the entire risk and liability of using this
  1822. -- software.
  1823. --
  1824. -- In no event shall any person or organization of people be
  1825. -- held responsible for any direct, indirect, consequential
  1826. -- or inconsequential damages or lost profits.
  1827. --
  1828. -------------------END-PROLOGUE--------------------------------
  1829.  
  1830.  
  1831.  
  1832. with text_io;
  1833. with date_package;
  1834.  
  1835.  
  1836.  
  1837. procedure test_ranges is
  1838.  
  1839.  
  1840.     package date is new date_package(short_value => short_integer,
  1841.                      long_value  => integer);
  1842.  
  1843.  
  1844.     use text_io;
  1845.     use date;
  1846.  
  1847.  
  1848.     -- This will be used as a base to force range constraint errors
  1849.     -- when doing date arithmetic.
  1850.     --
  1851.     first_date            : date_type;
  1852.     todays_date            : date_type;
  1853.     last_date            : date_type;
  1854.     test_date            : date_type;
  1855.  
  1856.  
  1857.  
  1858.     begin
  1859.  
  1860.     new_line (25);
  1861.     put_line ("This demo forces range constraint errors to see");
  1862.     put_line ("how well the date package handles date arithmetic.");
  1863.     new_line;
  1864.     put_line ("The tests should all produce messages with");
  1865.     put_line ("a banner indicating the test number.  Any");
  1866.     put_line ("number skiped will indicate that something is");
  1867.     put_line ("wrong in the date package.");
  1868.     new_line;
  1869.     put_line ("These cases will be tested:");
  1870.     put_line ("   1) Subtract one day from the first valid date.");
  1871.     put_line ("   2) Add one day to the last valid date.");
  1872.     put_line ("   3) Subtract full range of days from the current date.");
  1873.     put_line ("   4) Add full range of days to the current date.");
  1874.     new_line (3);
  1875.  
  1876.  
  1877.     first_date  := date_of (year_number_type'first, 1, 1);
  1878.     todays_date := current_date;
  1879.     last_date   := date_of (year_number_type'last, 12, 31);
  1880.  
  1881.  
  1882.     begin
  1883.         test_date := first_date - 1;
  1884.         exception
  1885.         when result_out_of_range =>
  1886.             put_line ("------- Test 1 OK -------");
  1887.     end;
  1888.  
  1889.         
  1890.     begin
  1891.         test_date := last_date + 1;
  1892.         exception
  1893.         when result_out_of_range =>
  1894.             put_line ("------- Test 2 OK -------");
  1895.     end;
  1896.  
  1897.         
  1898.     begin
  1899.         test_date := todays_date - day_delta_type'last;
  1900.         exception
  1901.         when result_out_of_range =>
  1902.             put_line ("------- Test 3 OK -------");
  1903.     end;
  1904.  
  1905.         
  1906.     begin
  1907.         test_date := todays_date + day_delta_type'last;
  1908.         exception
  1909.         when result_out_of_range =>
  1910.             put_line ("------- Test 4 OK -------");
  1911.     end;
  1912.         
  1913.     end test_ranges;
  1914.