For a file name, how to build the unbounded_string of:

For a file name, how to build the unbounded_string of:

YyyyMmDd.Hr.Mn.Se

where Y year, M month, D day, Hr hour, Mn minute, and Se second.

For example “20240819.15.28.17” for August 19, 2024 at 3:28:17 PM.

Cohen (1986) on this was probably written by a first semester graduate assistant, and Ada95RM as a compiler-writer’s guide is not informative to me after two reads from the index.

Hi;

I found something pertinent when going to the learn.adacore.com web site.

There’s a download button there.

I can’t find the “timestamp.adb” file when browing this site, but when I downloaded it (last year?), it contained this file.

It looks like it does almost exactly what you want.

The path inside the directory I downloaded is:

from_AdaCore_Getting_Started/calendar/timestamp.adb

Hope this helps,
Retired Build Engineer

Update/Correction: Looking at this file more closely I see that it was something that I wrote, partially achieving what I wanted using some minimal insight gained from going through the learn.adacore.com website (Standard library: Dates & Times — learn.adacore.com). So you probably won’t find this file when looking there; sorry to misinform you. If you want my half-a**sed code attempt, (incomplete) I’ll share it here (I’m sure I’ll get lots of (positive?) criticism if I do)…

Retird Build Engineer

Thanks for suggesting. I generally avoid AdaCore because it is based on Stallman’s stint at and C-language from NYU while feeding at the public trough where nothing turned out to be free as promised from taxpayer expense.

As usual in Ada95, there’s nothing as straight forward as True BASIC string handling in:
Date$ & “.” & RepChar$( Time$, “:”, “.”) for “20240819.20.22.11”.

I am just trying to void wading through contractor-speak in RM95 and densely packed, page-long paragraphs in the Barnes, Cohen, and Feldman used copies which I own. For example, none has an index entry for “Date” or example of the constructor program Time_of.

An example code largely inspired by the Image function of the standard library (GNAT) :

with Ada.Calendar.Formatting;
with Ada.Text_IO;

procedure Test is
   --  t : constant Ada.Calendar.Time := Ada.Calendar.Clock;

   function TimeToString (Time : Ada.Calendar.Time) return String is
      To_Char : constant array (0 .. 9) of Character := "0123456789";

      Year       : Ada.Calendar.Year_Number;
      Month      : Ada.Calendar.Month_Number;
      Day        : Ada.Calendar.Day_Number;
      Hour       : Ada.Calendar.Formatting.Hour_Number;
      Minute     : Ada.Calendar.Formatting.Minute_Number;
      Second     : Ada.Calendar.Formatting.Second_Number;
      Sub_Second : Ada.Calendar.Formatting.Second_Duration;

      Result : String := "00000000.00.00.00";
   begin
      Ada.Calendar.Formatting.Split
                         (Date       => Time,
                          Year       => Year,
                          Month      => Month,
                          Day        => Day,
                          Hour       => Hour,
                          Minute     => Minute,
                          Second     => Second,
                          Sub_Second => Sub_Second);
      --  Year processing
      Result (1) := To_Char (Year / 1000);
      Result (2) := To_Char (Year / 100 mod 10);
      Result (3) := To_Char (Year / 10 mod 10);
      Result (4) := To_Char (Year mod 10);
      --  Month processing
      Result (5) := To_Char (Month / 10);
      Result (6) := To_Char (Month mod 10);
      --  Day processing
      Result (7)  := To_Char (Day / 10);
      Result (8) := To_Char (Day mod 10);
      --  Hour processing
      Result (10) := To_Char (Hour / 10);
      Result (11) := To_Char (Hour mod 10);
      --  Minute processing
      Result (13) := To_Char (Minute / 10);
      Result (14) := To_Char (Minute mod 10);
      --  Second processing
      Result (16) := To_Char (Second / 10);
      Result (17) := To_Char (Second mod 10);

      return Result;
   end TimeToString;

begin
   Ada.Text_IO.Put_Line ("Date and Time : " & TimeToString (Ada.Calendar.Clock));
end Test;

This is awsesome! This was what I was trying to do myself and didn’t quite get to the finish line. My desired format is “YYYYMMDD_HHMMSS”, which was very easy to obtain from this code.

Thanks,
Retired Build Engineer

Thank you for the code that compiled and ran at IdeOne.com, an organ of GNAT.

However for my requirement to stay in Ada95, the code barfs because it uses a different definition of Split where the time of day is expected in seconds after midnight as in True BASIC with hours derived using sexagesimal arithmetic.

I really wonder if there isn’t a simpler way to get DATE$ and TIME$ without all that typing.

My mistake was in not making the title of this thread more explicit as:

“In Ada 95, how to build the string for “YYYYMMDD.sssss””

but decided not to reinvent a new topic to save bandwidth.

Unfortunately the library Ada.Calendar.Formatting is too advanced for the RM95, and is a more fundamental reason the proffered code barfs.

Surely there is reusable code for this somewhere in the public domain to appropriate, but I just can’t find it. One would think that Booch et al cooked it up much as Numerical Recipes in FORTRAN, but no cigar.

Since I only use the code once, I prefer not to stack-it by calling as a function or procedure, but rather to keep it inline. This is my proposed solution in nine lines of code.

WITH Ada.text_io ;             USE Ada.text_io ;
WITH Ada.strings.unbounded ;   USE Ada.strings.unbounded ;
WITH Ada.calendar ;            USE Ada.calendar ;
-- .....
DECLARE
  time_tim     : Time ;
  YYYY_int     : Integer ;
  MM_int       : Integer ;
  DD_int       : Integer ;
  sssss_int    : Duration ;
  time_unb_str : Unbounded_string ;

  time_tim := Clock ;
  Split( time_tim, YYYY_int, MM_int, DD_int, sssss_dur) ;
  time_unb_str := To_unbounded_string( IMAGE'YYYY_int & IMAGE'MM_int & 
     IMAGE'DD_int & "." & IMAGE'( sssss_dur)) ; 

  New_line ;
  Put_line( To_string( time_unb_str)) ;

[Not compiled, so not sure if IMAGE’( sssss_dur) does the trick.]

You can customize this:

--  Time_display returns date & time, current or given.
--  E.g.: "2023/08/01  05:49:51.457"
--  Useful for a log file or for displaying a lengthy operation.
--
--  Test program in following comment:
--
--    with Ada.Text_IO, Time_display;
--    procedure Test is begin Ada.Text_IO.Put(Time_display);end;

with Ada.Calendar;

function Time_Display
  (T            : Ada.Calendar.Time := Ada.Calendar.Clock;
   Intra_Day    : Boolean           := True;
   Seconds      : Boolean           := True;
   Milliseconds : Boolean           := True)
  return String
is
  use Ada.Calendar;
  sdu : constant Day_Duration := Ada.Calendar.Seconds (T);
  type Sec_Int is range 0 .. 86_400;
  s : constant Sec_Int := Sec_Int (sdu - 0.5);
  m : constant Sec_Int := s / 60;
  --  + 100: trick for obtaining 0x
  sY    : constant String := Integer'Image  (Year (T));
  sM    : constant String := Integer'Image (Month (T) + 100);
  sD    : constant String := Integer'Image   (Day (T) + 100);
  shour : constant String := Sec_Int'Image  (m  /  60 + 100);
  smin  : constant String := Sec_Int'Image  (m mod 60 + 100);
  ssec  : constant String := Sec_Int'Image  (s mod 60 + 100);
  sfrac : constant String := Duration'Image (sdu - Duration (s));
  --
  function Optional_Milliseconds return String is
  begin
    if Milliseconds then
      return sfrac (sfrac'First + 2 .. sfrac'First + 5);
    else
      return "";
    end if;
  end Optional_Milliseconds;
  --
  function Optional_Seconds return String is
  begin
    if Seconds then
      return
        ':' & ssec (ssec'Last - 1 .. ssec'Last) &
        Optional_Milliseconds;
    else
      return "";
    end if;
  end Optional_Seconds;
  --
  function Optional_Intra_Day return String is
  begin
    if Intra_Day then
      return
        "  " &
        shour (shour'Last - 1 .. shour'Last) & ':' &
        smin (smin'Last - 1 .. smin'Last) & Optional_Seconds;
    else
      return "";
    end if;
  end Optional_Intra_Day;

begin
  return
    sY (sY'Last - 3 .. sY'Last) & '/' &   --  Not Year 10'000 compliant.
    sM (sM'Last - 1 .. sM'Last) & '/' &
    sD (sD'Last - 1 .. sD'Last) &
    Optional_Intra_Day;
end Time_Display;

If you’re looking for old public domain Ada code, grab the Walnut Creek Ada CD-ROM images on the Internet Archive. Most of the packages in those images came from the Public Ada Library, which was catalogued by the AJPO and served via FTP through the early 90s. Walnut Creek inherited that collection when the FTP sites shut down. The PAL FAQ should give you an idea of how it’s organized.

The Usenet archives are searchable back to 1982 and sometimes contain useful tips for early internet era Ada. Try sorting by date and use the “reverse” link at the bottom of the page.

I found this Calendar_Utilities code from 1990 that looks like it might do what you want. I wouldn’t call the use of 'Image attributes there a best practice, but it should work.

The Ada-95 version of PragmARC.Date_Handler has operations you can use to build such a string:

PragmARC.Date_Handler.Split
   (Date => Date, Year => Year, Month => Month, Day => Day, Hour => Hour, Minute => Minute, Seconds => Seconds);

Name := To_Unbounded_String (PragmARC.Date_Handler.Year_Image_Long (Year) &
                             PragmARC.Date_Handler.Month_Image_Numeric (Month) &
                             PragmARC.Date_Handler.Day_Image (Day) & '.' &
                             PragmARC.Date_Handler.Hour_Image_24 (Hour) & '.' &
                             PragmARC.Date_Handler.Minute_Image (Minute) & '.' &
                             PragmARC.Date_Handler.Seconds_Image (Seconds) );

Since your name is always the same length, I don’t know why you want an Unbounded_String.

1 Like

Thank you for the Walnut Creek link.

Thank you.

Name_unb_str is useful by which to add other file name qualifiers such as prefix directory and suffix file type for an OS-compliant file name path.

The idea is minimizing the incessant need to process unb_str as _str using injection everywhere of the 19-characters “To_unbounded_string” because Ada string implementation theory was so lame due to NYU hatred of Ada’s grown up older sister True BASIC born at Dartmouth in 1964.

Ada-Belgium distributed hundreds of copies of the Walnut Creek CD-ROMs at its events in the nineties and early nillies, when Internet connections and disk space was not so abundant as it is now.

Those CD-ROMs offered a convenient way to distribute the contents of the s.c. Ada and Software Engineering Library (ASE), the follow-up of the Public Ada Library (PAL). That Library was created and maintained by Richard (Rick) Conn, who also organized the successive CD-ROM versions that were produced by Walnut Creek.

A copy of the latest version of that 2 CD-ROM set, the s.c. Ada and Software Engineering Library Version 2 (ASE2), last updated October 2000, is still available on the Ada-Belgium site at https://people.cs.kuleuven.be/~dirk.craeynest/ada-belgium/archive/ase/.

(Note: this archive was provided for a long time via the site’s ftp-server; when ftp was no longer available, the ASE2 contents has been moved to the site’s web-server, but not thoroughly checked, so some of the contents might not be fully functional; nevertheless, we hope it might be useful for reference purposes…)

1 Like

Thanks for info, but I did not see any CD-image links to download.

There’s no CD-image to download. The given URL points to the contents that was copied from those 2 CDs, i.e. the Ada and Software Engineering Library Version 2 (ASE2), for online browsing. Hope this clarifies.