1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- A D A . C A L E N D A R --
11 -- Copyright (C) 1992-2000 Free Software Foundation, Inc. --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
31 -- GNAT was originally developed by the GNAT team at New York University. --
32 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
34 ------------------------------------------------------------------------------
36 -- This is the Alpha/VMS version.
38 with System.Aux_DEC; use System.Aux_DEC;
40 package body Ada.Calendar is
42 ------------------------------
43 -- Use of Pragma Unsuppress --
44 ------------------------------
46 -- This implementation of Calendar takes advantage of the permission in
47 -- Ada 95 of using arithmetic overflow checks to check for out of bounds
48 -- time values. This means that we must catch the constraint error that
49 -- results from arithmetic overflow, so we use pragma Unsuppress to make
50 -- sure that overflow is enabled, using software overflow checking if
51 -- necessary. That way, compiling Calendar with options to suppress this
52 -- checking will not affect its correctness.
54 ------------------------
55 -- Local Declarations --
56 ------------------------
58 Ada_Year_Min : constant := 1901;
59 Ada_Year_Max : constant := 2099;
61 -- Some basic constants used throughout
63 Days_In_Month : constant array (Month_Number) of Day_Number :=
64 (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
66 function To_Relative_Time (D : Duration) return Time;
68 function To_Relative_Time (D : Duration) return Time is
70 return Time (Long_Integer'Integer_Value (D) / 100);
77 function "+" (Left : Time; Right : Duration) return Time is
78 pragma Unsuppress (Overflow_Check);
80 return (Left + To_Relative_Time (Right));
83 when Constraint_Error =>
87 function "+" (Left : Duration; Right : Time) return Time is
88 pragma Unsuppress (Overflow_Check);
90 return (To_Relative_Time (Left) + Right);
93 when Constraint_Error =>
101 function "-" (Left : Time; Right : Duration) return Time is
102 pragma Unsuppress (Overflow_Check);
104 return Left - To_Relative_Time (Right);
107 when Constraint_Error =>
111 function "-" (Left : Time; Right : Time) return Duration is
112 pragma Unsuppress (Overflow_Check);
114 return Duration'Fixed_Value
115 ((Long_Integer (Left) - Long_Integer (Right)) * 100);
118 when Constraint_Error =>
126 function "<" (Left, Right : Time) return Boolean is
128 return Long_Integer (Left) < Long_Integer (Right);
135 function "<=" (Left, Right : Time) return Boolean is
137 return Long_Integer (Left) <= Long_Integer (Right);
144 function ">" (Left, Right : Time) return Boolean is
146 return Long_Integer (Left) > Long_Integer (Right);
153 function ">=" (Left, Right : Time) return Boolean is
155 return Long_Integer (Left) >= Long_Integer (Right);
162 -- The Ada.Calendar.Clock function gets the time.
163 -- Note that on other targets a soft-link is used to get a different clock
164 -- depending whether tasking is used or not. On VMS this isn't needed
165 -- since all clock calls end up using SYS$GETTIM, so call the
166 -- OS_Primitives version for efficiency.
168 function Clock return Time is
170 return Time (OSP.OS_Clock);
177 function Day (Date : Time) return Day_Number is
184 Split (Date, DY, DM, DD, DS);
192 function Month (Date : Time) return Month_Number is
199 Split (Date, DY, DM, DD, DS);
207 function Seconds (Date : Time) return Day_Duration is
214 Split (Date, DY, DM, DD, DS);
224 Year : out Year_Number;
225 Month : out Month_Number;
226 Day : out Day_Number;
227 Seconds : out Day_Duration)
230 Status : out Unsigned_Longword;
231 Timbuf : out Unsigned_Word_Array;
234 pragma Interface (External, Numtim);
236 pragma Import_Valued_Procedure (Numtim, "SYS$NUMTIM",
237 (Unsigned_Longword, Unsigned_Word_Array, Time),
238 (Value, Reference, Reference));
240 Status : Unsigned_Longword;
241 Timbuf : Unsigned_Word_Array (1 .. 7);
244 Numtim (Status, Timbuf, Date);
247 or else Timbuf (1) not in Ada_Year_Min .. Ada_Year_Max
253 := Day_Duration (Timbuf (6) + 60 * (Timbuf (5) + 60 * Timbuf (4)))
254 + Day_Duration (Timbuf (7)) / 100.0;
255 Day := Integer (Timbuf (3));
256 Month := Integer (Timbuf (2));
257 Year := Integer (Timbuf (1));
266 Month : Month_Number;
268 Seconds : Day_Duration := 0.0)
272 procedure Cvt_Vectim (
273 Status : out Unsigned_Longword;
274 Input_Time : in Unsigned_Word_Array;
275 Resultant_Time : out Time);
277 pragma Interface (External, Cvt_Vectim);
279 pragma Import_Valued_Procedure (Cvt_Vectim, "LIB$CVT_VECTIM",
280 (Unsigned_Longword, Unsigned_Word_Array, Time),
281 (Value, Reference, Reference));
283 Status : Unsigned_Longword;
284 Timbuf : Unsigned_Word_Array (1 .. 7);
287 Day_Hack : Boolean := False;
289 -- The following checks are redundant with respect to the constraint
290 -- error checks that should normally be made on parameters, but we
291 -- decide to raise Constraint_Error in any case if bad values come
292 -- in (as a result of checks being off in the caller, or for other
293 -- erroneous or bounded error cases).
296 or else not Month 'Valid
297 or else not Day 'Valid
298 or else not Seconds'Valid
300 raise Constraint_Error;
303 -- Truncate seconds value by subtracting 0.5 and rounding,
304 -- but be careful with 0.0 since that will give -1.0 unless
305 -- it is treated specially.
307 if Seconds > 0.0 then
308 Int_Secs := Integer (Seconds - 0.5);
310 Int_Secs := Integer (Seconds);
313 -- Cvt_Vectim barfs on the largest Day_Duration, so trick it by
314 -- setting it to zero and then adding the difference after conversion.
316 if Int_Secs = 86_400 then
321 Timbuf (7) := Unsigned_Word
322 (100.0 * Duration (Seconds - Day_Duration (Int_Secs)));
323 -- Cvt_Vectim accurate only to within .01 seconds
326 -- Similar hack needed for 86399 and 100/100ths, since that gets
327 -- treated as 86400 (largest Day_Duration). This can happen because
328 -- Duration has more accuracy than VMS system time conversion calls
331 if Int_Secs = 86_399 and then Timbuf (7) = 100 then
337 Timbuf (6) := Unsigned_Word (Int_Secs mod 60);
338 Timbuf (5) := Unsigned_Word ((Int_Secs / 60) mod 60);
339 Timbuf (4) := Unsigned_Word (Int_Secs / 3600);
340 Timbuf (3) := Unsigned_Word (Day);
341 Timbuf (2) := Unsigned_Word (Month);
342 Timbuf (1) := Unsigned_Word (Year);
344 Cvt_Vectim (Status, Timbuf, Date);
346 if Status mod 2 /= 1 then
351 Date := Date + 10_000_000 * 86_400;
362 function Year (Date : Time) return Year_Number is
369 Split (Date, DY, DM, DD, DS);