[Ada] Fix support for > 24 hours image in Ada.Calendar.Formatting
diff mbox series

Message ID 20191213095501.GA14043@adacore.com
State New
Headers show
Series
  • [Ada] Fix support for > 24 hours image in Ada.Calendar.Formatting
Related show

Commit Message

Pierre-Marie de Rodat Dec. 13, 2019, 9:55 a.m. UTC
The Ada.Calendar.Formatting.Image function is supposed to support at
least durations up to (excluding) 100 hours. Fixes the implementation so
that it does and clarify in the spec the behavior when the duration
exceeds 100 hours (raise Time_Error).

Tested on x86_64-pc-linux-gnu, committed on trunk

2019-12-13  Arnaud Charlet  <charlet@adacore.com>

gcc/ada/

	* libgnat/a-calfor.ads, libgnat/a-calfor.adb (Split_Duration):
	New procedure.
	(Split, Image): Use Split_Duration. Update Image spec.

Patch
diff mbox series

--- gcc/ada/libgnat/a-calfor.adb
+++ gcc/ada/libgnat/a-calfor.adb
@@ -52,6 +52,15 @@  package body Ada.Calendar.Formatting is
    --  such as 1983-*1-j3 u5:n7:k9 which should be 1983-01-03 05:07:09. Raise
    --  Constraint_Error if there is a mismatch.
 
+   procedure Split_Duration
+     (Seconds    : Duration;
+      Hour       : out Natural;
+      Minute     : out Minute_Number;
+      Second     : out Second_Number;
+      Sub_Second : out Second_Duration);
+   --  Version of Split that allows durations < 100 hours.
+   --  Will raise Time_Error if Seconds >= 100 hours.
+
    ----------------
    -- Check_Char --
    ----------------
@@ -140,7 +149,7 @@  package body Ada.Calendar.Formatting is
       Include_Time_Fraction : Boolean := False) return String
    is
       To_Char    : constant array (0 .. 9) of Character := "0123456789";
-      Hour       : Hour_Number;
+      Hour       : Natural;
       Minute     : Minute_Number;
       Second     : Second_Number;
       Sub_Second : Duration;
@@ -155,7 +164,7 @@  package body Ada.Calendar.Formatting is
       Result : String := "-00:00:00.00";
 
    begin
-      Split (abs (Elapsed_Time), Hour, Minute, Second, Sub_Second);
+      Split_Duration (abs Elapsed_Time, Hour, Minute, Second, Sub_Second);
 
       --  Hour processing, positions 2 and 3
 
@@ -361,6 +370,34 @@  package body Ada.Calendar.Formatting is
              Sub_Second;
    end Seconds_Of;
 
+   --------------------
+   -- Split_Duration --
+   --------------------
+
+   procedure Split_Duration
+     (Seconds    : Duration;
+      Hour       : out Natural;
+      Minute     : out Minute_Number;
+      Second     : out Second_Number;
+      Sub_Second : out Second_Duration)
+   is
+      Secs : Natural;
+   begin
+      --  Check that Seconds is below 100 hours
+
+      if Seconds >= 3600.0 * 100.0 then
+         raise Time_Error;
+      end if;
+
+      Secs := (if Seconds = 0.0 then 0 else Natural (Seconds - 0.5));
+
+      Sub_Second := Second_Duration (Seconds - Duration (Secs));
+      Hour       := Natural (Secs / 3_600);
+      Secs       := Secs mod 3_600;
+      Minute     := Minute_Number (Secs / 60);
+      Second     := Second_Number (Secs mod 60);
+   end Split_Duration;
+
    -----------
    -- Split --
    -----------
@@ -372,8 +409,7 @@  package body Ada.Calendar.Formatting is
       Second     : out Second_Number;
       Sub_Second : out Second_Duration)
    is
-      Secs : Natural;
-
+      Unchecked_Hour : Natural;
    begin
       --  Validity checks
 
@@ -381,23 +417,13 @@  package body Ada.Calendar.Formatting is
          raise Constraint_Error;
       end if;
 
-      Secs := (if Seconds = 0.0 then 0 else Natural (Seconds - 0.5));
-
-      Sub_Second := Second_Duration (Seconds - Day_Duration (Secs));
-      Hour       := Hour_Number (Secs / 3_600);
-      Secs       := Secs mod 3_600;
-      Minute     := Minute_Number (Secs / 60);
-      Second     := Second_Number (Secs mod 60);
-
-      --  Validity checks
+      Split_Duration (Seconds, Unchecked_Hour, Minute, Second, Sub_Second);
 
-      if not Hour'Valid
-        or else not Minute'Valid
-        or else not Second'Valid
-        or else not Sub_Second'Valid
-      then
+      if Unchecked_Hour > Hour_Number'Last then
          raise Time_Error;
       end if;
+
+      Hour := Unchecked_Hour;
    end Split;
 
    -----------

--- gcc/ada/libgnat/a-calfor.ads
+++ gcc/ada/libgnat/a-calfor.ads
@@ -204,7 +204,7 @@  package Ada.Calendar.Formatting is
    --  to the string as a point followed by a 2-digit value. If Elapsed_Time <
    --  0.0, the result is Image (abs Elapsed_Time, Include_Time_Fraction)
    --  prefixed with a minus sign. If abs Elapsed_Time represents 100 hours or
-   --  more, the result is implementation-defined.
+   --  more, Time_Error is raised.
 
    function Value (Elapsed_Time : String) return Duration;
    --  Returns a Duration value for the image given as Elapsed_Time.