Time: Ada.Calendar, Formatting, Arithmetic & Real_Time
Represent dates and times with Ada.Calendar (Time, Duration, Clock, Split, Time_Of), format and parse with Ada.Calendar.Formatting (UTC by default), compute day differences with Ada.Calendar.Arithmetic, handle time zones, and measure intervals with the monotonic Ada.Real_Time clock and Time_Span.
Ada separates wall-clock time from real time. Ada.Calendar gives calendar dates and the time of day and can jump when the system clock is adjusted; Ada.Real_Time is a monotonic clock designed for measuring intervals and scheduling periodic tasks. Duration, a fixed-point type counting seconds, connects them.
Ada.Calendar
Ada.Calendar.Clock returns the current Time. Time_Of (Year, Month, Day, Seconds) builds a Time and Split decomposes one — both in the local time zone. Time ± Duration and Time - Time → Duration are predefined; comparisons work as expected. Duration is a fixed-point type in seconds (GNAT: Duration'Small = 1 ns); Day_Duration is 0.0 .. 86_400.0.
• Clock, Time_Of, Split, Year/Month/Day/Seconds (local time zone). • Time ± Duration; Time - Time = Duration. • Duration: fixed-point seconds.
Formatting, Arithmetic and Time Zones
Ada.Calendar.Formatting offers Image ("YYYY-MM-DD HH:MM:SS") and Value for parsing, Time_Of with Hour/Minute/Second, component functions (Year, Hour, ...), and Day_Of_Week. Its operations take a Time_Zone parameter that defaults to 0 (UTC). Mixing Ada.Calendar.Time_Of (local) with Formatting.Image (UTC) is a classic bug: while building this lesson, noon created with Calendar.Time_Of on a UTC+5:30 machine printed as 06:30:00. Ada.Calendar.Time_Zones.UTC_Time_Offset gives the local offset. Ada.Calendar.Arithmetic.Difference splits an interval into whole days plus seconds (and leap seconds), and "+" (Time, Day_Count) adds days.
• Formatting.Image / Value / Time_Of / Day_Of_Week — UTC by default. • Don't mix local Calendar.Time_Of with UTC Formatting.Image. • Arithmetic.Difference (days + seconds); Arithmetic."+" adds days.
Ada.Real_Time
Ada.Real_Time.Clock is monotonic: it never goes backwards, so it is the right clock for measuring elapsed time and for periodic tasks ('delay until Next'). Intervals are Time_Span values created with Nanoseconds, Microseconds, Milliseconds, Seconds and Minutes, and converted with To_Duration / To_Time_Span. 'delay D' suspends for at least D seconds (relative), 'delay until T' until an absolute time — the concurrency lessons build on this.
• Real_Time.Clock: monotonic, for intervals and scheduling. • Time_Span: Milliseconds (N), Seconds (N) ...; To_Duration. • delay D (relative), delay until T (absolute).
Code Examples
Dates are fixed (UTC), so the output is reproducible; only the final line depends on the real clock, and it prints a Boolean that is always True. From 1983-02-17 12:00 to 2012-12-10 09:30 is 10 888 days plus 21.5 hours (77 400 s). Output: Launch : 1983-02-17 12:00:00 Revised : 2012-12-10 09:30:00 Fields : 1983 2 17, hour 12 Weekday of launch: THURSDAY Difference: 10888 days and 77400.000000000 s Launch + 30 days: 1983-03-19 12:00:00 Launch + 90 minutes: 1983-02-17 13:30:00 Revised > Launch? TRUE Duration'Small = 0.000000001, one day = 86400.000000000 1500 ms as Duration = 1.500000000 Span * 2 = 3.000000000 Elapsed after delay 0.2 >= 200 ms? TRUE
Start := Ada.Calendar.Clock; ... Elapsed := Ada.Calendar.Clock - Start;
Start := Ada.Real_Time.Clock; ... Elapsed := To_Duration (Ada.Real_Time.Clock - Start);
The calendar clock can jump (NTP, daylight saving); measure with the monotonic clock.
T := Ada.Calendar.Time_Of (2024, 1, 1, 0.0); Put_Line (Formatting.Image (T)); -- shows a different hour
T := Ada.Calendar.Formatting.Time_Of (2024, 1, 1, 0, 0, 0);
Calendar.Time_Of is local time; Formatting uses UTC unless told otherwise.
loop Work; delay 1.0; -- drifts end loop;
Next := Clock; loop Work; Next := Next + Seconds (1); delay until Next; end loop;
delay until avoids cumulative drift in periodic loops.
Which clock should you use to measure elapsed time? A. Ada.Calendar.Clock B. Ada.Real_Time.Clock C. Either D. Duration'Clock B. It is monotonic.
What time zone does Ada.Calendar.Formatting.Image use by default? A. Local B. UTC (Time_Zone => 0) C. The compiler's D. None
What type is Time - Time in Ada.Calendar? A. Time B. Duration C. Integer D. Time_Span
Which statement prevents drift in a periodic loop? A. delay 1.0; B. delay until Next; C. sleep(1) D. pragma Periodic Trace the time example.
Real output: Launch : 1983-02-17 12:00:00 Revised : 2012-12-10 09:30:00 Fields : 1983 2 17, hour 12 Weekday of launch: THURSDAY Difference: 10888 days and 77400.000000000 s Launch + 30 days: 1983-03-19 12:00:00 Launch + 90 minutes: 1983-02-17 13:30:00 Revised > Launch? TRUE Duration'Small = 0.000000001, one day = 86400.000000000 1500 ms as Duration = 1.500000000 Span * 2 = 3.000000000 Elapsed after delay 0.2 >= 200 ms? TRUE
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;
with Ada.Calendar.Formatting; use Ada.Calendar.Formatting;
with Ada.Calendar.Arithmetic;
with Ada.Real_Time;
procedure L50_Time is
-- Fixed dates keep this example reproducible (Clock would give the current time).
-- Formatting.Time_Of / Image / Hour use UTC by default (Time_Zone => 0);
-- Ada.Calendar.Time_Of and Split use the machine's local time zone.
Launch : constant Time := Formatting.Time_Of (1983, 2, 17, Hour => 12, Minute => 0, Second => 0);
Revised : constant Time := Formatting.Time_Of (2012, 12, 10, Hour => 9, Minute => 30, Second => 0);
Days : Ada.Calendar.Arithmetic.Day_Count;
Secs : Duration;
Leaps : Ada.Calendar.Arithmetic.Leap_Seconds_Count;
begin
Put_Line ("Launch : " & Image (Launch));
Put_Line ("Revised : " & Image (Revised));
Put_Line ("Fields :" & Year_Number'Image (Year (Launch, Time_Zone => 0))
& Month_Number'Image (Month (Launch, Time_Zone => 0))
& Day_Number'Image (Day (Launch, Time_Zone => 0))
& ", hour" & Hour_Number'Image (Hour (Launch)));
Put_Line ("Weekday of
…