fixing pr42337
[official-gcc.git] / gcc / ada / a-calfor.adb
blobb8e6222475dad46e22def19c2110eea25b4914b7
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT RUN-TIME COMPONENTS --
4 -- --
5 -- A D A . C A L E N D A R . F O R M A T T I N G --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2006-2009, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
32 with Ada.Calendar; use Ada.Calendar;
33 with Ada.Calendar.Time_Zones; use Ada.Calendar.Time_Zones;
35 package body Ada.Calendar.Formatting is
37 --------------------------
38 -- Implementation Notes --
39 --------------------------
41 -- All operations in this package are target and time representation
42 -- independent, thus only one source file is needed for multiple targets.
44 procedure Check_Char (S : String; C : Character; Index : Integer);
45 -- Subsidiary to the two versions of Value. Determine whether the
46 -- input string S has character C at position Index. Raise
47 -- Constraint_Error if there is a mismatch.
49 procedure Check_Digit (S : String; Index : Integer);
50 -- Subsidiary to the two versions of Value. Determine whether the
51 -- character of string S at position Index is a digit. This catches
52 -- invalid input such as 1983-*1-j3 u5:n7:k9 which should be
53 -- 1983-01-03 05:07:09. Raise Constraint_Error if there is a mismatch.
55 ----------------
56 -- Check_Char --
57 ----------------
59 procedure Check_Char (S : String; C : Character; Index : Integer) is
60 begin
61 if S (Index) /= C then
62 raise Constraint_Error;
63 end if;
64 end Check_Char;
66 -----------------
67 -- Check_Digit --
68 -----------------
70 procedure Check_Digit (S : String; Index : Integer) is
71 begin
72 if S (Index) not in '0' .. '9' then
73 raise Constraint_Error;
74 end if;
75 end Check_Digit;
77 ---------
78 -- Day --
79 ---------
81 function Day
82 (Date : Time;
83 Time_Zone : Time_Zones.Time_Offset := 0) return Day_Number
85 Y : Year_Number;
86 Mo : Month_Number;
87 D : Day_Number;
88 H : Hour_Number;
89 Mi : Minute_Number;
90 Se : Second_Number;
91 Ss : Second_Duration;
92 Le : Boolean;
94 pragma Unreferenced (Y, Mo, H, Mi);
96 begin
97 Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
98 return D;
99 end Day;
101 -----------------
102 -- Day_Of_Week --
103 -----------------
105 function Day_Of_Week (Date : Time) return Day_Name is
106 begin
107 return Day_Name'Val (Formatting_Operations.Day_Of_Week (Date));
108 end Day_Of_Week;
110 ----------
111 -- Hour --
112 ----------
114 function Hour
115 (Date : Time;
116 Time_Zone : Time_Zones.Time_Offset := 0) return Hour_Number
118 Y : Year_Number;
119 Mo : Month_Number;
120 D : Day_Number;
121 H : Hour_Number;
122 Mi : Minute_Number;
123 Se : Second_Number;
124 Ss : Second_Duration;
125 Le : Boolean;
127 pragma Unreferenced (Y, Mo, D, Mi);
129 begin
130 Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
131 return H;
132 end Hour;
134 -----------
135 -- Image --
136 -----------
138 function Image
139 (Elapsed_Time : Duration;
140 Include_Time_Fraction : Boolean := False) return String
142 Hour : Hour_Number;
143 Minute : Minute_Number;
144 Second : Second_Number;
145 Sub_Second : Duration;
146 SS_Nat : Natural;
148 Low : Integer;
149 High : Integer;
151 Result : String := "-00:00:00.00";
153 begin
154 Split (abs (Elapsed_Time), Hour, Minute, Second, Sub_Second);
156 -- Determine the two slice bounds for the result string depending on
157 -- whether the input is negative and whether fractions are requested.
159 Low := (if Elapsed_Time < 0.0 then 1 else 2);
160 High := (if Include_Time_Fraction then 12 else 9);
162 -- Prevent rounding when converting to natural
164 Sub_Second := Sub_Second * 100.0;
166 if Sub_Second > 0.0 then
167 Sub_Second := Sub_Second - 0.5;
168 end if;
170 SS_Nat := Natural (Sub_Second);
172 declare
173 Hour_Str : constant String := Hour_Number'Image (Hour);
174 Minute_Str : constant String := Minute_Number'Image (Minute);
175 Second_Str : constant String := Second_Number'Image (Second);
176 SS_Str : constant String := Natural'Image (SS_Nat);
178 begin
179 -- Hour processing, positions 2 and 3
181 if Hour < 10 then
182 Result (3) := Hour_Str (2);
183 else
184 Result (2) := Hour_Str (2);
185 Result (3) := Hour_Str (3);
186 end if;
188 -- Minute processing, positions 5 and 6
190 if Minute < 10 then
191 Result (6) := Minute_Str (2);
192 else
193 Result (5) := Minute_Str (2);
194 Result (6) := Minute_Str (3);
195 end if;
197 -- Second processing, positions 8 and 9
199 if Second < 10 then
200 Result (9) := Second_Str (2);
201 else
202 Result (8) := Second_Str (2);
203 Result (9) := Second_Str (3);
204 end if;
206 -- Optional sub second processing, positions 11 and 12
208 if Include_Time_Fraction then
209 if SS_Nat < 10 then
210 Result (12) := SS_Str (2);
211 else
212 Result (11) := SS_Str (2);
213 Result (12) := SS_Str (3);
214 end if;
215 end if;
217 return Result (Low .. High);
218 end;
219 end Image;
221 -----------
222 -- Image --
223 -----------
225 function Image
226 (Date : Time;
227 Include_Time_Fraction : Boolean := False;
228 Time_Zone : Time_Zones.Time_Offset := 0) return String
230 Year : Year_Number;
231 Month : Month_Number;
232 Day : Day_Number;
233 Hour : Hour_Number;
234 Minute : Minute_Number;
235 Second : Second_Number;
236 Sub_Second : Duration;
237 SS_Nat : Natural;
238 Leap_Second : Boolean;
240 Result : String := "0000-00-00 00:00:00.00";
242 begin
243 Split (Date, Year, Month, Day,
244 Hour, Minute, Second, Sub_Second, Leap_Second, Time_Zone);
246 -- Prevent rounding when converting to natural
248 Sub_Second := Sub_Second * 100.0;
250 if Sub_Second > 0.0 then
251 Sub_Second := Sub_Second - 0.5;
252 end if;
254 SS_Nat := Natural (Sub_Second);
256 declare
257 Year_Str : constant String := Year_Number'Image (Year);
258 Month_Str : constant String := Month_Number'Image (Month);
259 Day_Str : constant String := Day_Number'Image (Day);
260 Hour_Str : constant String := Hour_Number'Image (Hour);
261 Minute_Str : constant String := Minute_Number'Image (Minute);
262 Second_Str : constant String := Second_Number'Image (Second);
263 SS_Str : constant String := Natural'Image (SS_Nat);
265 begin
266 -- Year processing, positions 1, 2, 3 and 4
268 Result (1) := Year_Str (2);
269 Result (2) := Year_Str (3);
270 Result (3) := Year_Str (4);
271 Result (4) := Year_Str (5);
273 -- Month processing, positions 6 and 7
275 if Month < 10 then
276 Result (7) := Month_Str (2);
277 else
278 Result (6) := Month_Str (2);
279 Result (7) := Month_Str (3);
280 end if;
282 -- Day processing, positions 9 and 10
284 if Day < 10 then
285 Result (10) := Day_Str (2);
286 else
287 Result (9) := Day_Str (2);
288 Result (10) := Day_Str (3);
289 end if;
291 -- Hour processing, positions 12 and 13
293 if Hour < 10 then
294 Result (13) := Hour_Str (2);
295 else
296 Result (12) := Hour_Str (2);
297 Result (13) := Hour_Str (3);
298 end if;
300 -- Minute processing, positions 15 and 16
302 if Minute < 10 then
303 Result (16) := Minute_Str (2);
304 else
305 Result (15) := Minute_Str (2);
306 Result (16) := Minute_Str (3);
307 end if;
309 -- Second processing, positions 18 and 19
311 if Second < 10 then
312 Result (19) := Second_Str (2);
313 else
314 Result (18) := Second_Str (2);
315 Result (19) := Second_Str (3);
316 end if;
318 -- Optional sub second processing, positions 21 and 22
320 if Include_Time_Fraction then
321 if SS_Nat < 10 then
322 Result (22) := SS_Str (2);
323 else
324 Result (21) := SS_Str (2);
325 Result (22) := SS_Str (3);
326 end if;
328 return Result;
329 else
330 return Result (1 .. 19);
331 end if;
332 end;
333 end Image;
335 ------------
336 -- Minute --
337 ------------
339 function Minute
340 (Date : Time;
341 Time_Zone : Time_Zones.Time_Offset := 0) return Minute_Number
343 Y : Year_Number;
344 Mo : Month_Number;
345 D : Day_Number;
346 H : Hour_Number;
347 Mi : Minute_Number;
348 Se : Second_Number;
349 Ss : Second_Duration;
350 Le : Boolean;
352 pragma Unreferenced (Y, Mo, D, H);
354 begin
355 Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
356 return Mi;
357 end Minute;
359 -----------
360 -- Month --
361 -----------
363 function Month
364 (Date : Time;
365 Time_Zone : Time_Zones.Time_Offset := 0) return Month_Number
367 Y : Year_Number;
368 Mo : Month_Number;
369 D : Day_Number;
370 H : Hour_Number;
371 Mi : Minute_Number;
372 Se : Second_Number;
373 Ss : Second_Duration;
374 Le : Boolean;
376 pragma Unreferenced (Y, D, H, Mi);
378 begin
379 Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
380 return Mo;
381 end Month;
383 ------------
384 -- Second --
385 ------------
387 function Second (Date : Time) return Second_Number is
388 Y : Year_Number;
389 Mo : Month_Number;
390 D : Day_Number;
391 H : Hour_Number;
392 Mi : Minute_Number;
393 Se : Second_Number;
394 Ss : Second_Duration;
395 Le : Boolean;
397 pragma Unreferenced (Y, Mo, D, H, Mi);
399 begin
400 Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le);
401 return Se;
402 end Second;
404 ----------------
405 -- Seconds_Of --
406 ----------------
408 function Seconds_Of
409 (Hour : Hour_Number;
410 Minute : Minute_Number;
411 Second : Second_Number := 0;
412 Sub_Second : Second_Duration := 0.0) return Day_Duration is
414 begin
415 -- Validity checks
417 if not Hour'Valid
418 or else not Minute'Valid
419 or else not Second'Valid
420 or else not Sub_Second'Valid
421 then
422 raise Constraint_Error;
423 end if;
425 return Day_Duration (Hour * 3_600) +
426 Day_Duration (Minute * 60) +
427 Day_Duration (Second) +
428 Sub_Second;
429 end Seconds_Of;
431 -----------
432 -- Split --
433 -----------
435 procedure Split
436 (Seconds : Day_Duration;
437 Hour : out Hour_Number;
438 Minute : out Minute_Number;
439 Second : out Second_Number;
440 Sub_Second : out Second_Duration)
442 Secs : Natural;
444 begin
445 -- Validity checks
447 if not Seconds'Valid then
448 raise Constraint_Error;
449 end if;
451 Secs := (if Seconds = 0.0 then 0 else Natural (Seconds - 0.5));
453 Sub_Second := Second_Duration (Seconds - Day_Duration (Secs));
454 Hour := Hour_Number (Secs / 3_600);
455 Secs := Secs mod 3_600;
456 Minute := Minute_Number (Secs / 60);
457 Second := Second_Number (Secs mod 60);
459 -- Validity checks
461 if not Hour'Valid
462 or else not Minute'Valid
463 or else not Second'Valid
464 or else not Sub_Second'Valid
465 then
466 raise Time_Error;
467 end if;
468 end Split;
470 -----------
471 -- Split --
472 -----------
474 procedure Split
475 (Date : Time;
476 Year : out Year_Number;
477 Month : out Month_Number;
478 Day : out Day_Number;
479 Seconds : out Day_Duration;
480 Leap_Second : out Boolean;
481 Time_Zone : Time_Zones.Time_Offset := 0)
483 H : Integer;
484 M : Integer;
485 Se : Integer;
486 Su : Duration;
487 Tz : constant Long_Integer := Long_Integer (Time_Zone);
489 begin
490 Formatting_Operations.Split
491 (Date => Date,
492 Year => Year,
493 Month => Month,
494 Day => Day,
495 Day_Secs => Seconds,
496 Hour => H,
497 Minute => M,
498 Second => Se,
499 Sub_Sec => Su,
500 Leap_Sec => Leap_Second,
501 Time_Zone => Tz,
502 Is_Ada_05 => True);
504 -- Validity checks
506 if not Year'Valid
507 or else not Month'Valid
508 or else not Day'Valid
509 or else not Seconds'Valid
510 then
511 raise Time_Error;
512 end if;
513 end Split;
515 -----------
516 -- Split --
517 -----------
519 procedure Split
520 (Date : Time;
521 Year : out Year_Number;
522 Month : out Month_Number;
523 Day : out Day_Number;
524 Hour : out Hour_Number;
525 Minute : out Minute_Number;
526 Second : out Second_Number;
527 Sub_Second : out Second_Duration;
528 Time_Zone : Time_Zones.Time_Offset := 0)
530 Dd : Day_Duration;
531 Le : Boolean;
532 Tz : constant Long_Integer := Long_Integer (Time_Zone);
534 begin
535 Formatting_Operations.Split
536 (Date => Date,
537 Year => Year,
538 Month => Month,
539 Day => Day,
540 Day_Secs => Dd,
541 Hour => Hour,
542 Minute => Minute,
543 Second => Second,
544 Sub_Sec => Sub_Second,
545 Leap_Sec => Le,
546 Time_Zone => Tz,
547 Is_Ada_05 => True);
549 -- Validity checks
551 if not Year'Valid
552 or else not Month'Valid
553 or else not Day'Valid
554 or else not Hour'Valid
555 or else not Minute'Valid
556 or else not Second'Valid
557 or else not Sub_Second'Valid
558 then
559 raise Time_Error;
560 end if;
561 end Split;
563 -----------
564 -- Split --
565 -----------
567 procedure Split
568 (Date : Time;
569 Year : out Year_Number;
570 Month : out Month_Number;
571 Day : out Day_Number;
572 Hour : out Hour_Number;
573 Minute : out Minute_Number;
574 Second : out Second_Number;
575 Sub_Second : out Second_Duration;
576 Leap_Second : out Boolean;
577 Time_Zone : Time_Zones.Time_Offset := 0)
579 Dd : Day_Duration;
580 Tz : constant Long_Integer := Long_Integer (Time_Zone);
582 begin
583 Formatting_Operations.Split
584 (Date => Date,
585 Year => Year,
586 Month => Month,
587 Day => Day,
588 Day_Secs => Dd,
589 Hour => Hour,
590 Minute => Minute,
591 Second => Second,
592 Sub_Sec => Sub_Second,
593 Leap_Sec => Leap_Second,
594 Time_Zone => Tz,
595 Is_Ada_05 => True);
597 -- Validity checks
599 if not Year'Valid
600 or else not Month'Valid
601 or else not Day'Valid
602 or else not Hour'Valid
603 or else not Minute'Valid
604 or else not Second'Valid
605 or else not Sub_Second'Valid
606 then
607 raise Time_Error;
608 end if;
609 end Split;
611 ----------------
612 -- Sub_Second --
613 ----------------
615 function Sub_Second (Date : Time) return Second_Duration is
616 Y : Year_Number;
617 Mo : Month_Number;
618 D : Day_Number;
619 H : Hour_Number;
620 Mi : Minute_Number;
621 Se : Second_Number;
622 Ss : Second_Duration;
623 Le : Boolean;
625 pragma Unreferenced (Y, Mo, D, H, Mi);
627 begin
628 Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le);
629 return Ss;
630 end Sub_Second;
632 -------------
633 -- Time_Of --
634 -------------
636 function Time_Of
637 (Year : Year_Number;
638 Month : Month_Number;
639 Day : Day_Number;
640 Seconds : Day_Duration := 0.0;
641 Leap_Second : Boolean := False;
642 Time_Zone : Time_Zones.Time_Offset := 0) return Time
644 Adj_Year : Year_Number := Year;
645 Adj_Month : Month_Number := Month;
646 Adj_Day : Day_Number := Day;
648 H : constant Integer := 1;
649 M : constant Integer := 1;
650 Se : constant Integer := 1;
651 Ss : constant Duration := 0.1;
652 Tz : constant Long_Integer := Long_Integer (Time_Zone);
654 begin
655 -- Validity checks
657 if not Year'Valid
658 or else not Month'Valid
659 or else not Day'Valid
660 or else not Seconds'Valid
661 or else not Time_Zone'Valid
662 then
663 raise Constraint_Error;
664 end if;
666 -- A Seconds value of 86_400 denotes a new day. This case requires an
667 -- adjustment to the input values.
669 if Seconds = 86_400.0 then
670 if Day < Days_In_Month (Month)
671 or else (Is_Leap (Year)
672 and then Month = 2)
673 then
674 Adj_Day := Day + 1;
675 else
676 Adj_Day := 1;
678 if Month < 12 then
679 Adj_Month := Month + 1;
680 else
681 Adj_Month := 1;
682 Adj_Year := Year + 1;
683 end if;
684 end if;
685 end if;
687 return
688 Formatting_Operations.Time_Of
689 (Year => Adj_Year,
690 Month => Adj_Month,
691 Day => Adj_Day,
692 Day_Secs => Seconds,
693 Hour => H,
694 Minute => M,
695 Second => Se,
696 Sub_Sec => Ss,
697 Leap_Sec => Leap_Second,
698 Use_Day_Secs => True,
699 Is_Ada_05 => True,
700 Time_Zone => Tz);
701 end Time_Of;
703 -------------
704 -- Time_Of --
705 -------------
707 function Time_Of
708 (Year : Year_Number;
709 Month : Month_Number;
710 Day : Day_Number;
711 Hour : Hour_Number;
712 Minute : Minute_Number;
713 Second : Second_Number;
714 Sub_Second : Second_Duration := 0.0;
715 Leap_Second : Boolean := False;
716 Time_Zone : Time_Zones.Time_Offset := 0) return Time
718 Dd : constant Day_Duration := Day_Duration'First;
719 Tz : constant Long_Integer := Long_Integer (Time_Zone);
721 begin
722 -- Validity checks
724 if not Year'Valid
725 or else not Month'Valid
726 or else not Day'Valid
727 or else not Hour'Valid
728 or else not Minute'Valid
729 or else not Second'Valid
730 or else not Sub_Second'Valid
731 or else not Time_Zone'Valid
732 then
733 raise Constraint_Error;
734 end if;
736 return
737 Formatting_Operations.Time_Of
738 (Year => Year,
739 Month => Month,
740 Day => Day,
741 Day_Secs => Dd,
742 Hour => Hour,
743 Minute => Minute,
744 Second => Second,
745 Sub_Sec => Sub_Second,
746 Leap_Sec => Leap_Second,
747 Use_Day_Secs => False,
748 Is_Ada_05 => True,
749 Time_Zone => Tz);
750 end Time_Of;
752 -----------
753 -- Value --
754 -----------
756 function Value
757 (Date : String;
758 Time_Zone : Time_Zones.Time_Offset := 0) return Time
760 D : String (1 .. 22);
761 Year : Year_Number;
762 Month : Month_Number;
763 Day : Day_Number;
764 Hour : Hour_Number;
765 Minute : Minute_Number;
766 Second : Second_Number;
767 Sub_Second : Second_Duration := 0.0;
769 begin
770 -- Validity checks
772 if not Time_Zone'Valid then
773 raise Constraint_Error;
774 end if;
776 -- Length checks
778 if Date'Length /= 19
779 and then Date'Length /= 22
780 then
781 raise Constraint_Error;
782 end if;
784 -- After the correct length has been determined, it is safe to
785 -- copy the Date in order to avoid Date'First + N indexing.
787 D (1 .. Date'Length) := Date;
789 -- Format checks
791 Check_Char (D, '-', 5);
792 Check_Char (D, '-', 8);
793 Check_Char (D, ' ', 11);
794 Check_Char (D, ':', 14);
795 Check_Char (D, ':', 17);
797 if Date'Length = 22 then
798 Check_Char (D, '.', 20);
799 end if;
801 -- Leading zero checks
803 Check_Digit (D, 6);
804 Check_Digit (D, 9);
805 Check_Digit (D, 12);
806 Check_Digit (D, 15);
807 Check_Digit (D, 18);
809 if Date'Length = 22 then
810 Check_Digit (D, 21);
811 end if;
813 -- Value extraction
815 Year := Year_Number (Year_Number'Value (D (1 .. 4)));
816 Month := Month_Number (Month_Number'Value (D (6 .. 7)));
817 Day := Day_Number (Day_Number'Value (D (9 .. 10)));
818 Hour := Hour_Number (Hour_Number'Value (D (12 .. 13)));
819 Minute := Minute_Number (Minute_Number'Value (D (15 .. 16)));
820 Second := Second_Number (Second_Number'Value (D (18 .. 19)));
822 -- Optional part
824 if Date'Length = 22 then
825 Sub_Second := Second_Duration (Second_Duration'Value (D (20 .. 22)));
826 end if;
828 -- Sanity checks
830 if not Year'Valid
831 or else not Month'Valid
832 or else not Day'Valid
833 or else not Hour'Valid
834 or else not Minute'Valid
835 or else not Second'Valid
836 or else not Sub_Second'Valid
837 then
838 raise Constraint_Error;
839 end if;
841 return Time_Of (Year, Month, Day,
842 Hour, Minute, Second, Sub_Second, False, Time_Zone);
844 exception
845 when others => raise Constraint_Error;
846 end Value;
848 -----------
849 -- Value --
850 -----------
852 function Value (Elapsed_Time : String) return Duration is
853 D : String (1 .. 11);
854 Hour : Hour_Number;
855 Minute : Minute_Number;
856 Second : Second_Number;
857 Sub_Second : Second_Duration := 0.0;
859 begin
860 -- Length checks
862 if Elapsed_Time'Length /= 8
863 and then Elapsed_Time'Length /= 11
864 then
865 raise Constraint_Error;
866 end if;
868 -- After the correct length has been determined, it is safe to
869 -- copy the Elapsed_Time in order to avoid Date'First + N indexing.
871 D (1 .. Elapsed_Time'Length) := Elapsed_Time;
873 -- Format checks
875 Check_Char (D, ':', 3);
876 Check_Char (D, ':', 6);
878 if Elapsed_Time'Length = 11 then
879 Check_Char (D, '.', 9);
880 end if;
882 -- Leading zero checks
884 Check_Digit (D, 1);
885 Check_Digit (D, 4);
886 Check_Digit (D, 7);
888 if Elapsed_Time'Length = 11 then
889 Check_Digit (D, 10);
890 end if;
892 -- Value extraction
894 Hour := Hour_Number (Hour_Number'Value (D (1 .. 2)));
895 Minute := Minute_Number (Minute_Number'Value (D (4 .. 5)));
896 Second := Second_Number (Second_Number'Value (D (7 .. 8)));
898 -- Optional part
900 if Elapsed_Time'Length = 11 then
901 Sub_Second := Second_Duration (Second_Duration'Value (D (9 .. 11)));
902 end if;
904 -- Sanity checks
906 if not Hour'Valid
907 or else not Minute'Valid
908 or else not Second'Valid
909 or else not Sub_Second'Valid
910 then
911 raise Constraint_Error;
912 end if;
914 return Seconds_Of (Hour, Minute, Second, Sub_Second);
916 exception
917 when others => raise Constraint_Error;
918 end Value;
920 ----------
921 -- Year --
922 ----------
924 function Year
925 (Date : Time;
926 Time_Zone : Time_Zones.Time_Offset := 0) return Year_Number
928 Y : Year_Number;
929 Mo : Month_Number;
930 D : Day_Number;
931 H : Hour_Number;
932 Mi : Minute_Number;
933 Se : Second_Number;
934 Ss : Second_Duration;
935 Le : Boolean;
937 pragma Unreferenced (Mo, D, H, Mi);
939 begin
940 Split (Date, Y, Mo, D, H, Mi, Se, Ss, Le, Time_Zone);
941 return Y;
942 end Year;
944 end Ada.Calendar.Formatting;