1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- G N A T . C A L E N D A R . T I M E _ I O --
9 -- Copyright (C) 1999-2006, AdaCore --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 2, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
21 -- for more details. You should have received a copy of the GNU General --
22 -- Public License distributed with GNAT; see file COPYING. If not, write --
23 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
24 -- Boston, MA 02110-1301, USA. --
26 -- As a special exception, if other files instantiate generics from this --
27 -- unit, or you link this unit with other files to produce an executable, --
28 -- this unit does not by itself cause the resulting executable to be --
29 -- covered by the GNU General Public License. This exception does not --
30 -- however invalidate any other reasons why the executable file might be --
31 -- covered by the GNU Public License. --
33 -- GNAT was originally developed by the GNAT team at New York University. --
34 -- Extensive contributions were provided by Ada Core Technologies Inc. --
36 ------------------------------------------------------------------------------
38 with Ada
.Calendar
; use Ada
.Calendar
;
39 with Ada
.Characters
.Handling
;
40 with Ada
.Strings
.Unbounded
; use Ada
.Strings
.Unbounded
;
43 package body GNAT
.Calendar
.Time_IO
is
59 type Padding_Mode
is (None
, Zero
, Space
);
61 type Sec_Number
is mod 2 ** 64;
62 -- Type used to compute the number of seconds since 01/01/1970. A 32 bit
63 -- number will cover only a period of 136 years. This means that for date
64 -- past 2106 the computation is not possible. A 64 bits number should be
65 -- enough for a very large period of time.
67 -----------------------
68 -- Local Subprograms --
69 -----------------------
71 function Am_Pm
(H
: Natural) return String;
72 -- Return AM or PM depending on the hour H
74 function Hour_12
(H
: Natural) return Positive;
75 -- Convert a 1-24h format to a 0-12 hour format
77 function Image
(Str
: String; Length
: Natural := 0) return String;
78 -- Return Str capitalized and cut to length number of characters. If
79 -- length is set to 0 it does not cut it.
83 Padding
: Padding_Mode
:= Zero
;
84 Length
: Natural := 0) return String;
85 -- Return image of N. This number is eventually padded with zeros or spaces
86 -- depending of the length required. If length is 0 then no padding occurs.
90 Padding
: Padding_Mode
:= Zero
;
91 Length
: Natural := 0) return String;
92 -- As above with N provided in Integer format
98 function Am_Pm
(H
: Natural) return String is
100 if H
= 0 or else H
> 12 then
111 function Hour_12
(H
: Natural) return Positive is
128 Length
: Natural := 0) return String
130 use Ada
.Characters
.Handling
;
131 Local
: constant String :=
132 To_Upper
(Str
(1)) & To_Lower
(Str
(2 .. Str
'Last));
137 return Local
(1 .. Length
);
147 Padding
: Padding_Mode
:= Zero
;
148 Length
: Natural := 0) return String
151 return Image
(Sec_Number
(N
), Padding
, Length
);
156 Padding
: Padding_Mode
:= Zero
;
157 Length
: Natural := 0) return String
159 function Pad_Char
return String;
165 function Pad_Char
return String is
168 when None
=> return "";
169 when Zero
=> return "00";
170 when Space
=> return " ";
174 NI
: constant String := Sec_Number
'Image (N
);
175 NIP
: constant String := Pad_Char
& NI
(2 .. NI
'Last);
177 -- Start of processing for Image
180 if Length
= 0 or else Padding
= None
then
181 return NI
(2 .. NI
'Last);
183 return NIP
(NIP
'Last - Length
+ 1 .. NIP
'Last);
192 (Date
: Ada
.Calendar
.Time
;
193 Picture
: Picture_String
) return String
195 Padding
: Padding_Mode
:= Zero
;
196 -- Padding is set for one directive
198 Result
: Unbounded_String
;
201 Month
: Month_Number
;
204 Minute
: Minute_Number
;
205 Second
: Second_Number
;
206 Sub_Second
: Second_Duration
;
208 P
: Positive := Picture
'First;
211 Split
(Date
, Year
, Month
, Day
, Hour
, Minute
, Second
, Sub_Second
);
214 -- A directive has the following format "%[-_]."
216 if Picture
(P
) = '%' then
220 if P
= Picture
'Last then
224 -- Check for GNU extension to change the padding
226 if Picture
(P
+ 1) = '-' then
229 elsif Picture
(P
+ 1) = '_' then
234 if P
= Picture
'Last then
238 case Picture
(P
+ 1) is
243 Result
:= Result
& '%';
248 Result
:= Result
& ASCII
.LF
;
253 Result
:= Result
& ASCII
.HT
;
258 Result
:= Result
& Image
(Hour
, Padding
, 2);
263 Result
:= Result
& Image
(Hour_12
(Hour
), Padding
, 2);
268 Result
:= Result
& Image
(Hour
, Space
, 2);
273 Result
:= Result
& Image
(Hour_12
(Hour
), Space
, 2);
278 Result
:= Result
& Image
(Minute
, Padding
, 2);
283 Result
:= Result
& Am_Pm
(Hour
);
285 -- Time, 12-hour (hh:mm:ss [AP]M)
289 Image
(Hour_12
(Hour
), Padding
, Length
=> 2) & ':' &
290 Image
(Minute
, Padding
, Length
=> 2) & ':' &
291 Image
(Second
, Padding
, Length
=> 2) & ' ' &
294 -- Seconds since 1970-01-01 00:00:00 UTC
295 -- (a nonstandard extension)
299 Sec
: constant Sec_Number
:=
300 Sec_Number
(Julian_Day
(Year
, Month
, Day
) -
301 Julian_Day
(1970, 1, 1)) * 86_400
302 + Sec_Number
(Hour
) * 3_600
303 + Sec_Number
(Minute
) * 60
304 + Sec_Number
(Second
);
307 Result
:= Result
& Image
(Sec
, None
);
313 Result
:= Result
& Image
(Second
, Padding
, Length
=> 2);
315 -- Milliseconds (3 digits)
316 -- Microseconds (6 digits)
317 -- Nanoseconds (9 digits)
319 when 'i' |
'e' |
'o' =>
321 Sub_Sec
: constant Long_Integer :=
322 Long_Integer (Sub_Second
* 1_000_000_000
);
324 Img1
: constant String := Sub_Sec
'Img;
325 Img2
: constant String :=
326 "00000000" & Img1
(Img1
'First + 1 .. Img1
'Last);
327 Nanos
: constant String :=
328 Img2
(Img2
'Last - 8 .. Img2
'Last);
331 case Picture
(P
+ 1) is
334 Nanos
(Nanos
'First .. Nanos
'First + 2);
338 Nanos
(Nanos
'First .. Nanos
'First + 5);
341 Result
:= Result
& Nanos
;
348 -- Time, 24-hour (hh:mm:ss)
352 Image
(Hour
, Padding
, Length
=> 2) & ':' &
353 Image
(Minute
, Padding
, Length
=> 2) & ':' &
354 Image
(Second
, Padding
, Length
=> 2);
356 -- Locale's abbreviated weekday name (Sun..Sat)
360 Image
(Day_Name
'Image (Day_Of_Week
(Date
)), 3);
362 -- Locale's full weekday name, variable length
363 -- (Sunday..Saturday)
367 Image
(Day_Name
'Image (Day_Of_Week
(Date
)));
369 -- Locale's abbreviated month name (Jan..Dec)
373 Image
(Month_Name
'Image (Month_Name
'Val (Month
- 1)), 3);
375 -- Locale's full month name, variable length
376 -- (January..December)
380 Image
(Month_Name
'Image (Month_Name
'Val (Month
- 1)));
382 -- Locale's date and time (Sat Nov 04 12:02:33 EST 1989)
387 Result
:= Result
& Image
(Date
, "%a %b %d %T %Y");
389 Result
:= Result
& Image
(Date
, "%a %b %_d %_T %Y");
391 Result
:= Result
& Image
(Date
, "%a %b %-d %-T %Y");
394 -- Day of month (01..31)
397 Result
:= Result
& Image
(Day
, Padding
, 2);
403 Image
(Month
, Padding
, 2) & '/' &
404 Image
(Day
, Padding
, 2) & '/' &
405 Image
(Year
, Padding
, 2);
407 -- Day of year (001..366)
410 Result
:= Result
& Image
(Day_In_Year
(Date
), Padding
, 3);
415 Result
:= Result
& Image
(Month
, Padding
, 2);
417 -- Week number of year with Sunday as first day of week
422 Offset
: constant Natural :=
423 (Julian_Day
(Year
, 1, 1) + 1) mod 7;
425 Week
: constant Natural :=
426 1 + ((Day_In_Year
(Date
) - 1) + Offset
) / 7;
429 Result
:= Result
& Image
(Week
, Padding
, 2);
432 -- Day of week (0..6) with 0 corresponding to Sunday
436 DOW
: Natural range 0 .. 6;
439 if Day_Of_Week
(Date
) = Sunday
then
442 DOW
:= Day_Name
'Pos (Day_Of_Week
(Date
));
445 Result
:= Result
& Image
(DOW
, Length
=> 1);
448 -- Week number of year with Monday as first day of week
452 Result
:= Result
& Image
(Week_In_Year
(Date
), Padding
, 2);
454 -- Last two digits of year (00..99)
458 Y
: constant Natural := Year
- (Year
/ 100) * 100;
460 Result
:= Result
& Image
(Y
, Padding
, 2);
466 Result
:= Result
& Image
(Year
, None
, 4);
475 Result
:= Result
& Picture
(P
);
479 exit when P
> Picture
'Last;
483 return To_String
(Result
);
491 (Date
: Ada
.Calendar
.Time
;
492 Picture
: Picture_String
)
495 Ada
.Text_IO
.Put
(Image
(Date
, Picture
));
498 end GNAT
.Calendar
.Time_IO
;