From 90a1abf304ff076f2e96a5d039f549e99124a606 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Sun, 10 May 2020 11:29:27 -0400 Subject: [PATCH] [Ada] Time_IO.Image: Allow printing the time zone gcc/ada/ * libgnat/g-catiio.ads: Document newly supported format. Add ISO_Time constant, for convenience. * libgnat/g-catiio.adb (Image_Helper): New helper function to do all the formatting work, called by the two exported Image functions. Add support for "%:::z" here. Add a Time_Zone parameter used by the "%:::z" processing. This parameter is not used for the actual time zone computations; local time is always used for that, for ease of implementation reasons. It would make sense to use Append throughout this function, but that's a cleanup for another day. (Image): Modify these to pass the local time zone, or the specified time zone, as appropriate. --- gcc/ada/libgnat/g-catiio.adb | 73 ++++++++++++++++++++++++++++++++++-- gcc/ada/libgnat/g-catiio.ads | 10 ++++- 2 files changed, 77 insertions(+), 6 deletions(-) diff --git a/gcc/ada/libgnat/g-catiio.adb b/gcc/ada/libgnat/g-catiio.adb index f7bffe4e471..ad1babfb826 100644 --- a/gcc/ada/libgnat/g-catiio.adb +++ b/gcc/ada/libgnat/g-catiio.adb @@ -69,6 +69,14 @@ package body GNAT.Calendar.Time_IO is -- Local Subprograms -- ----------------------- + function Image_Helper + (Date : Ada.Calendar.Time; + Picture : Picture_String; + Time_Zone : Time_Zones.Time_Offset) return String; + -- This is called by the two exported Image functions. It uses the local + -- time zone for its computations, but uses Time_Zone when interpreting the + -- "%:::z" tag. + function Am_Pm (H : Natural) return String; -- Return AM or PM depending on the hour H @@ -168,6 +176,10 @@ package body GNAT.Calendar.Time_IO is return Image (Sec_Number (N), Padding, Length); end Image; + ----------- + -- Image -- + ----------- + function Image (N : Sec_Number; Padding : Padding_Mode := Zero; @@ -213,15 +225,16 @@ package body GNAT.Calendar.Time_IO is Time_Zone : Time_Zones.Time_Offset) return String is -- We subtract off the local time zone, and add in the requested - -- Time_Zone, and then pass it on to the version of Image that uses - -- the local time zone. + -- Time_Zone, and then pass it on to Image_Helper, which uses the + -- local time zone. use Time_Zones; Local_TZ : constant Time_Offset := Local_Time_Offset (Date); Minute_Offset : constant Integer := Integer (Time_Zone - Local_TZ); Second_Offset : constant Integer := Minute_Offset * 60; begin - return Image (Date + Duration (Second_Offset), Picture); + return Image_Helper + (Date + Duration (Second_Offset), Picture, Time_Zone); end Image; ----------- @@ -231,6 +244,21 @@ package body GNAT.Calendar.Time_IO is function Image (Date : Ada.Calendar.Time; Picture : Picture_String) return String + is + use Time_Zones; + Local_TZ : constant Time_Offset := Local_Time_Offset (Date); + begin + return Image_Helper (Date, Picture, Local_TZ); + end Image; + + ------------------ + -- Image_Helper -- + ------------------ + + function Image_Helper + (Date : Ada.Calendar.Time; + Picture : Picture_String; + Time_Zone : Time_Zones.Time_Offset) return String is Padding : Padding_Mode := Zero; -- Padding is set for one directive @@ -424,6 +452,43 @@ package body GNAT.Calendar.Time_IO is Image (Minute, Padding, Length => 2) & ':' & Image (Second, Padding, Length => 2); + -- Time zone. Append "+hh", "-hh", "+hh:mm", or "-hh:mm", as + -- appropriate. + + when ':' => + declare + use type Time_Zones.Time_Offset; + TZ_Form : constant Picture_String := "%:::z"; + TZ : constant Natural := Natural (abs Time_Zone); + begin + if P + TZ_Form'Length - 1 <= Picture'Last + and then Picture (P .. P + TZ_Form'Length - 1) = "%:::z" + then + if Time_Zone >= 0 then + Result := Result & "+"; + else + Result := Result & "-"; + end if; + + Result := Result & + Image (Integer (TZ / 60), Padding, Length => 2); + + if TZ mod 60 /= 0 then + Result := Result & ":"; + Result := Result & + Image (TZ mod 60, Padding, Length => 2); + end if; + + P := P + TZ_Form'Length - 2; -- will add 2 below + + -- We do not support any of the other standard GNU + -- time-zone formats (%z, %:z, %::z, %Z). + + else + raise Picture_Error with "unsupported picture format"; + end if; + end; + -- Locale's abbreviated weekday name (Sun..Sat) when 'a' => @@ -550,7 +615,7 @@ package body GNAT.Calendar.Time_IO is end loop; return To_String (Result); - end Image; + end Image_Helper; -------------------------- -- Month_Name_To_Number -- diff --git a/gcc/ada/libgnat/g-catiio.ads b/gcc/ada/libgnat/g-catiio.ads index 982b80d13c3..6bb98471f69 100644 --- a/gcc/ada/libgnat/g-catiio.ads +++ b/gcc/ada/libgnat/g-catiio.ads @@ -43,7 +43,7 @@ package GNAT.Calendar.Time_IO is -- This is a string to describe date and time output format. The string is -- a set of standard character and special tag that are replaced by the -- corresponding values. It follows the GNU Date specification. Here are - -- the recognized directives : + -- the recognized directives: -- -- % a literal % -- n a newline @@ -62,6 +62,8 @@ package GNAT.Calendar.Time_IO is -- (a nonstandard extension) -- %S second (00..59) -- %T time, 24-hour (hh:mm:ss) + -- %:::z numeric time zone with : to necessary precision + -- (e.g., -04, +05:30) -- -- Date fields: -- @@ -98,8 +100,11 @@ package GNAT.Calendar.Time_IO is -- %e microseconds (6 digits) -- %o nanoseconds (9 digits) + ISO_Time : constant Picture_String; + -- ISO 8601 standard date and time, with time zone. + ISO_Date : constant Picture_String; - -- This format follow the ISO 8601 standard. The format is "YYYY-MM-DD", + -- This format follows the ISO 8601 standard. The format is "YYYY-MM-DD", -- four digits year, month and day number separated by minus. US_Date : constant Picture_String; @@ -174,6 +179,7 @@ package GNAT.Calendar.Time_IO is -- Put Date with format Picture. Raise Picture_Error if bad picture string private + ISO_Time : constant Picture_String := "%Y-%m-%dT%H:%M:%S%:::z"; ISO_Date : constant Picture_String := "%Y-%m-%d"; US_Date : constant Picture_String := "%m/%d/%y"; European_Date : constant Picture_String := "%d/%m/%y"; -- 2.30.2