9.6 Delay Statements, Duration, and Time
1
[
{expiration time 
[partial]} A 
delay_statement 
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. 
{timing: See delay_statement} 
]
 
Syntax
2
delay_statement ::= delay_until_statement | 
delay_relative_statement 
3
delay_until_statement ::= delay until delay_expression;
 
4
delay_relative_statement ::= delay delay_expression;
 
Name Resolution Rules
5
{expected type (delay_relative_statement 
expression) [partial]} The expected type 
for the 
delay_expression in a 
delay_relative_statement 
is the predefined type Duration. 
{expected 
type (delay_until_statement expression) [partial]} The 
delay_expression in a 
delay_until_statement 
is expected to be of any nonlimited type.
 
Legality Rules
6
{time type} 
{time base} 
{clock} 
There can be multiple time bases, each with a corresponding 
clock, and a corresponding 
time type. 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), or some other implementation-defined time type 
(see 
D.8). 
 
6.a
Implementation defined: Any implementation-defined 
time types.
Static Semantics
7
[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.]
8
A value of the type Time in package Calendar, or 
of some other implementation-defined time type, represents a time as 
reported by a corresponding clock.
9
The following language-defined 
library package exists: 
10
package Ada.Calendar 
is
  type Time 
is private;
 
11/2
{
AI95-00351-01} 
  
subtype Year_Number  
is Integer 
range 1901 .. 
2399 2099;
  
subtype Month_Number 
is Integer 
range 1 .. 12;
  
subtype Day_Number   
is Integer 
range 1 .. 31;
  
subtype Day_Duration 
is Duration 
range 0.0 .. 86_400.0;
 
11.a/2
Reason: {
AI95-00351-01} 
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 to represent.)  
12
  function Clock 
return Time;
 
13
  function Year   (Date : Time) 
return Year_Number;
  
function Month  (Date : Time) 
return Month_Number;
  
function Day    (Date : Time) 
return Day_Number;
  
function Seconds(Date : Time) 
return Day_Duration;
 
14
  procedure Split (Date  : 
in Time;
                   Year    : 
out Year_Number;
                   Month   : 
out Month_Number;
                   Day     : 
out Day_Number;
                   Seconds : 
out Day_Duration);
 
15
  function Time_Of(Year  : Year_Number;
                   Month   : Month_Number;
                   Day     : Day_Number;
                   Seconds : Day_Duration := 0.0)
   
return Time;
 
16
  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;
17
  function "<" (Left, Right : Time) return Boolean;
  function "<="(Left, Right : Time) return Boolean;
  function ">" (Left, Right : Time) return Boolean;
  function ">="(Left, Right : Time) return Boolean;
18
19
private
   ... -- not specified by the language
end Ada.Calendar;
Dynamic Semantics
20
{execution (delay_statement) 
[partial]} For the execution of a 
delay_statement, 
the 
delay_expression is first evaluated. 
{expiration time (for a delay_until_statement)} 
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. 
{expiration time (for a delay_relative_statement)} 
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 
tick. 
{implicit subtype conversion (delay 
expression) [partial]} The time base associated 
with relative delays is as defined in 
D.9, 
“
Delay Accuracy” or is implementation 
defined. 
 
20.a
Implementation defined: The time base 
associated with relative delays.
20.b
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. 
21
{blocked (on a delay_statement) 
[partial]} 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 
blocked. 
 
21.a
Discussion: For a delay_relative_statement, 
this case corresponds to when the value of the delay_expression 
is zero or negative.
21.b
Even though the task is not blocked, it might 
be put back on the end of its ready queue. See 
D.2, 
“
Priority Scheduling”. 
 
22
{cancellation (of 
a delay_statement)} If an attempt is made 
to 
cancel the 
delay_statement [(as 
part of an 
asynchronous_select or abort — 
see 
9.7.4 and 
9.8)], 
the 
_statement is cancelled if the expiration 
time has not yet passed, thereby completing the 
delay_statement. 
 
22.a
Reason: This is worded this way so that 
in an asynchronous_select where the triggering_statement 
is a delay_statement, an attempt to cancel 
the delay when the abortable_part completes 
is ignored if the expiration time has already passed, in which case the 
optional statements of the triggering_alternative 
are executed. 
23
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.] 
 
23.a
Implementation defined: The time base 
of the type Calendar.Time.
24/2
 {
AI95-00351-01} 
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 timezone; 
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 conventional meaning. 
 
24.a/2
Implementation defined: The time 
zone timezone used for package Calendar 
operations.
25
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 
than 86_400.0.
26/1
 {
8652/0030} 
{
AI95-00113-01} 
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 function
s 
Year
, Month, Day, and Seconds and or 
the procedure Split if the year number of the given date is outside of 
the range of the subtype Year_Number. 
 
26.a/1
To be honest: {
8652/0106} 
{
AI95-00160-01} 
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.  
26.b/2
Reason: {
8652/0030} 
{
AI95-00113-01} 
{
AI95-00351-01} 
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 2099. 
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. 
 
Implementation Requirements
27
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 
later).] 
Implementation Permissions
28
An implementation may define additional time types 
(see 
D.8).
 
29
An implementation may raise Time_Error if the value 
of a delay_expression in a delay_until_statement 
of a select_statement represents a time more 
than 90 days past the current time. The actual limit, if any, is implementation-defined. 
29.a
Implementation defined: Any limit on 
delay_until_statements of select_statements.
29.b
Implementation Note: 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 delay_until_statements, 
as these can be implemented internally using a loop if necessary to accommodate 
a long delay. 
Implementation Advice
30
Whenever possible in an implementation, the value 
of Duration'Small should be no greater than 100 microseconds. 
30.a
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. 
30.b/2
Implementation Advice: 
The value of Duration'Small should be 
no greater than 100 microseconds.
31
The time base for delay_relative_statements 
should be monotonic; it need not be the same time base as used for Calendar.Clock. 
31.a/2
Implementation Advice: 
The time base for delay_relative_statements 
should be monotonic.
32
32  A delay_relative_statement 
with a negative value of the delay_expression 
is equivalent to one with a zero value.
33
33  A 
delay_statement 
may be executed by the environment task; consequently 
delay_statements 
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).
 
34
34  
{potentially 
blocking operation (delay_statement) [partial]} {blocking, 
potentially (delay_statement) [partial]} A 
delay_statement is an abort completion point 
and a potentially blocking operation, even if the task is not actually 
blocked.
 
35
35  There is no necessary relationship between 
System.Tick (the resolution of the clock of package Calendar) and Duration'Small 
(the small of type Duration). 
35.a
Ramification: 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.
35.b
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, “
Real-Time 
Systems”. 
 
36
36  Additional requirements associated with 
delay_statements are given in 
D.9, 
“
Delay Accuracy”.
 
Examples
37
Example of a relative 
delay statement: 
38
delay 3.0;  -- delay 3.0 seconds
39
{periodic 
task (example)} {periodic 
task: See delay_until_statement} Example 
of a periodic task:  
40
declare
   use Ada.Calendar;
   Next_Time : Time := Clock + Period;
                      -- Period is a global constant of type Duration
begin
   loop               -- repeated every Period seconds
      delay until Next_Time;
      ... -- perform some actions
      Next_Time := Next_Time + Period;
   end loop;
end;
Inconsistencies With Ada 83
40.a
{
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
40.b
{
extensions to Ada 83} 
The 
syntax rule for 
delay_statement is modified 
to allow 
delay_until_statements.
 
40.c/2
{
AI95-00351-01} 
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 timezone 
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.
 
40.d/2
This paragraph 
was deleted.{
AI95-00351-01} 
We anticipate that implementations will provide 
child packages of Calendar to provide more explicit control over time 
zones and other environment-dependent time-related issues. These would 
be appropriate for standardization in a given environment (such as POSIX). 
 
Inconsistencies With Ada 95
40.e/2
{
AI95-00351-01} 
{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
40.f/2