function "+" (Left : Time; Right : Duration) return Time is
pragma Unsuppress (Overflow_Check);
-
- Res_M : Time;
-
begin
- -- Trivial case
-
- if Right = Duration (0.0) then
- return Left;
- end if;
-
- Res_M := Left + To_Relative_Time (Right);
-
- Check_Within_Time_Bounds (Res_M);
-
- return Res_M;
-
+ return Left + To_Relative_Time (Right);
exception
when Constraint_Error =>
raise Time_Error;
function "-" (Left : Time; Right : Duration) return Time is
pragma Unsuppress (Overflow_Check);
-
- Res_M : Time;
-
begin
- -- Trivial case
-
- if Right = Duration (0.0) then
- return Left;
- end if;
-
- Res_M := Left - To_Relative_Time (Right);
-
- Check_Within_Time_Bounds (Res_M);
-
- return Res_M;
-
+ return Left - To_Relative_Time (Right);
exception
when Constraint_Error =>
raise Time_Error;
begin
Res_M := Left - Right;
- -- The result does not fit in a duration value
+ -- Due to the extended range of Ada time, "-" is capable of producing
+ -- results which may exceed the range of Duration. In order to prevent
+ -- the generation of bogus values by the Unchecked_Conversion, we apply
+ -- the following check.
if Res_M < Dur_Low
or else Res_M >= Dur_High
then
raise Time_Error;
+
+ -- Normal case, result fits
+
+ else
+ return To_Duration (Res_M);
end if;
- return To_Duration (Res_M);
exception
when Constraint_Error =>
raise Time_Error;
function Add (Date : Time; Days : Long_Integer) return Time is
pragma Unsuppress (Overflow_Check);
-
- Res_M : Time;
-
begin
- -- Trivial case
-
- if Days = 0 then
- return Date;
- end if;
-
- Res_M := Date + Time (Days) * Milis_In_Day;
-
- Check_Within_Time_Bounds (Res_M);
-
- return Res_M;
-
+ return Date + Time (Days) * Milis_In_Day;
exception
when Constraint_Error =>
raise Time_Error;
function Subtract (Date : Time; Days : Long_Integer) return Time is
pragma Unsuppress (Overflow_Check);
-
- Res_M : Time;
-
begin
- -- Trivial case
-
- if Days = 0 then
- return Date;
- end if;
-
- Res_M := Date - Time (Days) * Milis_In_Day;
-
- Check_Within_Time_Bounds (Res_M);
-
- return Res_M;
+ return Date - Time (Days) * Milis_In_Day;
exception
when Constraint_Error =>
raise Time_Error;
function "+" (Left : Time; Right : Duration) return Time is
pragma Unsuppress (Overflow_Check);
-
Left_N : constant Time_Rep := Time_Rep (Left);
- Res_N : Time_Rep;
-
begin
- -- Trivial case
-
- if Right = Duration (0.0) then
- return Left;
- end if;
-
- Res_N := Left_N + Duration_To_Time_Rep (Right);
-
- Check_Within_Time_Bounds (Res_N);
-
- return Time (Res_N);
-
+ return Time (Left_N + Duration_To_Time_Rep (Right));
exception
when Constraint_Error =>
raise Time_Error;
function "-" (Left : Time; Right : Duration) return Time is
pragma Unsuppress (Overflow_Check);
-
Left_N : constant Time_Rep := Time_Rep (Left);
- Res_N : Time_Rep;
-
begin
- -- Trivial case
-
- if Right = Duration (0.0) then
- return Left;
- end if;
-
- Res_N := Left_N - Duration_To_Time_Rep (Right);
-
- Check_Within_Time_Bounds (Res_N);
-
- return Time (Res_N);
-
+ return Time (Left_N - Duration_To_Time_Rep (Right));
exception
when Constraint_Error =>
raise Time_Error;
begin
Res_N := Time_Rep (Left) - Time_Rep (Right);
- -- The result does not fit in a duration value
+ -- Due to the extended range of Ada time, "-" is capable of producing
+ -- results which may exceed the range of Duration. In order to prevent
+ -- the generation of bogus values by the Unchecked_Conversion, we apply
+ -- the following check.
if Res_N < Dur_Low
or else Res_N > Dur_High
function Add (Date : Time; Days : Long_Integer) return Time is
pragma Unsuppress (Overflow_Check);
-
Date_N : constant Time_Rep := Time_Rep (Date);
- Res_N : Time_Rep;
-
begin
- -- Trivial case
-
- if Days = 0 then
- return Date;
- end if;
-
- Res_N := Date_N + Time_Rep (Days) * Nanos_In_Day;
-
- Check_Within_Time_Bounds (Res_N);
-
- return Time (Res_N);
-
+ return Time (Date_N + Time_Rep (Days) * Nanos_In_Day);
exception
when Constraint_Error =>
raise Time_Error;
is
Res_Dur : Time_Dur;
Earlier : Time_Rep;
- Earlier_Sub : Time_Rep;
Elapsed_Leaps : Natural;
Later : Time_Rep;
- Later_Sub : Time_Rep;
Negate : Boolean := False;
Next_Leap_N : Time_Rep;
- Sub_Seconds : Duration;
+ Sub_Secs : Duration;
+ Sub_Secs_Diff : Time_Rep;
begin
-- Both input time values are assumed to be in UTC
Elapsed_Leaps := 0;
end if;
- -- Sub seconds
+ -- Sub seconds processing. We add the resulting difference to one
+ -- of the input dates in order to account for any potential rounding
+ -- of the difference in the next step.
- Earlier_Sub := Earlier mod Nano;
- Later_Sub := Later mod Nano;
-
- if Later_Sub < Earlier_Sub then
- Later_Sub := Later_Sub + Time_Rep (1) * Nano;
- Later := Later - Time_Rep (1) * Nano;
- end if;
+ Sub_Secs_Diff := Later mod Nano - Earlier mod Nano;
+ Earlier := Earlier + Sub_Secs_Diff;
+ Sub_Secs := Duration (Sub_Secs_Diff) / Nano_F;
- Sub_Seconds := Duration (Later_Sub - Earlier_Sub) / Nano_F;
+ -- Difference processing. This operation should be able to calculate
+ -- the difference between opposite values which are close to the end
+ -- and start of Ada time. To accomodate the large range, we convert
+ -- to seconds. This action may potentially round the two values and
+ -- either add or drop a second. We compensate for this issue in the
+ -- previous step.
- Res_Dur := Time_Dur (Later / Nano - Earlier / Nano) -
- Time_Dur (Elapsed_Leaps);
+ Res_Dur :=
+ Time_Dur (Later / Nano - Earlier / Nano) - Time_Dur (Elapsed_Leaps);
- Days := Long_Integer (Res_Dur / Secs_In_Day);
- Seconds := Duration (Res_Dur mod Secs_In_Day) + Sub_Seconds;
+ Days := Long_Integer (Res_Dur / Secs_In_Day);
+ Seconds := Duration (Res_Dur mod Secs_In_Day) + Sub_Secs;
Leap_Seconds := Integer (Elapsed_Leaps);
if Negate then
function Subtract (Date : Time; Days : Long_Integer) return Time is
pragma Unsuppress (Overflow_Check);
-
Date_N : constant Time_Rep := Time_Rep (Date);
- Res_N : Time_Rep;
-
begin
- -- Trivial case
-
- if Days = 0 then
- return Date;
- end if;
-
- Res_N := Date_N - Time_Rep (Days) * Nanos_In_Day;
-
- Check_Within_Time_Bounds (Res_N);
-
- return Time (Res_N);
-
+ return Time (Date_N - Time_Rep (Days) * Nanos_In_Day);
exception
when Constraint_Error =>
raise Time_Error;