------------------------------------------------------------------------------- -- -- Copyright © 2001, 2002 by Thomas Wolf. --
-- This piece of software is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as published -- by the Free Software Foundation; either version 2, or (at your option) -- any later version. This software is distributed in the hope that it will -- be useful, but without 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 with this distribution, -- see file "GPL.txt". If not, write to the Free -- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, -- USA. --
--
-- As a special exception from the GPL, 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 GPL. This exception does not however invalidate any -- other reasons why the executable file might be covered by the GPL. --
-- -- -- Thomas Wolf (TW) -- -- -- -- Routines for converting @Ada.Calendar.Time@ values to strings. Identical -- in function to the operations in -- Util.Calendars.Western -- and Util.Times.IO. -- -- Provided nonetheless because one doesn't always want to drag in all the -- extended time and calendar support, especially for simple applications. -- -- -- -- Fully task-safe; not abortion-safe. -- -- -- -- -- -- 13-MAR-2002 TW Initial version. -- ------------------------------------------------------------------------------- pragma License (Modified_GPL); with Ada.Strings.Fixed; with Ada.Text_IO; package body Util.Calendar.IO is use Ada.Calendar; ---------------------------------------------------------------------------- -- Utility functions function Pad (Source : in String; Count : in Natural := 2; Pad : in Character := '0') return String renames Ada.Strings.Fixed.Tail; -- 'Tail' is such a misleading name: we don't want to get at source's -- tail, we want to right-align and pad it with leading zeroes! function Trim (Source : in String; Side : in Ada.Strings.Trim_End := Ada.Strings.Both) return String renames Ada.Strings.Fixed.Trim; -- Renaming to supply the 'Side' argument. ---------------------------------------------------------------------------- -- Images for type 'Day_Duration' function Image (Instant : in Ada.Calendar.Day_Duration; With_Seconds : in Boolean := True; AM_PM : in Boolean := False) return String is begin if not AM_PM then declare H : Hours_Type; M : Minutes_Type; S : Seconds_Type; F : Day_Duration; begin Split (Instant, H, M, S, F); if not With_Seconds then return Pad (Trim (Hours_Type'Image (H))) & ':' & Pad (Trim (Minutes_Type'Image (M))); else return Pad (Trim (Hours_Type'Image (H))) & ':' & Pad (Trim (Minutes_Type'Image (M))) & ':' & Pad (Trim (Seconds_Type'Image (S))); end if; end; else if Instant = 0.0 then return "Midnight"; elsif Instant = 43_200.0 then return "Noon"; end if; if Instant > 43_200.0 then if Instant >= 43_200.0 + 3_600.0 then return Image (Instant - 43_200.0, With_Seconds) & " pm"; else -- Hmmm... I believe times between noon and 13:00 are usually -- given as "12:xx pm"? return Image (Instant, With_Seconds) & " pm"; end if; else return Image (Instant, With_Seconds) & " am"; end if; end if; end Image; package DIO is new Ada.Text_IO.Fixed_IO (Day_Duration); function Image (Instant : in Ada.Calendar.Day_Duration; Precision : in Natural; AM_PM : in Boolean := False) return String is begin if not AM_PM then declare Frac : String (1 .. Day_Duration'Fore + 1 + Natural'Max (Day_Duration'Aft, Precision)); H : Hours_Type; M : Minutes_Type; S : Seconds_Type; F : Day_Duration; HH : Natural; begin Split (Instant, H, M, S, F); -- HH is *not* Hours_Type because it may overflow to 24! HH := Natural (H); -- We nicely delegate the whole rounding business to 'DIO'! DIO.Put (To => Frac, Item => F, Aft => Precision, Exp => 0); declare Fraction : constant String := Trim (Frac); begin -- Since F is always positive, Fraction now has the format -- "D.DDDDD". if Fraction (Fraction'First) = '1' or else (Precision = 0 and then F >= 0.5) then -- Propagate carry: if S = Seconds_Type'Last then if M = Minutes_Type'Last then HH := HH + 1; M := 0; else M := M + 1; end if; S := 0; else S := S + 1; end if; end if; if Precision > 0 then return Pad (Trim (Natural'Image (HH))) & ':' & Pad (Trim (Minutes_Type'Image (M))) & ':' & Pad (Trim (Seconds_Type'Image (S))) & Fraction (Fraction'First + 1 .. Fraction'Last); else return Pad (Trim (Natural'Image (HH))) & ':' & Pad (Trim (Minutes_Type'Image (M))) & ':' & Pad (Trim (Seconds_Type'Image (S))); end if; end; end; else -- AM/PM Format if Instant = 0.0 then return "Midnight"; elsif Instant = 43_200.0 then return "Noon"; end if; if Instant > 43_200.0 then -- What about times between 12:00 and 13:00 here? Rounding of -- times > 23:59:59.5 may give "12:00:00 pm", but so should -- rounding down of times between 12:00:00 and 12:00:00.5. For -- the latter case, we return "00:00:00 pm"; client code can -- check for that and change it into "12:00:00 pm" if desired. return Image (Instant - 43_200.0, Precision) & " pm"; else return Image (Instant, Precision) & " am"; end if; end if; end Image; function Image (Date : in Ada.Calendar.Time; Format : in Date_Format := YMD; Separator : in String := "-"; Padding : in Boolean := True) return String is function Canonical (Source : in String; Padding : in Boolean) return String is begin -- Canonical if Padding then return Pad (Trim (Source)); else return Trim (Source); end if; end Canonical; Y : Year_Number; M : Month_Number; D : Day_Number; S : Day_Duration; begin Split (Date, Y, M, D, S); declare YS : constant String := Trim (Year_Number'Image (Y)); MS : constant String := Canonical (Month_Number'Image (M), Padding); DS : constant String := Canonical (Day_Number'Image (D), Padding); begin case Format is when DMY => return DS & Separator & MS & Separator & YS; when MDY => return MS & Separator & DS & Separator & YS; when YMD => return YS & Separator & MS & Separator & DS; end case; end; end Image; end Util.Calendar.IO;