3. Dates and Times

Introduction

------------------------------------------------------------------------------
-- All standard Ada date / time subprograms are defined in the packages
-- Ada.Calendar and Ada.Real_Time
--
-- Time values can be split into a Year number, a Month number, a Day
-- (of the month) number, and a Seconds number.
------------------------------------------------------------------------------

Finding Today's Date

------------------------------------------------------------------------------
Now : Time;

Now := Clock; -- A parameter-less function returning the current time value.
Put("The current date is ");
Put(Item => Year(Now), Width => 4);
Put(Item => Month(Now), Width => 3);
Put(Item => Day(Now), Width => 3);

The current date is 2002  2 25
------------------------------
Now : Time;
This_Year  : Year_Number;
This_Month : Month_Number;
This_Day   : Day_Number;
This_Seconds : Day_Duration;

Split(Date => Now, Year => This_Year, Month => This_Month,
      Day => This_Day, Seconds => This_Seconds);
Put("The current date is ");
Put(Item => This_Year, Width => 4);
Put(Item => This_Month, Width => 3);
Put(Item => This_Day, Width => 3);

The current date is 2002  2 25
------------------------------------------------------------------------------

Converting DMYHMS to Epoch Seconds

------------------------------------------------------------------------------
-- Ada does not directly deal with minutes. Minutes are contained in the
-- Seconds value, which is the number of seconds into the day for the current
-- time. Seconds is a value from 0.0 through 86400.0
This_Year    : Year_Number;
This_Month   : Month_Number;
This_Day     : Day_Number;
This_Seconds : Day_Duration;
The_Time     : Time;

The_Time := Time_Of(Year => This_Year, Month => This_Month,
                    Day => This_Day, Seconds => This_Seconds);
-------------------------------
-- Year_Number is an integer from 1901 through 2099
-- Month_Number is an integer from 1 through 12
-- Day_Number is an integer from 1 through 31
-- Day_Duration is a Fixed Point type from 0.0 through 86400.0
------------------------------------------------------------------------------

Converting Epoch Seconds to DMYHMS

------------------------------------------------------------------------------
The_Time     : Time;
The_Year     : Year_Number;
The_Month    : Month_Number;
The_Day      : Day_Number;
The_Seconds  : Day_Duration;
The_Minutes  : Integer;
The_Hour     : Integer;
Seconds      : Integer;

Split(Date => The_Time, Year => The_Year, Month => The_Month,
      Day => The_Day, Seconds => The_Seconds);
The_Hour := The_Seconds / 3600;
The_Minutes := (The_Seconds - (3600 * The_Hour)) / 60;
Seconds := The_Seconds mod 60;
------------------------------------------------------------------------------

Adding to or Subtracting from a Date

------------------------------------------------------------------------------
-- Time addition involves adding a Duration to a Time.
-- A Duration is a total number of seconds.
Birthtime : Time;
Interval  : Duration;
Then      : Time;

Birthtime := Time_Of(Year => 1973, Month => 1, Day => 18,
             Seconds => ((3.0 * 3600.0) +  -- 3:45:50
                         (45.0 * 60.0) + 50.0));
Interval := 5.0 +               -- 5 seconds
            (17.0 * 60.0) +     -- 17 minutes
            (2.0 * 3600.0) +    -- 2 hours
            (55.0 * 86400.0);   -- 55 days
Then := Birthtime + Interval; --
-- or
Then := Interval + Birthtime;

Put("Then is ");
Put(Item => Month(Then), Width => 2);
Put(Item => Day(Then), Width => 3);
Put(Item => Year(Then), Width => 5);
Put(Item => Seconds(Then) / 3600, Width => 3);
Put(":");
Put(Item => (Seconds(Then) - (Seconds(Then) / 3600 * 3600)) / 60,
    Width => 2);
Put(":");
Put(Item => Seconds(Then) mod 60, Width => 2);
New_Line;

Then is 3 14 1973  6: 2:55
------------------------------------------------------------------------------

Difference of Two Dates

------------------------------------------------------------------------------
Seconds : Duration;
Recent  : Time;
Earlier : Time;

Seconds := Recent - Earlier;

Earlier := Recent - Seconds;
------------------------------------------------------------------------------

Day in a Week/Month/Year or Week Number

------------------------------------------------------------------------------
-- Ada provides no standard subprogram for calculation of week number, day of
-- week, Julian Date, or Month name.
-- Those calculations can be performed, with month names localized to the
-- current locale, by simple user defined functions.
------------------------------------------------------------------------------

Parsing Dates and Times from Strings

------------------------------------------------------------------------------
date : String := "1998-06-03"; -- YYYY-MM-DD format
The_Year : Year_Number;
The_Month : Month_Number;
The_Day : Day_Number;
Index : Positive;

Get(From => date, Item => The_Year, Last => Index); -- Get YYYY as an integer
Get(From => date(Index + 2..date'Last),  -- Get MM skipping first "-"
    Item => The_Month, Last => Index);
Get(From => date(Index + 2..date'Last),  -- Get DD skipping second "-"
    Item => The_Day, Last => Index);
-- Calculate the time value at midnight of that date
The_Time : Time;

The_Time := Time_Of(Year => The_Year, Month => The_Month,
                    Day => The_Day, Seconds => 0.0);
------------------------------------------------------------------------------

Printing a Date

------------------------------------------------------------------------------
function Month_Name(Month : Month_Number) return String is
   type Months is (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT,
                        NOV, DEC);
begin
   -- convert month number to enumeration value then convert enumeration
   -- value to a string
   return Months'Image(Months'Val(Month - 1));
end Month_Name;
-------------------------------
SEP 21 15:33:36 1997
-------------------------------
The_Time : Time;
The_Time := Time_Of(Year => 1997,
                    Month => 9,
                    Day   => 21,
                    Seconds => 36.0 +
                               (33.0 * 60.0) +
                               (15.0 * 3600.0));
Put(Month_Name(Month(The_Time)) & " ");
Put(Item => Day(The_Time), Width => 2);
Put(Item => Seconds(The_Time) / 3600, Width => 3);
Put(":");
Put(Item => (Seconds(The_Time) - (Seconds(The_Time) / 3600 * 3600)) / 60,
    Width => 2);
Put(":");
Put(Item => Seconds(The_Time) mod 60, Width => 2);
Put(Item => Year(The_Time), Width => 5);
New_Line;
------------------------------------------------------------------------------

High-Resolution Timers

------------------------------------------------------------------------------
-- High resolution time is provided by the Ada.Real_Time package.
-- High resolution time values shall be sufficient to uniquely represent the
-- range of real times from program start up to 50 years later.
-- Tick (the avearage time interval during which the clock value remains constant)
-- shall be no greater than 1 millisecond. Time_Unit (the smallest amount of real
-- time representable by the time type) shall be less than or equal to 20
-- microseconds.

with Ada.Real_Time; use Ada.Real_Time;

t0 : Time;
t1 : Time;

t0 := Clock; -- Get initial time stamp;
-- Perform some operation
t1 := Clock; -- Get ending time stamp;

elapsed : Time_Span;

elapsed := t1 - t0; -- Time in seconds i.e 0.0015
------------------------------------------------------------------------------

Short Sleeps

------------------------------------------------------------------------------
-- sleeps are achieved in Ada using the "delay" statement.
-- The parameter to the delay command is a Duration expressing a number of
-- seconds.

delay 0.0025;
------------------------------------------------------------------------------

Program: hopdelta

------------------------------------------------------------------------------
-- To Be Done
------------------------------------------------------------------------------