blob: 76252ad7dbf3369384b5b1518340d5a397d7bd03 [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- G N A T . C A L E N D A R --
-- --
-- B o d y --
-- --
-- $Revision: 1.8 $
-- --
-- Copyright (C) 1999-2001 Ada Core Technologies, Inc. --
-- --
-- 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, 59 Temple Place - Suite 330, Boston, --
-- MA 02111-1307, 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. --
-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
-- --
------------------------------------------------------------------------------
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;