In Chapters 3 and 7 we
discussed some of the uses of Ada's predefined package
Ada.Calendar
. This package provides many facilities for working
with dates and times, but it does not provide a way to represent calendar dates
that is suitable for reading and displaying. In this section we develop a
specification for a simple package to give us a nicer form for dates, including
procedures to read and display dates. In Chapter 10
we will refine this package
to make it more capable and robust.
Program 8.3
WITH Ada.Calendar; PACKAGE Simple_Dates IS ------------------------------------------------------------------------ --| Specification for package to represent calendar dates --| in a form convenient for reading and displaying. --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ TYPE Months IS (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); TYPE Date IS RECORD Month: Months; Day: Ada.Calendar.Day_Number; Year: Ada.Calendar.Year_Number; END RECORD; PROCEDURE Get(Item: OUT Date); -- Pre: None -- Post: Reads a date in mmm dd yyyy form, returning it in Item PROCEDURE Put(Item: IN Date); -- Pre: Item is defined -- Post: Displays a date in mmm dd yyyy form FUNCTION Today RETURN Date; -- Pre: None -- Post: Returns today's date END Simple_Dates;We want the
SimpleDates
package to provide a standard representation
for the months of the year. We do this by giving an enumeration type
Months
representing the abbreviated names of the months:
TYPE Months IS (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec);We can now make use of this type and the day and year types provided by
Ada.Calendar
to define a record type for a date, using the month
abbreviation for the month field, as follows:
TYPE Date IS RECORD Month: Months; Day: Ada.Calendar.Day_Number; Year: Ada.Calendar.Year_Number; END RECORD;We could have defined our own year and month number types, but we chose instead to use types that were already available to us in a predefined Ada package (instead of "reinventing the wheel"). The input program
Get
will
read a date in the form
OCT 31 1995and the output program
Put
will display dates in this form as well.
One more operation is included: a function Today
that returns a
date record initialized with the date the program is being run. In other words,
given a declaration
D: SimpleDates.Date;the statement
D := SimpleDates.Today;sets the fields of
D
to today's month, day, and year, respectively. Two
things are noteworthy about this function. First, it is an example of a
parameterless function; like Ada.Calendar.Clock
, it
requires no parameters. Second, the return type of the function is a record,
namely, one of type Date
.
Program 8.4 shows the body of package
SimpleDates
.
Program 8.4
WITH Ada.Calendar; WITH Ada.Text_IO; WITH Ada.Integer_Text_IO; PACKAGE BODY Simple_Dates IS ------------------------------------------------------------------------ --| Body for package to represent calendar dates --| in a form convenient for reading and displaying. --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 ------------------------------------------------------------------------ PACKAGE Month_IO IS NEW Ada.Text_IO.Enumeration_IO(Enum => Months); PROCEDURE Get(Item: OUT Date) IS BEGIN -- Get Month_IO.Get(Item => Item.Month); Ada.Integer_Text_IO.Get(Item => Item.Day); Ada.Integer_Text_IO.Get(Item => Item.Year); END Get; PROCEDURE Put(Item: IN Date) IS BEGIN -- Put Month_IO.Put (Item => Item.Month, Width=>1); Ada.Text_IO.Put(Item => ' '); Ada.Integer_Text_IO.Put(Item => Item.Day, Width => 1); Ada.Text_IO.Put(Item => ' '); Ada.Integer_Text_IO.Put(Item => Item.Year, Width => 4); END Put; FUNCTION Today RETURN Date IS Right_Now : Ada.Calendar.Time; -- holds internal clock value Result : Date; BEGIN -- Today -- Get the current time value from the computer's clock Right_Now := Ada.Calendar.Clock; -- Extract the current month, day, and year from the time value Result.Month := Months'Val(Ada.Calendar.Month(Right_Now)- 1); Result.Day := Ada.Calendar.Day (Right_Now); Result.Year := Ada.Calendar.Year (Date => Right_Now); RETURN Result; END Today; END Simple_Dates;There are just two procedures,
Get
and Put
.
SimpleDates.Get
expects its input to be in the form given above.
It is not a robust procedure like the ones in
Robust_Input
(
Section
6.7) which prompt the user until correct input is entered; it is more like
the predefined Get
routines in Ada.Text_IO
: If
anything is wrong with the input, Get
simply allows the exception
to be passed back to the calling routine.
What can go wrong? The month, day, or year entered by the user can be badly
formed or out of range, or the combination of month, day, and year can form a
nonexistent date such as Feb 30 1995
. A badly formed month, day,
or year will result in Ada.Text_IO.Data_Error
being raised by
Months_IO
; an out-of-range month or year will result in
Constraint_Error
being raised. This routine does not discover the
case of a nonexistent date; a revised version of the package, to be developed
in Chapter 10, will correct this shortcoming and add the desired robustness.
The procedure SimpleDates.Put
displays a date in the MMM
DD YYYY
form. Also note how the function Today
uses the
package Ada.Calendar
to produce today's date and return it to the
caller.
Program
8.5 shows a test of the Simple_Dates
package. Because the
package is not robust, we include an exception-handling loop in the test
program.
Proram 8.5
WITH Ada.Text_IO; WITH Simple_Dates; PROCEDURE Test_Simple_Dates IS ------------------------------------------------------------------------ --| --| Program to test the Simple_Dates package --| --| Author: Michael B. Feldman, The George Washington University --| Last Modified: July 1995 --| ------------------------------------------------------------------------ D: Simple_Dates.Date; BEGIN -- Test_Simple_Dates -- first test the function Today D := Simple_Dates.Today; Ada.Text_IO.Put(Item => "Today is "); Simple_Dates.Put(Item => D); Ada.Text_IO.New_Line; LOOP BEGIN -- block for exception handler Ada.Text_IO.Put("Please enter a date in MMM DD YYYY form > "); Simple_Dates.Get(Item => D); EXIT; -- only if no exception is raised EXCEPTION WHEN Constraint_Error => Ada.Text_IO.Skip_Line; Ada.Text_IO.Put(Item => "Badly formed date; try again, please."); Ada.Text_IO.New_Line; WHEN Ada.Text_IO.Data_Error => Ada.Text_IO.Skip_Line; Ada.Text_IO.Put(Item => "Badly formed date; try again, please."); Ada.Text_IO.New_Line; END; END LOOP; -- assert: at this point, D contains a correct date record Ada.Text_IO.Put(Item => "You entered "); Simple_Dates.Put(Item => D); Ada.Text_IO.New_Line; END Test_Simple_Dates;Sample Run
Today is AUG 16 1995 Please enter a date in MMM DD YYYY form > mmm dd yyyy Badly formed date; try again, please. Please enter a date in MMM DD YYYY form > Dec 15 1944 You entered DEC 15 1944
SimpleDates
change the day
field of a Date
variable? For example, suppose the variable
represents November 30, 1991. Can the client program change the 30 to a 31?
Copyright © 1996 by Addison-Wesley Publishing Company, Inc.