| ------------------------------------------------------------------------------ | 
 | --                                                                          -- | 
 | --                         GNAT RUN-TIME COMPONENTS                         -- | 
 | --                                                                          -- | 
 | --                         G N A T . C A L E N D A R                        -- | 
 | --                                                                          -- | 
 | --                                 B o d y                                  -- | 
 | --                                                                          -- | 
 | --                     Copyright (C) 1999-2005, AdaCore                     -- | 
 | --                                                                          -- | 
 | -- GNAT is free software;  you can  redistribute it  and/or modify it under -- | 
 | -- terms of the  GNU General Public License as published  by the Free Soft- -- | 
 | -- ware  Foundation;  either version 2,  or (at your option) any later ver- -- | 
 | -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- -- | 
 | -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY -- | 
 | -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License -- | 
 | -- for  more details.  You should have  received  a copy of the GNU General -- | 
 | -- Public License  distributed with GNAT;  see file COPYING.  If not, write -- | 
 | -- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, -- | 
 | -- Boston, MA 02110-1301, USA.                                              -- | 
 | --                                                                          -- | 
 | -- As a special exception,  if other files  instantiate  generics from this -- | 
 | -- unit, or you link  this unit with other files  to produce an executable, -- | 
 | -- this  unit  does not  by itself cause  the resulting  executable  to  be -- | 
 | -- covered  by the  GNU  General  Public  License.  This exception does not -- | 
 | -- however invalidate  any other reasons why  the executable file  might be -- | 
 | -- covered by the  GNU Public License.                                      -- | 
 | --                                                                          -- | 
 | -- GNAT was originally developed  by the GNAT team at  New York University. -- | 
 | -- Extensive contributions were provided by Ada Core Technologies Inc.      -- | 
 | --                                                                          -- | 
 | ------------------------------------------------------------------------------ | 
 |  | 
 | package body GNAT.Calendar is | 
 |  | 
 |    use Ada.Calendar; | 
 |    use Interfaces; | 
 |  | 
 |    ----------------- | 
 |    -- Day_In_Year -- | 
 |    ----------------- | 
 |  | 
 |    function Day_In_Year (Date : Time) return Day_In_Year_Number is | 
 |       Year  : Year_Number; | 
 |       Month : Month_Number; | 
 |       Day   : Day_Number; | 
 |       Dsecs : Day_Duration; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Dsecs); | 
 |  | 
 |       return Julian_Day (Year, Month, Day) - Julian_Day (Year, 1, 1) + 1; | 
 |    end Day_In_Year; | 
 |  | 
 |    ----------------- | 
 |    -- Day_Of_Week -- | 
 |    ----------------- | 
 |  | 
 |    function Day_Of_Week (Date : Time) return Day_Name is | 
 |       Year  : Year_Number; | 
 |       Month : Month_Number; | 
 |       Day   : Day_Number; | 
 |       Dsecs : Day_Duration; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Dsecs); | 
 |  | 
 |       return Day_Name'Val ((Julian_Day (Year, Month, Day)) mod 7); | 
 |    end Day_Of_Week; | 
 |  | 
 |    ---------- | 
 |    -- Hour -- | 
 |    ---------- | 
 |  | 
 |    function Hour (Date : Time) 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; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second); | 
 |       return Hour; | 
 |    end Hour; | 
 |  | 
 |    ---------------- | 
 |    -- Julian_Day -- | 
 |    ---------------- | 
 |  | 
 |    --  Julian_Day is used to by Day_Of_Week and Day_In_Year. Note | 
 |    --  that this implementation is not expensive. | 
 |  | 
 |    function Julian_Day | 
 |      (Year  : Year_Number; | 
 |       Month : Month_Number; | 
 |       Day   : Day_Number) return Integer | 
 |    is | 
 |       Internal_Year  : Integer; | 
 |       Internal_Month : Integer; | 
 |       Internal_Day   : Integer; | 
 |       Julian_Date    : Integer; | 
 |       C              : Integer; | 
 |       Ya             : Integer; | 
 |  | 
 |    begin | 
 |       Internal_Year  := Integer (Year); | 
 |       Internal_Month := Integer (Month); | 
 |       Internal_Day   := Integer (Day); | 
 |  | 
 |       if Internal_Month > 2 then | 
 |          Internal_Month := Internal_Month - 3; | 
 |       else | 
 |          Internal_Month := Internal_Month + 9; | 
 |          Internal_Year  := Internal_Year - 1; | 
 |       end if; | 
 |  | 
 |       C  := Internal_Year / 100; | 
 |       Ya := Internal_Year - (100 * C); | 
 |  | 
 |       Julian_Date := (146_097 * C) / 4 + | 
 |         (1_461 * Ya) / 4 + | 
 |         (153 * Internal_Month + 2) / 5 + | 
 |         Internal_Day + 1_721_119; | 
 |  | 
 |       return Julian_Date; | 
 |    end Julian_Day; | 
 |  | 
 |    ------------ | 
 |    -- Minute -- | 
 |    ------------ | 
 |  | 
 |    function Minute (Date : Time) 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; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second); | 
 |       return Minute; | 
 |    end Minute; | 
 |  | 
 |    ------------ | 
 |    -- Second -- | 
 |    ------------ | 
 |  | 
 |    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; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second); | 
 |       return Second; | 
 |    end Second; | 
 |  | 
 |    ----------- | 
 |    -- Split -- | 
 |    ----------- | 
 |  | 
 |    procedure Split | 
 |      (Date       : Time; | 
 |       Year       : out Year_Number; | 
 |       Month      : out Month_Number; | 
 |       Day        : out Day_Number; | 
 |       Hour       : out Hour_Number; | 
 |       Minute     : out Minute_Number; | 
 |       Second     : out Second_Number; | 
 |       Sub_Second : out Second_Duration) | 
 |    is | 
 |       Dsecs : Day_Duration; | 
 |       Secs  : Natural; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Dsecs); | 
 |  | 
 |       if Dsecs = 0.0 then | 
 |          Secs := 0; | 
 |       else | 
 |          Secs := Natural (Dsecs - 0.5); | 
 |       end if; | 
 |  | 
 |       Sub_Second := Second_Duration (Dsecs - Day_Duration (Secs)); | 
 |       Hour       := Hour_Number (Secs / 3600); | 
 |       Secs       := Secs mod 3600; | 
 |       Minute     := Minute_Number (Secs / 60); | 
 |       Second     := Second_Number (Secs mod 60); | 
 |    end Split; | 
 |  | 
 |    ---------------- | 
 |    -- Sub_Second -- | 
 |    ---------------- | 
 |  | 
 |    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; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second); | 
 |       return Sub_Second; | 
 |    end Sub_Second; | 
 |  | 
 |    ------------- | 
 |    -- Time_Of -- | 
 |    ------------- | 
 |  | 
 |    function Time_Of | 
 |      (Year       : Year_Number; | 
 |       Month      : Month_Number; | 
 |       Day        : Day_Number; | 
 |       Hour       : Hour_Number; | 
 |       Minute     : Minute_Number; | 
 |       Second     : Second_Number; | 
 |       Sub_Second : Second_Duration := 0.0) return Time | 
 |    is | 
 |       Dsecs : constant Day_Duration := | 
 |                 Day_Duration (Hour * 3600 + Minute * 60 + Second) + | 
 |                                                              Sub_Second; | 
 |    begin | 
 |       return Time_Of (Year, Month, Day, Dsecs); | 
 |    end Time_Of; | 
 |  | 
 |    ----------------- | 
 |    -- To_Duration -- | 
 |    ----------------- | 
 |  | 
 |    function To_Duration (T : access timeval) return Duration is | 
 |  | 
 |       procedure timeval_to_duration | 
 |         (T    : access timeval; | 
 |          sec  : access C.long; | 
 |          usec : access C.long); | 
 |       pragma Import (C, timeval_to_duration, "__gnat_timeval_to_duration"); | 
 |  | 
 |       Micro : constant := 10**6; | 
 |       sec   : aliased C.long; | 
 |       usec  : aliased C.long; | 
 |  | 
 |    begin | 
 |       timeval_to_duration (T, sec'Access, usec'Access); | 
 |       return Duration (sec) + Duration (usec) / Micro; | 
 |    end To_Duration; | 
 |  | 
 |    ---------------- | 
 |    -- To_Timeval -- | 
 |    ---------------- | 
 |  | 
 |    function To_Timeval  (D : Duration) return timeval is | 
 |  | 
 |       procedure duration_to_timeval (Sec, Usec : C.long; T : access timeval); | 
 |       pragma Import (C, duration_to_timeval, "__gnat_duration_to_timeval"); | 
 |  | 
 |       Micro  : constant := 10**6; | 
 |       Result : aliased timeval; | 
 |       sec    : C.long; | 
 |       usec   : C.long; | 
 |  | 
 |    begin | 
 |       if D = 0.0 then | 
 |          sec  := 0; | 
 |          usec := 0; | 
 |       else | 
 |          sec  := C.long (D - 0.5); | 
 |          usec := C.long ((D - Duration (sec)) * Micro - 0.5); | 
 |       end if; | 
 |  | 
 |       duration_to_timeval (sec, usec, Result'Access); | 
 |  | 
 |       return Result; | 
 |    end To_Timeval; | 
 |  | 
 |    ------------------ | 
 |    -- Week_In_Year -- | 
 |    ------------------ | 
 |  | 
 |    function Week_In_Year | 
 |      (Date : Ada.Calendar.Time) return Week_In_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; | 
 |       Offset     : Natural; | 
 |  | 
 |    begin | 
 |       Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second); | 
 |  | 
 |       --  Day offset number for the first week of the year | 
 |  | 
 |       Offset := Julian_Day (Year, 1, 1) mod 7; | 
 |  | 
 |       return 1 + ((Day_In_Year (Date) - 1) + Offset) / 7; | 
 |    end Week_In_Year; | 
 |  | 
 | end GNAT.Calendar; |