OSDN Git Service

2007-04-20 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-calfor.adb
index 23d2ab5..b8a8c01 100644 (file)
 
 with Ada.Calendar;            use Ada.Calendar;
 with Ada.Calendar.Time_Zones; use Ada.Calendar.Time_Zones;
-with Unchecked_Conversion;
 
 package body Ada.Calendar.Formatting is
 
-   use Leap_Sec_Ops;
+   --------------------------
+   -- Implementation Notes --
+   --------------------------
 
-   Days_In_4_Years          : constant := 365 * 3 + 366;
-   Seconds_In_Day           : constant := 86_400;
-   Seconds_In_4_Years       : constant := Days_In_4_Years * Seconds_In_Day;
-   Seconds_In_Non_Leap_Year : constant := 365 * Seconds_In_Day;
-
-   --  Exact time bounds for the range of Ada time: January 1, 1901 -
-   --  December 31, 2099. These bounds are based on the Unix Time of Epoc,
-   --  January 1, 1970. Start of Time is -69 years from TOE while End of
-   --  time is +130 years and one second from TOE.
-
-   Start_Of_Time : constant Time :=
-                     Time (-(17 * Seconds_In_4_Years +
-                                  Seconds_In_Non_Leap_Year));
-
-   End_Of_Time   : constant Time :=
-                     Time (32 * Seconds_In_4_Years +
-                            2 * Seconds_In_Non_Leap_Year) +
-                                All_Leap_Seconds;
-
-   Days_In_Month : constant array (Month_Number) of Day_Number :=
-     (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
+   --  All operations in this package are target and time representation
+   --  independent, thus only one source file is needed for multiple targets.
 
    procedure Check_Char (S : String; C : Character; Index : Integer);
    --  Subsidiary to the two versions of Value. Determine whether the
@@ -102,19 +84,18 @@ package body Ada.Calendar.Formatting is
      (Date      : Time;
       Time_Zone : Time_Zones.Time_Offset := 0) return Day_Number
    is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
+      Y  : Year_Number;
+      Mo : Month_Number;
+      D  : Day_Number;
+      H  : Hour_Number;
+      Mi : Minute_Number;
+      Se : Second_Number;
+      Ss : Second_Duration;
+      Le : Boolean;
 
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
-      return Day;
+      Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
+      return D;
    end Day;
 
    -----------------
@@ -122,51 +103,8 @@ package body Ada.Calendar.Formatting is
    -----------------
 
    function Day_Of_Week (Date : Time) return Day_Name is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
-
-      D           : Duration;
-      Day_Count   : Long_Long_Integer;
-      Midday_Date : Time;
-      Secs_Count  : Long_Long_Integer;
-
    begin
-      --  Split the Date to obtain the year, month and day, then build a time
-      --  value for the middle of the same day, so that we don't have to worry
-      --  about leap seconds in the subsequent arithmetic.
-
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second);
-
-      Midday_Date := Time_Of (Year, Month, Day, 12, 0, 0);
-      D           := Midday_Date - Start_Of_Time;
-
-      --  D is a positive Duration value counting seconds since 1901. Convert
-      --  it into an integer for ease of arithmetic.
-
-      declare
-         type D_Int is range 0 .. 2 ** (Duration'Size - 1) - 1;
-         for D_Int'Size use Duration'Size;
-
-         function To_D_Int is new Unchecked_Conversion (Duration, D_Int);
-
-         D_As_Int  : constant D_Int := To_D_Int (D);
-         Small_Div : constant D_Int := D_Int (1.0 / Duration'Small);
-
-      begin
-         Secs_Count := Long_Long_Integer (D_As_Int / Small_Div);
-      end;
-
-      Day_Count := Secs_Count / Seconds_In_Day;
-      Day_Count := Day_Count + 1;  --  Jan 1, 1901 was a Tuesday;
-
-      return Day_Name'Val (Day_Count mod 7);
+      return Day_Name'Val (Formatting_Operations.Day_Of_Week (Date));
    end Day_Of_Week;
 
    ----------
@@ -177,19 +115,18 @@ package body Ada.Calendar.Formatting is
      (Date      : Time;
       Time_Zone : Time_Zones.Time_Offset := 0) return Hour_Number
    is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
+      Y  : Year_Number;
+      Mo : Month_Number;
+      D  : Day_Number;
+      H  : Hour_Number;
+      Mi : Minute_Number;
+      Se : Second_Number;
+      Ss : Second_Duration;
+      Le : Boolean;
 
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
-      return Hour;
+      Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
+      return H;
    end Hour;
 
    -----------
@@ -377,19 +314,17 @@ package body Ada.Calendar.Formatting is
      (Date      : Time;
       Time_Zone : Time_Zones.Time_Offset := 0) return Minute_Number
    is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
-
+      Y  : Year_Number;
+      Mo : Month_Number;
+      D  : Day_Number;
+      H  : Hour_Number;
+      Mi : Minute_Number;
+      Se : Second_Number;
+      Ss : Second_Duration;
+      Le : Boolean;
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
-      return Minute;
+      Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
+      return Mi;
    end Minute;
 
    -----------
@@ -400,19 +335,17 @@ package body Ada.Calendar.Formatting is
      (Date      : Time;
       Time_Zone : Time_Zones.Time_Offset := 0) return Month_Number
    is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
-
+      Y  : Year_Number;
+      Mo : Month_Number;
+      D  : Day_Number;
+      H  : Hour_Number;
+      Mi : Minute_Number;
+      Se : Second_Number;
+      Ss : Second_Duration;
+      Le : Boolean;
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
-      return Month;
+      Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
+      return Mo;
    end Month;
 
    ------------
@@ -420,19 +353,17 @@ package body Ada.Calendar.Formatting is
    ------------
 
    function Second (Date : Time) return Second_Number is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
-
+      Y  : Year_Number;
+      Mo : Month_Number;
+      D  : Day_Number;
+      H  : Hour_Number;
+      Mi : Minute_Number;
+      Se : Second_Number;
+      Ss : Second_Duration;
+      Le : Boolean;
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second);
-      return Second;
+      Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le);
+      return Se;
    end Second;
 
    ----------------
@@ -456,9 +387,9 @@ package body Ada.Calendar.Formatting is
          raise Constraint_Error;
       end if;
 
-      return Day_Duration (Hour   * 3600) +
-             Day_Duration (Minute *   60) +
-             Day_Duration (Second)        +
+      return Day_Duration (Hour   * 3_600) +
+             Day_Duration (Minute *    60) +
+             Day_Duration (Second)         +
                            Sub_Second;
    end Seconds_Of;
 
@@ -489,10 +420,20 @@ package body Ada.Calendar.Formatting is
       end if;
 
       Sub_Second := Second_Duration (Seconds - Day_Duration (Secs));
-      Hour       := Hour_Number (Secs / 3600);
-      Secs       := Secs mod 3600;
+      Hour       := Hour_Number (Secs / 3_600);
+      Secs       := Secs mod 3_600;
       Minute     := Minute_Number (Secs / 60);
       Second     := Second_Number (Secs mod 60);
+
+      --  Validity checks
+
+      if not Hour'Valid
+        or else not Minute'Valid
+        or else not Second'Valid
+        or else not Sub_Second'Valid
+      then
+         raise Time_Error;
+      end if;
    end Split;
 
    -----------
@@ -508,16 +449,36 @@ package body Ada.Calendar.Formatting is
       Leap_Second : out Boolean;
       Time_Zone   : Time_Zones.Time_Offset := 0)
    is
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
+      H  : Integer;
+      M  : Integer;
+      Se : Integer;
+      Su : Duration;
+      Tz : constant Long_Integer := Long_Integer (Time_Zone);
 
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
+      Formatting_Operations.Split
+        (Date      => Date,
+         Year      => Year,
+         Month     => Month,
+         Day       => Day,
+         Day_Secs  => Seconds,
+         Hour      => H,
+         Minute    => M,
+         Second    => Se,
+         Sub_Sec   => Su,
+         Leap_Sec  => Leap_Second,
+         Time_Zone => Tz,
+         Is_Ada_05 => True);
+
+      --  Validity checks
 
-      Seconds := Seconds_Of (Hour, Minute, Second, Sub_Second);
+      if not Year'Valid
+        or else not Month'Valid
+        or else not Day'Valid
+        or else not Seconds'Valid
+      then
+         raise Time_Error;
+      end if;
    end Split;
 
    -----------
@@ -535,11 +496,37 @@ package body Ada.Calendar.Formatting is
       Sub_Second : out Second_Duration;
       Time_Zone  : Time_Zones.Time_Offset := 0)
    is
-      Leap_Second : Boolean;
+      Dd : Day_Duration;
+      Le : Boolean;
+      Tz : constant Long_Integer := Long_Integer (Time_Zone);
 
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
+      Formatting_Operations.Split
+        (Date      => Date,
+         Year      => Year,
+         Month     => Month,
+         Day       => Day,
+         Day_Secs  => Dd,
+         Hour      => Hour,
+         Minute    => Minute,
+         Second    => Second,
+         Sub_Sec   => Sub_Second,
+         Leap_Sec  => Le,
+         Time_Zone => Tz,
+         Is_Ada_05 => True);
+
+      --  Validity checks
+
+      if not Year'Valid
+        or else not Month'Valid
+        or else not Day'Valid
+        or else not Hour'Valid
+        or else not Minute'Valid
+        or else not Second'Valid
+        or else not Sub_Second'Valid
+      then
+         raise Time_Error;
+      end if;
    end Split;
 
    -----------
@@ -558,139 +545,36 @@ package body Ada.Calendar.Formatting is
       Leap_Second : out Boolean;
       Time_Zone   : Time_Zones.Time_Offset := 0)
    is
-      Ada_Year_Min    : constant Year_Number := Year_Number'First;
-      Day_In_Year     : Integer;
-      Day_Second      : Integer;
-      Elapsed_Leaps   : Duration;
-      Hour_Second     : Integer;
-      In_Leap_Year    : Boolean;
-      Modified_Date   : Time;
-      Next_Leap       : Time;
-      Remaining_Years : Integer;
-      Seconds_Count   : Long_Long_Integer;
+      Dd : Day_Duration;
+      Tz : constant Long_Integer := Long_Integer (Time_Zone);
 
    begin
-      --  Our measurement of time is the number of seconds that have elapsed
-      --  since the Unix TOE. To calculate a UTC date from this we do a
-      --  sequence of divides and mods to get the components of a date based
-      --  on 86,400 seconds in each day. Since, UTC time depends upon the
-      --  occasional insertion of leap seconds, the number of leap seconds
-      --  that have been added prior to the input time are then subtracted
-      --  from the previous calculation. In fact, it is easier to do the
-      --  subtraction first, so a more accurate discription of what is
-      --  actually done, is that the number of added leap seconds is looked
-      --  up using the input Time value, than that number of seconds is
-      --  subtracted before the sequence of divides and mods.
-      --
-      --  If the input date turns out to be a leap second, we don't add it to
-      --  date (we want to return 23:59:59) but we set the Leap_Second output
-      --  to true.
-
-      --  Is there a need to account for a difference from Unix time prior
-      --  to the first leap second ???
-
-      --  Step 1: Determine the number of leap seconds since the start
-      --  of Ada time and the input date as well as the next leap second
-      --  occurence and process accordingly.
-
-      Cumulative_Leap_Secs (Start_Of_Time, Date, Elapsed_Leaps, Next_Leap);
-
-      Leap_Second   := Date >= Next_Leap;
-      Modified_Date := Date - Elapsed_Leaps;
-
-      if Leap_Second then
-         Modified_Date := Modified_Date - Duration (1.0);
-      end if;
+      Formatting_Operations.Split
+       (Date      => Date,
+        Year      => Year,
+        Month     => Month,
+        Day       => Day,
+        Day_Secs  => Dd,
+        Hour      => Hour,
+        Minute    => Minute,
+        Second    => Second,
+        Sub_Sec   => Sub_Second,
+        Leap_Sec  => Leap_Second,
+        Time_Zone => Tz,
+        Is_Ada_05 => True);
 
-      --  Step 2: Process the time zone
-
-      Modified_Date := Modified_Date + Duration (Time_Zone * 60);
-
-      --  Step 3: Sanity check on the calculated date. Since the leap
-      --  seconds and the time zone have been eliminated, the result needs
-      --  to be within the range of Ada time.
+      --  Validity checks
 
-      if Modified_Date < Start_Of_Time
-        or else Modified_Date >= (End_Of_Time - All_Leap_Seconds)
+      if not Year'Valid
+        or else not Month'Valid
+        or else not Day'Valid
+        or else not Hour'Valid
+        or else not Minute'Valid
+        or else not Second'Valid
+        or else not Sub_Second'Valid
       then
          raise Time_Error;
       end if;
-
-      Modified_Date := Modified_Date - Start_Of_Time;
-
-      declare
-         type D_Int is range 0 .. 2 ** (Duration'Size - 1) - 1;
-         for D_Int'Size use Duration'Size;
-
-         function To_D_Int is new Unchecked_Conversion (Duration, D_Int);
-         function To_Duration is new Unchecked_Conversion (D_Int, Duration);
-         function To_Duration is new Unchecked_Conversion (Time, Duration);
-
-         D_As_Int  : constant D_Int := To_D_Int (To_Duration (Modified_Date));
-         Small_Div : constant D_Int := D_Int (1.0 / Duration'Small);
-
-      begin
-         Seconds_Count := Long_Long_Integer (D_As_Int / Small_Div);
-         Sub_Second    := Second_Duration
-                            (To_Duration (D_As_Int rem Small_Div));
-      end;
-
-      --  Step 4: Calculate the number of years since the start of Ada time.
-      --  First consider sequences of four years, then the remaining years.
-
-      Year := Ada_Year_Min + 4 * Integer (Seconds_Count / Seconds_In_4_Years);
-      Seconds_Count   := Seconds_Count mod Seconds_In_4_Years;
-      Remaining_Years := Integer (Seconds_Count / Seconds_In_Non_Leap_Year);
-
-      if Remaining_Years > 3 then
-         Remaining_Years := 3;
-      end if;
-
-      Year := Year + Remaining_Years;
-
-      --  Remove the seconds elapsed in those remaining years
-
-      Seconds_Count := Seconds_Count - Long_Long_Integer
-                         (Remaining_Years * Seconds_In_Non_Leap_Year);
-      In_Leap_Year := (Year mod 4) = 0;
-
-      --  Step 5: Month and day processing. Determine the day to which the
-      --  remaining seconds map to.
-
-      Day_In_Year := Integer (Seconds_Count / Seconds_In_Day) + 1;
-
-      Month := 1;
-
-      if Day_In_Year > 31 then
-         Month       := 2;
-         Day_In_Year := Day_In_Year - 31;
-
-         if Day_In_Year > 28
-           and then ((not In_Leap_Year)
-                        or else Day_In_Year > 29)
-         then
-            Month       := 3;
-            Day_In_Year := Day_In_Year - 28;
-
-            if In_Leap_Year then
-               Day_In_Year := Day_In_Year - 1;
-            end if;
-
-            while Day_In_Year > Days_In_Month (Month) loop
-               Day_In_Year := Day_In_Year - Days_In_Month (Month);
-               Month := Month + 1;
-            end loop;
-         end if;
-      end if;
-
-      --  Step 6: Hour, minute and second processing
-
-      Day         := Day_In_Year;
-      Day_Second  := Integer (Seconds_Count mod Seconds_In_Day);
-      Hour        := Day_Second / 3600;
-      Hour_Second := Day_Second mod 3600;
-      Minute      := Hour_Second / 60;
-      Second      := Hour_Second mod 60;
    end Split;
 
    ----------------
@@ -698,20 +582,17 @@ package body Ada.Calendar.Formatting is
    ----------------
 
    function Sub_Second (Date : Time) return Second_Duration is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
-
+      Y  : Year_Number;
+      Mo : Month_Number;
+      D  : Day_Number;
+      H  : Hour_Number;
+      Mi : Minute_Number;
+      Se : Second_Number;
+      Ss : Second_Duration;
+      Le : Boolean;
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second);
-
-      return Sub_Second;
+      Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le);
+      return Ss;
    end Sub_Second;
 
    -------------
@@ -726,79 +607,63 @@ package body Ada.Calendar.Formatting is
       Leap_Second : Boolean := False;
       Time_Zone   : Time_Zones.Time_Offset := 0) return Time
    is
-      Hour       : Hour_Number;
-      Minute     : Minute_Number;
-      Sec_Num    : Second_Number;
-      Sub_Sec    : Second_Duration;
-      Whole_Part : Integer;
+      Adj_Year  : Year_Number  := Year;
+      Adj_Month : Month_Number := Month;
+      Adj_Day   : Day_Number   := Day;
+
+      H  : constant Integer := 1;
+      M  : constant Integer := 1;
+      Se : constant Integer := 1;
+      Ss : constant Duration := 0.1;
+      Tz : constant Long_Integer := Long_Integer (Time_Zone);
 
    begin
-      if not Seconds'Valid then
+      --  Validity checks
+
+      if not Year'Valid
+        or else not Month'Valid
+        or else not Day'Valid
+        or else not Seconds'Valid
+        or else not Time_Zone'Valid
+      then
          raise Constraint_Error;
       end if;
 
-      --  The fact that Seconds can go to 86,400 creates all this extra work.
-      --  Perhaps a Time_Of just like the next one but allowing the Second_
-      --  Number input to reach 60 should become an internal version that this
-      --  and the next version call.... but for now we do the ugly bumping up
-      --  of Day, Month and Year;
+      --  A Seconds value of 86_400 denotes a new day. This case requires an
+      --  adjustment to the input values.
 
       if Seconds = 86_400.0 then
-         declare
-            Adj_Year  : Year_Number  := Year;
-            Adj_Month : Month_Number := Month;
-            Adj_Day   : Day_Number   := Day;
-
-         begin
-            Hour    := 0;
-            Minute  := 0;
-            Sec_Num := 0;
-            Sub_Sec := 0.0;
-
-            if Day < Days_In_Month (Month)
-              or else (Month = 2
-                         and then Year mod 4 = 0)
-            then
-               Adj_Day := Day + 1;
+         if Day < Days_In_Month (Month)
+           or else (Is_Leap (Year)
+                      and then Month = 2)
+         then
+            Adj_Day := Day + 1;
+         else
+            Adj_Day := 1;
+
+            if Month < 12 then
+               Adj_Month := Month + 1;
             else
-               Adj_Day := 1;
-
-               if Month < 12 then
-                  Adj_Month := Month + 1;
-               else
-                  Adj_Month := 1;
-                  Adj_Year  := Year + 1;
-               end if;
+               Adj_Month := 1;
+               Adj_Year  := Year + 1;
             end if;
-
-            return Time_Of (Adj_Year, Adj_Month, Adj_Day, Hour, Minute,
-                            Sec_Num, Sub_Sec, Leap_Second, Time_Zone);
-         end;
+         end if;
       end if;
 
-      declare
-         type D_Int is range 0 .. 2 ** (Duration'Size - 1) - 1;
-         for D_Int'Size use Duration'Size;
-
-         function To_D_Int is new Unchecked_Conversion (Duration, D_Int);
-         function To_Duration is new Unchecked_Conversion (D_Int, Duration);
-
-         D_As_Int  : constant D_Int := To_D_Int (Seconds);
-         Small_Div : constant D_Int := D_Int (1.0 / Duration'Small);
-
-      begin
-         Whole_Part := Integer (D_As_Int / Small_Div);
-         Sub_Sec    := Second_Duration
-                         (To_Duration (D_As_Int rem Small_Div));
-      end;
-
-      Hour       := Hour_Number (Whole_Part / 3600);
-      Whole_Part := Whole_Part mod 3600;
-      Minute     := Minute_Number (Whole_Part / 60);
-      Sec_Num    := Second_Number (Whole_Part mod 60);
-
-      return Time_Of (Year, Month, Day,
-                      Hour, Minute, Sec_Num, Sub_Sec, Leap_Second, Time_Zone);
+      return
+        Formatting_Operations.Time_Of
+          (Year         => Adj_Year,
+           Month        => Adj_Month,
+           Day          => Adj_Day,
+           Day_Secs     => Seconds,
+           Hour         => H,
+           Minute       => M,
+           Second       => Se,
+           Sub_Sec      => Ss,
+           Leap_Sec     => Leap_Second,
+           Use_Day_Secs => True,
+           Is_Ada_05    => True,
+           Time_Zone    => Tz);
    end Time_Of;
 
    -------------
@@ -816,23 +681,11 @@ package body Ada.Calendar.Formatting is
       Leap_Second : Boolean := False;
       Time_Zone   : Time_Zones.Time_Offset := 0) return Time
    is
-      Cumulative_Days_Before_Month :
-        constant array (Month_Number) of Natural :=
-          (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
-
-      Ada_Year_Min         : constant Year_Number := Year_Number'First;
-      Count                : Integer;
-      Elapsed_Leap_Seconds : Duration;
-      Fractional_Second    : Duration;
-      Next_Leap            : Time;
-      Result               : Time;
+      Dd : constant Day_Duration := Day_Duration'First;
+      Tz : constant Long_Integer := Long_Integer (Time_Zone);
 
    begin
-      --  The following checks are redundant with respect to the constraint
-      --  error checks that should normally be made on parameters, but we
-      --  decide to raise Constraint_Error in any case if bad values come in
-      --  (as a result of checks being off in the caller, or for other
-      --  erroneous or bounded error cases).
+      --  Validity checks
 
       if not Year'Valid
         or else not Month'Valid
@@ -846,99 +699,20 @@ package body Ada.Calendar.Formatting is
          raise Constraint_Error;
       end if;
 
-      --  Start the accumulation from the beginning of Ada time
-
-      Result := Start_Of_Time;
-
-      --  Step 1: Determine the number of leap and non-leap years since 1901
-      --  and the input date.
-
-      --  Count the number of four year segments
-
-      Count  := (Year - Ada_Year_Min) / 4;
-      Result := Result + Duration (Count * Seconds_In_4_Years);
-
-      --  Count the number of remaining non-leap years
-
-      Count  := (Year - Ada_Year_Min) mod 4;
-      Result := Result + Duration (Count * Seconds_In_Non_Leap_Year);
-
-      --  Step 2: Determine the number of days elapsed singe the start of the
-      --  input year and add them to the result.
-
-      --  Do not include the current day since it is not over yet
-
-      Count := Cumulative_Days_Before_Month (Month) + Day - 1;
-
-      --  The input year is a leap year and we have passed February
-
-      if (Year mod 4) = 0
-        and then Month > 2
-      then
-         Count := Count + 1;
-      end if;
-
-      Result := Result + Duration (Count * Seconds_In_Day);
-
-      --  Step 3: Hour, minute and second processing
-
-      Result := Result + Duration (Hour   * 3600) +
-                         Duration (Minute *   60) +
-                         Duration (Second);
-
-      --  The sub second may designate a whole second
-
-      if Sub_Second = 1.0 then
-         Result            := Result + Duration (1.0);
-         Fractional_Second := 0.0;
-      else
-         Fractional_Second := Sub_Second;
-      end if;
-
-      --  Step 4: Time zone processing
-
-      Result := Result - Duration (Time_Zone * 60);
-
-      --  Step 5: The caller wants a leap second
-
-      if Leap_Second then
-         Result := Result + Duration (1.0);
-      end if;
-
-      --  Step 6: Calculate the number of leap seconds occured since the
-      --  start of Ada time and the current point in time. The following
-      --  is an approximation which does not yet count leap seconds. It
-      --  can be pushed beyond 1 leap second, but not more.
-
-      Cumulative_Leap_Secs
-        (Start_Of_Time, Result, Elapsed_Leap_Seconds, Next_Leap);
-
-      Result := Result + Elapsed_Leap_Seconds;
-
-      --  Step 7: Validity check of a leap second occurence. It requires an
-      --  additional comparison to Next_Leap to ensure that we landed right
-      --  on a valid occurence and that Elapsed_Leap_Seconds did not shoot
-      --  past it.
-
-      if Leap_Second
-        and then
-           not (Result >= Next_Leap
-                  and then Result - Duration (1.0) < Next_Leap)
-      then
-         raise Time_Error;
-      end if;
-
-      --  Step 8: Final sanity check on the calculated duration value
-
-      if Result < Start_Of_Time
-        or else Result >= End_Of_Time
-      then
-         raise Time_Error;
-      end if;
-
-      --  Step 9: Lastly, add the sub second part
-
-      return Result + Fractional_Second;
+      return
+        Formatting_Operations.Time_Of
+          (Year         => Year,
+           Month        => Month,
+           Day          => Day,
+           Day_Secs     => Dd,
+           Hour         => Hour,
+           Minute       => Minute,
+           Second       => Second,
+           Sub_Sec      => Sub_Second,
+           Leap_Sec     => Leap_Second,
+           Use_Day_Secs => False,
+           Is_Ada_05    => True,
+           Time_Zone    => Tz);
    end Time_Of;
 
    -----------
@@ -1117,19 +891,18 @@ package body Ada.Calendar.Formatting is
      (Date      : Time;
       Time_Zone : Time_Zones.Time_Offset := 0) return Year_Number
    is
-      Year        : Year_Number;
-      Month       : Month_Number;
-      Day         : Day_Number;
-      Hour        : Hour_Number;
-      Minute      : Minute_Number;
-      Second      : Second_Number;
-      Sub_Second  : Second_Duration;
-      Leap_Second : Boolean;
+      Y  : Year_Number;
+      Mo : Month_Number;
+      D  : Day_Number;
+      H  : Hour_Number;
+      Mi : Minute_Number;
+      Se : Second_Number;
+      Ss : Second_Duration;
+      Le : Boolean;
 
    begin
-      Split (Date, Year, Month, Day,
-             Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
-      return Year;
+      Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
+      return Y;
    end Year;
 
 end Ada.Calendar.Formatting;