9.6 Delay Statements, Duration, and Time
is used to block further execution until a specified expiration time
is reached. The expiration time can be specified either as a particular
point in time (in a delay_until_statement
or in seconds from the current time (in a delay_relative_statement
The language-defined package Calendar provides definitions for a type
Time and associated operations, including a function Clock that returns
the current time.
delay_until_statement ::= delay until delay_expression
delay_relative_statement ::= delay delay_expression
Name Resolution Rules
be multiple time bases, each with a corresponding clock, and a corresponding
. The type of the delay_expression
in a delay_until_statement
shall be a time type — either the type Time defined in the language-defined
package Calendar (see below), the type Time in the package Real_Time
), or some other implementation-defined
Implementation defined: Any implementation-defined
[There is a predefined fixed point type named Duration,
declared in the visible part of package Standard;] a value of type Duration
is used to represent the length of an interval of time, expressed in
seconds. [The type Duration is not specific to a particular time base,
but can be used with any time base.]
A value of the type Time in package Calendar, or of some other time type,
represents a time as reported by a corresponding clock.
The following language-defined
library package exists:
with Nonblocking, Global => in out synchronized is
Time is private
1901 .. 2399;
1 .. 12;
1 .. 31;
0.0 .. 86_400.0;
A range of 500 years was chosen, as that only requires one extra bit
for the year as compared to Ada 95. This was done to minimize disruptions
with existing implementations. (One implementor reports that their time
values represent nanoseconds, and this year range requires 63.77 bits
Year (Date : Time) return
Month (Date : Time) return
Day (Date : Time) return
Seconds(Date : Time) return
Split (Date : in
Year : out
Month : out
Day : out
Seconds : out
Time_Of(Year : Year_Number;
Month : Month_Number;
Day : Day_Number;
Seconds : Day_Duration := 0.0)
function "+" (Left : Time; Right : Duration) return Time;
function "+" (Left : Duration; Right : Time) return Time;
function "-" (Left : Time; Right : Duration) return Time;
function "-" (Left : Time; Right : Time) return Duration;
function "<" (Left, Right : Time) return Boolean;
function "<="(Left, Right : Time) return Boolean;
function ">" (Left, Right : Time) return Boolean;
function ">="(Left, Right : Time) return Boolean;
... -- not specified by the language
For the execution of a delay_statement
is first evaluated.
For a delay_until_statement
the expiration time for the delay is the value of the delay_expression
in the time base associated with the type of the expression
For a delay_relative_statement
the expiration time is defined as the current time, in the time base
associated with relative delays, plus the value of the delay_expression
converted to the type Duration, and then rounded up to the next clock
The time base associated with relative delays
is as defined in D.9
” or is implementation defined.
Implementation defined: The time base
associated with relative delays.
Ramification: Rounding up to the next
clock tick means that the reading of the delay-relative clock when the
delay expires should be no less than the current reading of the delay-relative
clock plus the specified duration.
The task executing a delay_statement
is blocked until the expiration time is reached, at which point it becomes
ready again. If the expiration time has already passed, the task is not
Even though the task is not blocked, it might
be put back on the end of its ready queue. See D.2
The time base associated with the type Time of package
Calendar is implementation defined. The function Clock of package Calendar
returns a value representing the current time for this time base. [The
implementation-defined value of the named number System.Tick (see 13.7
is an approximation of the length of the real-time interval during which
the value of Calendar.Clock remains constant.]
Implementation defined: The time base
of the type Calendar.Time.
The functions Year, Month, Day, and Seconds return the corresponding
values for a given value of the type Time, as appropriate to an implementation-defined
time zone; the procedure Split returns all four corresponding values.
Conversely, the function Time_Of combines a year number, a month number,
a day number, and a duration, into a value of type Time. The operators
"+" and "–" for addition and subtraction of
times and durations, and the relational operators for times, have the
Implementation defined: The time zone
used for package Calendar operations.
The behavior of these values and subprograms if the time zone changes
is also implementation-defined. In particular, the changes associated
with summer time adjustments (like Daylight Savings Time in the United
States) should be treated as a change in the implementation-defined time
zone. The language does not specify whether the time zone information
is stored in values of type Time; therefore the results of binary operators
are unspecified when the operands are the two values with different effective
time zones. In particular, the results of "-" may differ from
the "real" result by the difference in the time zone adjustment.
Similarly, the result of UTC_Time_Offset (see 9.6.1) may or may not reflect
a time zone adjustment.
If Time_Of is called with a seconds value of 86_400.0,
the value returned is equal to the value of Time_Of for the next day
with a seconds value of 0.0. The value returned by the function Seconds
or through the Seconds parameter of the procedure Split is always less
The exception Time_Error is raised by the function Time_Of if the actual
parameters do not form a proper date. This exception is also raised by
the operators "+" and "–" if the result is
not representable in the type Time or Duration, as appropriate. This
exception is also raised by the functions Year, Month, Day, and Seconds
and the procedure Split if the year number of the given date is outside
of the range of the subtype Year_Number.
To be honest:
By "proper date" above we mean that the given year has a month
with the given day. For example, February 29th is a proper date only
for a leap year. We do not mean to include the Seconds in this notion;
in particular, we do not mean to require implementations to check for
the “missing hour” that occurs when Daylight Savings Time
starts in the spring.
We allow Year and Split to raise Time_Error because the arithmetic operators
are allowed (but not required) to produce times that are outside the
range of years from 1901 to 2399. This is similar to the way integer
operators may return values outside the base range of their type so long
as the value is mathematically correct. We allow the functions Month,
Day and Seconds to raise Time_Error so that they can be implemented in
terms of Split.
The implementation of the type Duration shall allow
representation of time intervals (both positive and negative) up to at
least 86400 seconds (one day); Duration'Small shall not be greater than
twenty milliseconds. The implementation of the type Time shall allow
representation of all dates with year numbers in the range of Year_Number[;
it may allow representation of other dates as well (both earlier and
An implementation may define additional time types.
This allows an implementation
to implement select_statement
timeouts using a representation that does not support the full range
of a time type. In particular 90 days of seconds can be represented in
23 bits, allowing a signed 24-bit representation for the seconds part
of a timeout. There is no similar restriction allowed for stand-alone
as these can be implemented internally using a loop if necessary to accommodate
a long delay.
Whenever possible in an implementation, the value
of Duration'Small should be no greater than 100 microseconds.
Implementation Note: This can be satisfied
using a 32-bit 2's complement representation with a small of 2.0**(–14)
— that is, 61 microseconds — and a range of ± 2.0**17
— that is, 131_072.0.
Implementation Advice: The value of Duration'Small
should be no greater than 100 microseconds.
The time base for delay_relative_statement
should be monotonic; it need not be the same time base as used for Calendar.Clock.
34 A delay_statement
may be executed by the environment task; consequently delay_statement
may be executed as part of the elaboration of a library_item
or the execution of the main subprogram. Such statements delay the environment
task (see 10.2
is an abort completion point and a potentially blocking operation, even
if the task is not actually blocked.
36 There is no necessary relationship between
System.Tick (the resolution of the clock of package Calendar) and Duration'Small
(the small of type Duration).
The inaccuracy of the delay_statement
has no relation to System.Tick. In particular, it is possible that the
clock used for the delay_statement
is less accurate than Calendar.Clock.
We considered making Tick a run-time-determined
quantity, to allow for easier configurability. However, this would not
be upward compatible, and the desired configurability can be achieved
using functionality defined in Annex D
Example of a relative
delay 3.0; -- delay 3.0 seconds
of a periodic task:
Next_Time : Time := Clock + Period;
-- Period is a global constant of type Duration
loop -- repeated every Period seconds
delay until Next_Time;
... -- perform some actions
Next_Time := Next_Time + Period;
Inconsistencies With Ada 83
For programs that raise
Time_Error on "+" or "–" in Ada 83,the exception
might be deferred until a call on Split or Year_Number, or might not
be raised at all (if the offending time is never Split after being calculated).
This should not affect typical programs, since they deal only with times
corresponding to the relatively recent past or near future.
Extensions to Ada 83
The type Time may represent dates with year numbers outside of Year_Number.
Therefore, the operations "+" and "–" need
only raise Time_Error if the result is not representable in Time (or
Duration); also, Split or Year will now raise Time_Error if the year
number is outside of Year_Number. This change is intended to simplify
the implementation of "+" and "–" (allowing
them to depend on overflow for detecting when to raise Time_Error) and
to allow local time zone information to be considered at the time of
Split rather than Clock (depending on the implementation approach). For
example, in a POSIX environment, it is natural for the type Time to be
based on GMT, and the results of procedure Split (and the functions Year,
Month, Day, and Seconds) to depend on local time zone information. In
other environments, it is more natural for the type Time to be based
on the local time zone, with the results of Year, Month, Day, and Seconds
being pure functions of their input.
Inconsistencies With Ada 95
The upper bound of Year_Number has been changed to
avoid a year 2100 problem. A program which expects years past 2099 to
raise Constraint_Error will fail in Ada 2005. We don't expect there to
be many programs which are depending on an exception to be raised. A
program that uses Year_Number'Last as a magic number may also fail if
values of Time are stored outside of the program. Note that the lower
bound of Year_Number wasn't changed, because it is not unusual to use
that value in a constant to represent an unknown time.
Wording Changes from Ada 95
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe