6  Date and Time Handling

The topic for this chapter is Date and Time. Deceptively simple, handling dates and times in the context of leap years, across time zones and daylight savings and other such phenomena make this extremely complicated. In a projectlet or 2, we will explore some problems and thus exercise the predefined libraries of the language.

6.1 Date of Birth

6.1.1 Learning Objectives

  • Convert Date and Time between internal and Printable formats

  • Arithmetic with Date, Time and Duration

6.1.2 Projectlet Specification

Given a date of birth argument, compute and printout the age, details of the 50th, 60th and other significant birthdays. Leap years should be handled appropriately.

6.1.3 Sample Runs

~/bin/bday
Bday.P1
Date of Birth          1986-04-01 06:00:01
Day of the Week        TUESDAY
Age (days)              14191
   (years)              38
Birthday at Age  50    2036-04-01 04:00:00 TUESDAY
Birthday at Age  60    2046-04-01 05:00:00 SUNDAY
Birthday at Age  70    2056-04-01 05:00:00 SATURDAY
Birthday at Age  80    2066-04-01 04:00:00 THURSDAY
Birthday at Age  90    2076-04-01 04:00:00 WEDNESDAY
Birthday at Age  100   2086-04-01 04:00:00 MONDAY

6.1.4 Implementation

Predefined Libraries

~/bin/codemd ../Prj/datetime/bday/src/bday.adb -x Environment -l
0006 | with Ada.Calendar;            use Ada.Calendar;
0007 | with Ada.Calendar.Formatting;
0008 | with Ada.Calendar.Arithmetic; use Ada.Calendar.Arithmetic;

Date of Birth Computations

~/bin/codemd ../Prj/datetime/bday/src/bday.adb -x Calc -l
0022 |    procedure Show_Birthday (dob : Ada.Calendar.Time; age : Positive) is
0023 |       reqbday : Ada.Calendar.Time;
0024 |    begin
0025 |       reqbday := Time_Of (Year (dob) + age, Month (dob), Day (dob));
0026 | 
0027 |       Put ("Birthday at Age ");
0028 |       Put (Positive'Image (age));
0029 |       Set_Col (24);
0030 |       Put (Formatting.Image (reqbday));
0031 |       Set_Col (44);
0032 |       Put (Formatting.Day_Of_Week (reqbday)'Image);
0033 |       New_Line;
0034 |    end Show_Birthday;

6.2 Multiple Dates

6.2.1 Learning Objectives

  • Date Comparison

  • Passage of Time

6.2.2 Projectlet Specifications

  • Given 2 dates, determine which is older. Essentially date comparisons.

  • Assuming these are dates of birth, determine the year when the older age will be double the younger. Triple the younger.

6.2.3 Sample runs

~/bin/dates 1996-10-07
dates
dates.P1
Person A
    Birthday              1986-04-01 06:00:01
    Day of the Week       TUESDAY
    Age today              14191 days
                        38 years
Person B
    Birthday              1996-10-07 06:00:01
    Day of the Week       MONDAY
    Age today              10349 days
                        28 years
Person A is older
Age difference is  3842 days
               or  10 years
Double the Age
On 2006-10-07 04:00:00
Person B
 will be                10 years old
Person A
 will be                20 years old

6.2.4 Implementation

6.2.4.1 Code fragments

Given 2 dates of birth determine who is older. Then project when the older person will be double the age of the younger person.

~/bin/codemd ../Prj/datetime/bday/src/dates.adb -x Compare -l
0066 |    procedure AgeDiff (operson : String; od : Time; yperson : String; yd : Time)
0067 |    is
0068 |       agediff   : Day_Count;
0069 |       yearsdiff : Integer;
0070 |       dblage    : Time := od;
0071 |    begin
0072 |       Put ("Person ");
0073 |       Put (operson);
0074 |       Put_Line (" is older");
0075 |       agediff   := yd - od;
0076 |       yearsdiff := Integer (agediff / days_in_year);
0077 |       Put ("Age difference is ");
0078 |       Put (agediff'Image);
0079 |       Put_Line (" days");
0080 |       Put ("               or ");
0081 |       Put (yearsdiff'Image);
0082 |       Put_Line (" years");
0083 |       Put_Line ("Double the Age");
0084 |       dblage := Age (yd, yearsdiff);
0085 | 
0086 |       Put ("On ");
0087 |       Put_Line (Formatting.Image (dblage));
0088 |       Show_Age (yperson, yd, dblage);
0089 |       Show_Age (operson, od, dblage);
0090 |    end AgeDiff;

Add a number of years to a date of birth.

~/bin/codemd ../Prj/datetime/bday/src/dates.adb -x AddYears -l
0056 |    function Age (dob : Time; years : Integer) return Time is
0057 |       agedTime : Time := dob;
0058 |    begin
0059 |       agedTime :=
0060 |         Time_Of (Year_Number (Year (dob) + years), Month (dob), Day (dob));
0061 |       return agedTime;
0062 |    end Age;

6.3 Timespan

6.3.1 Learning Objectives

  • Sleep or delay execution for a specified length of time

  • Set an alarm to wake up at a specific time

  • Creating a widget to help identify performance sensitive sections of code

6.3.2 Sample Runs

Sleep for a specified length of time

~/bin/realtime p1
realtime
realtime.P1
Sleeping for  3.000000000 seconds
Woke up
Slept from 2025-02-06 10:36:11 to 2025-02-06 10:36:14

Sleep till a specified time or set an alarm

~/bin/realtime p2
realtime
realtime.P2
Sleeping till 2025-02-06 10:36:23 seconds
Woke up
Slept from 2025-02-06 10:36:14 to 2025-02-06 10:36:23

Perform computations and measure the time it takes for different count of cycles.

~/bin/codemd ../Prj/datetime/bday/src/realtime.adb -x Time -l
0079 |       Put ("Starting computations ");
0080 |       Put (iterations'Image);
0081 |       Put (" cycles");
0082 |       t1 := Clock;
0083 | 
0084 |       for i in 1 .. iterations loop
0085 |          result := Cosh (Float (i) * vf) + Sinh (Float (i) * vf);
0086 |       end loop;
0087 |       t2 := Clock;
0088 |       Put ("Completed ");
0089 |       Put (Duration'Image (t2 - t1));
0090 |       Put_Line (" seconds");
~/bin/realtime p3 10000
~/bin/realtime p3 20000
realtime
realtime.P3
Starting computations  10240000 cyclesCompleted  0.058872000 seconds
realtime
realtime.P3
Starting computations  20480000 cyclesCompleted  0.108147000 seconds

6.4 Sample Implementation

Repository: TechAdaBook
Directory: Prj/datetime