Version 1.2 of ais/ai-00351.txt

Unformatted version of ais/ai-00351.txt version 1.2
Other versions for file ais/ai-00351.txt

!standard 9.06(19)          03-12-08 AI95-00351/02
!class amendment 03-09-22
!status work item 03-09-22
!status received 03-09-22
!priority Medium
!difficulty Easy
!subject Time operations
!summary
This proposal adds a number of useful operations on Calendar.Time.
!problem
Calendar.Time is missing a number of operations commonly needed by applications.
First, there is no day-of-the-week function. It is often necessary to do a task on a particular day of the week (maintenance tasks in servers often are executed on Sundays when the load in minimal). Determining the day of the week for an Ada.Calendar.Time value is complex.
Second, determining the Hour:Minutes:Seconds representation of a time value is not trivial. This representation is needed for most output of time values. Similarly, values often need to be converted from Hours:Minutes:Seconds to time values.
Third, determining elapsed time is difficult if more than Duration'Last seconds have elapsed. This makes it more likely that Ada programs and libraries will fail if they run longer than anticipated. We've had profilers, loggers, and other components fail due to this shortcoming.
Fourth, displaying a time value is complex. This is needed not only in carefully formatted output, but also in logs and debugging code.
Finally, determining the UTC time is not possible. This is needed in many applications, such as internet communication. Since Ada does not define whether the time value represents UTC time, local time, or some other time, it isn't possible to use Calendar.Time in such applications.
!proposal
(See wording.)
!wording
Change Year_Number in 9.6(11):
subtype Year_Number is Integer range 1901 .. 2399;
Add the following to 9.6:
The following language-defined library packages exist:
package Ada.Calendar.Time_Zones is
-- Time zone manipulation:
type Time_Offset is range -1440 .. 1440;
Unknown_Zone_Error : exception;
function Local_Time_Offset (Date : in Time := Clock) return Time_Offset;
end Ada.Calendar.Time_Zones;
package Ada.Calendar.Arithmetic is
-- Arithmetic on days:
type Day_Count is range -366*(1+Year_Number'last - Year_Number'first) .. 366*(1+Year_Number'last - Year_Number'first);
procedure Difference (Left, Right : Time; Days : out Day_Count; Seconds : out Duration; Leap_Seconds : out Leap_Seconds_Count);
function "+" (Left : Time; Right : Day_Count) return Time;
function "+" (Left : Day_Count; Right : Time) return Time;
function "-" (Left : Time; Right : Day_Count) return Time;
function "-" (Left, Right : Time) return Day_Count;
end Ada.Calendar.Arithmetic;
with Ada.Calendar.Time_Zones; package Ada.Calendar.Formatting is
-- Day of the week:
type Day_Name is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);
function Day_of_Week (Date : Time) return Day_Name;
-- Hours:Minutes:Seconds access:
subtype Hour_Number is Natural range 0 .. 23; subtype Minute_Number is Natural range 0 .. 59; subtype Second_Number is Natural range 0 .. 59; subtype Second_Duration is Day_Duration range 0.0 .. 1.0; subtype Leap_Seconds_Count is Integer range -999 .. 999;
function Hour (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0) return Hour_Number;
function Minute (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0) return Minute_Number;
function Second (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0) return Minute_Number;
function Sub_Second (Date : in Time) return Second_Duration; Time_Zone : in Time_Zones.Time_Zone := 0) return Second_Duration;
function Seconds_Of (Hour : in Hour_Number; Minute : in Minute_Number; Second : in Second_Number := 0; Sub_Second : in Second_Duration := 0.0) return Day_Duration;
procedure Split (Seconds : in Day_Duration; Hour : out Hour_Number; Minute : out Minute_Number; Second : out Second_Number; Sub_Second : out Second_Duration);
procedure Split (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0; Year : out Year_Number; Month : out Month_Number; Day : out Day_Number; Hour : out Hour_Number; Minute : out Minute_Number; Second : out Second_Number; Sub_Second : out Second_Duration);
function Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number; Sub_Second : Second_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : in Time_Zones.Time_Zone := 0);
return Time;
function Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration; Leap_Second: Boolean := False; Time_Zone : in Time_Zones.Time_Zone := 0);
return Time;
procedure Split (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0; Year : out Year_Number; Month : out Month_Number; Day : out Day_Number; Hour : out Hour_Number; Minute : out Minute_Number; Second : out Second_Number; Sub_Second : out Second_Duration; Leap_Second: out Boolean);
procedure Split (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0; Year : out Year_Number; Month : out Month_Number; Day : out Day_Number; Seconds : out Day_Duration; Leap_Second: out Boolean);
-- Simple image and value: function Image (Date : Time; Include_Time_Fraction : in Boolean := False) return String;
function Value (Date : String) return Time;
function Image (Elapsed_Time : Duration; Include_Time_Fraction : in Boolean := False) return String;
function Value (Elapsed_Time : String) return Duration;
end Ada.Calendar.Formatting;
Type Time_Offset represents the number of minutes difference between the mplementation-defined timezone used by Ada.Calendar and another timezone. Subtracting this value from a time value yields the time for the timezone.
function Local_Time_Offset (Date : in Time := Clock) return Time_Offset; Returns, as a number of minutes, the difference between the implementation-defined timezone of the values of Calendar, and UTC time, at the time Date. if the timezone of the Calendar implementation is unknown, then Unknown_Zone_Error is raised.
Notes: The time in the time zone known as Greenwich Mean Time (GMT) is generally equivalent to UTC time.
The implementation-defined timezone used for type Time may be, but need not be, the local timezone. Local_Time_Offset always returns the difference between the implementation-defined timezone of package Calendar. If Local_Time_Offset does not raise Unknown_Zone_Error, UTC time can be safely calculated (within the accuracy of the underlying time-base).
AARM Notes: The Date parameter is needed to take into account time differences caused by daylight-savings time and other time changes.
Other timezones can be supported with a child package.
The accuracy of this routine is not specified; the intent is that the facilities of the underlying target operating system are used to implement it.
Subtracting Duration(Local_Time_Zone*60) from Clock provides the UTC time. In the US, for example, Time_Offset will generally be negative.
procedure Difference (Left, Right : Time; Days : out Day_Count; Seconds : out Duration; Leap_Seconds : out Leap_Seconds_Count); Returns the difference between Left and Right. Days is the number of days of difference, Seconds is the remainder seconds of difference, and Leap_Seconds is the number of leap seconds. if Left < Right, then Seconds <= 0.0, Days <= 0, and Leap_Seconds <= 0. Otherwise, all values are non-negative.
AARM Note: The number of days is calculated midnight-to-midnight. Leap_Seconds are not included in Seconds.
function "+" (Left : Time; Right : Day_Count) return Time; function "+" (Left : Day_Count; Right : Time) return Time;
Add a number of days to a time value. Time_Error is raised if the result is not representable as a value of type Time.
function "-" (Left : Time; Right : Day_Count)
return Time; Subtract a number of days from a time value. Time_Error is raised if the result is not representable as a value of type Time.
function "-" (Left, Right : Time) return Day_Count;
Subtract two time values, and return the number of days between them. This is the same value that Difference would return in Days.
function Day_of_Week (Date : Time) return Day_Name;
Returns the day of the week for Time. This is based on the Year, Month, and Day values of Time.
function Hour (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0) return Hour_Number; Returns the hour for Date, as appropriate the specified timezone.
function Minute (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0) return Minute_Number; Returns the minute within the hour for Date, as appropriate to the specified timezone.
function Second (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0) return Minute_Number; Returns the second within the hour and minute for Date, as appropriate to the specified timezone.
function Sub_Second (Date : in Time) return Second_Duration; Time_Zone : in Time_Zones.Time_Zone := 0) return Second_Duration; Returns the fraction of second for Date. (This has the same accuracy as Day_Duration), as appropriate to the specified timezone.
function Seconds_Of (Hour : in Hour_Number; Minute : in Minute_Number; Second : in Second_Number := 0; Sub_Second : in Second_Duration := 0.0) return Day_Duration; Returns a Day_Duration value for the Hour:Minute:Second.Sub_Second. This value can be used in Calendar.Time_Of as well as the argument to Calendar."+" and Calendar."-".
procedure Split (Seconds : in Day_Duration; Hour : out Hour_Number; Minute : out Minute_Number; Second : out Second_Number; Sub_Second : out Second_Duration); Split Seconds into Hour:Minute:Second.Sub_Second.
procedure Split (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0; Year : out Year_Number; Month : out Month_Number; Day : out Day_Number; Hour : out Hour_Number; Minute : out Minute_Number; Second : out Second_Number; Sub_Second : out Second_Duration); Split Date into its constituent parts (Year, Month, Day, Hour, Minute, Second, Sub_Second), relative to the specified timezone.
function Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number; Sub_Second : Second_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : in Time_Zones.Time_Zone := 0);
return Time; Returns a Time built from the date and time values, relative to the specified timezone. Time_Error is raised if Leap_Second is True, and Hour, Minute, and Second are not appropriate for a Leap_Second.
AARM Note: A leap second always occurs as midnight, and is 23:59:60 UTC in ISO notation. So, if the timezone is UTC, if any of Hour /= 23, Minute /= 59, or Second /= 59, then Time_Error should be raised. However, we do not say that, because other time zones will have different values for them.
function Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration; Leap_Second: Boolean := False; Time_Zone : in Time_Zones.Time_Zone := 0);
return Time; Returns a Time built from the date and time values, relative to the specified timezone. Time_Error is raised if Leap_Second is True, and Seconds is not appropriate for a Leap_Second.
procedure Split (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0; Year : out Year_Number; Month : out Month_Number; Day : out Day_Number; Hour : out Hour_Number; Minute : out Minute_Number; Second : out Second_Number; Sub_Second : out Second_Duration; Leap_Second: out Boolean); Split Date into its constituent parts (Year, Month, Day, Hour, Minute, Second, Sub_Second), relative to the specified timezone. Leap_Second is true if Date identifies a leap second.
procedure Split (Date : in Time; Time_Zone : in Time_Zones.Time_Zone := 0; Year : out Year_Number; Month : out Month_Number; Day : out Day_Number; Seconds : out Day_Duration; Leap_Second: out Boolean); Split Date into its constituent parts (Year, Month, Day, Seconds), relative to the specified timezone. Leap_Second is true if Date identifies a leap second.
function Image (Date : Time; Include_Time_Fraction : in Boolean := False) return String; Returns a string form of the Date. The format is "Year-Month-Day Hour:Minute:Second", where each value other than Year is a 2 digit form of the value of the functions defined in Calendar and Calendar.Formatting, including a leading '0', if needed. Year is a 4 digit value. if Include_Time_Fraction is True, and Sub_Seconds*100 is suffixed to the string as a 2 digit value following a '.'.
AARM Note: The Image provides a string in ISO 8601 format, the international standard time format. Alternative representations allowed in ISO 8601 are not supported here.
ISO 8601 allows 24:0:0 for midnight; and a seconds value of 60 for leap seconds. These are not allowed here (the routines mentioned above cannot produce those results).
function Value (Date : String) return Time; Returns a Time value for the image given as Date. The string should be formatted as described for Image. Constraint_Error is raised if the function cannot interpret the given string as a Time value.
AARM Note: We do not require that the given string is in exactly the form returned by Image, as that would complicate the definition and implementation for no value. For instance, the absence of leading zeros shouldn't prevent that string from being decoded. If the implementation has access to a complete ISO 8601 decoding routine, we certainly want to let it be used. But we do require that any string that Image can produce be convertible here without raising Constraint_Error.
function Image (Elapsed_Time : Duration; Include_Time_Fraction : in Boolean := False) return String; Returns a string form of the The format is "Hours:Minute:Second", where each value is a 2 digit form of the value, including a leading '0', if needed. if Include_Time_Fraction is True, and Sub_Seconds*100 is suffixed to the string as a 2 digit value following a '.'.
AARM Note: This cannot be implemented (directly) by calling Ada.Calendar.Formatting.Split, since it may be out of the range of Day_Duration, and thus the number of hours may be out of the range of Hour_Number.
function Value (Elapsed_Time : String) return Duration; Returns a Duration value for the image given as Elapsed_Time. The string should be formatted as described for Image. Constraint_Error is raised if the function cannot interpret the given string as a Duration value.
Implementation Advice
An implementation should support leap seconds if the target system supports them. If leap seconds are not supported, functions returning leap seconds should return zero, and Time_Of should raise Time_Error if Leap_Second is true.
!discussion
The proposal is taken from the operations provided in GNAT.Calendar and Claw.Time.
The packages are defined as children of Ada.Calendar. While the operations could be added to Ada.Calendar itself, doing so would potentially add ambiguities to many existing programs. (There are many new overloadings of Split and Time_Of.) In addition, while Ada.Calendar may be included in many programs, these operations are less likely to be needed and their overhead should not burden existing programs. The package should be a child, and not a stand-alone package, so that its implementation can take advantage of the internal representation of type Time.
These operations are most valuable for wall clock time and date values. Thus, we have chosen not to provide similar operations for Ada.Real_Time.
The rather vague descriptions of the Hour:Minute:Second:Sub_Second functions is similar to the existing description of Ada.Calendar.
This package provides mechanisms to handle leap seconds. This is critical if the target is connected to a time-base. Otherwise, programs could potentially wait too long when a leap second is inserted.
We have chosen to keep the invariant that there are 86400.0 seconds in a day. This is important, since existing Ada programs assume that, and changing it could break many programs. Therefore, we have adopted the model that Split ignores leap seconds - it will return 23:59:59 for a leap second. Similarly, "-" ignores leap seconds. The difference between 23:00:00 and 01:00:00 the next day is always 7200.0 seconds. Difference will return a count of leap seconds in case that information is needed.
The time of day of a leap second depends on the time zone in use. (They always happen at midnight UTC). Thus, they can occur at any local time of day.
The result of procedure Difference is a bit weird. We define the remainder this way so that the Seconds value would be the same as the result "-" if the two times are less than one day apart.
Image is defined to provide a human readable output compatible with ISO 8601. The ISO 8601 form was used to allow us to provide a simple, useful form without providing extensive formatting and localization facilities. In this sense, Image is similar to 'Image of types: a quick and useful image string where format is not critical.
The format has been chosen to maximize human readability without compromising machine readability. The more compact ISO forms are not used here.
More complex formatting routines have been suggested. These were not included in the proposal because they are complex or lack capability for non-English-speaking locales.
Three kinds of formatting routines have been proposed. The simplest is the 'many default parameter form'. This would look similar to the Image function, just with many more parameters. Claw.Time contains a function like this. However, experience with the Claw function shows that not only is the large number of parameters daunting (even to the designer!), but it still lacks in flexibility (limited number of orderings, no non-English words). Renamings of the function help in ease of use, but nothing can help the flexibility.
A second approach is the generic signature & generic package scheme. This provides good localization, but at the cost of a generic signature package. The good news is that this package would not change often, and a predefined one could be provided for English and other common locales. But using it still requires an instantiation with many parameters. This is similar to the renaming, and it too lacks in flexibility in some cases.
A third approach is the format string approach. GNAT provides a package like this; Windows provides a function like this in its API. This provides a lot of flexibility in ordering, but little in terms of localization. (Windows does localization elsewhere.) Moreover, it would require several pages of RM description.
These possibilities are all quite complex, none covers everything desired, and none would really allow a Value function. Thus, we do not provide a formatted output function, preferring instead to provide the building blocks (such as the Hour:Minute:Second splitter) which can be used to write whatever is needed.
Ada 95 defines the results of Time_Of and Split relative to an "implementation-defined timezone". We extend this by providing a Time_Offset type, and providing a function to return the offset of the "implementation-defined timezone" to UTC time. We also provide defaulted parameters to Split and Time_Of so that a specified timezone can be used with those routines.
Supporting more timezones other than local and UTC is much more difficult. An implementation can add such support with child packages.
We expect the timezone functions will use the underlying operating system facilities. If those are inaccurate (say determining the starting date of daylight savings time in 1960 in Italy), we do not expect the Ada implementation to try to correct them.
The upper bound of the subtype Ada.Calendar.Year_Number is increased in order to eliminate Ada's Y2.1K problem. The lower bound is unchanged, because a lot of Ada 95 code uses Year_Number'First to represent No_Time or Unknown_Time, and dates in the distant past aren't usually interesting. The change in range is purposely kept small, so that we are not requiring a lot of extra bits in representations of Ada.Calendar.Time.
--!corrigendum 9.06(00)
!ACATS test
Test(s) need to be constructed.
!appendix

From: Robert I. Eachus
Sent: Thursday, June 5, 2003  12:36 PM

Tucker Taft wrote:
> While we are at it, I might argue for Boolean_Text_IO
> and Duration_Text_IO, because these are perhaps even
> more appropriate than Integer_Text_IO, since as Robert
> points out, using Integer is generally "bad form,"
> while using Boolean and Duration seems eminently reasonable.

Duration_IO would be a definite plus.  Boolean_IO would IMHO be a waste
of effort, similar to instantiating Enumeration_IO for Character.  Maybe
not quite as bad, but still something you don't want beginners to be
misled by.

Of course the real need is for a simple to use Time_IO package.  The
problem is internationalization.  I think the right solution would be to
have a package Ada.Time_IO with lots of customization options, and a
dozen or so pre-instantiations such as Ada.Time_IO.American,
Ada.Time_IO.Engish, Ada.Time_IO.French, Ada.Time_IO.Spanish,
Ada.Time_IO.French_Canadian and so on.  (And yes, the right way to do
this is with about twenty-three generic parameters including the names
of the months, the names of the weekdays and so on.)

Might as well put a straw man out there. A trivial alternative would be
to make Ada.Time_IO an empty package with Generic_Time_IO as a child.

with Ada.Calendar; use Ada.Calendar;
with Ada.Text_IO;
package Ada.Time_IO is

    generic

      Include_Day: in Boolean := True;
      Include_Time: in Boolean := True;
      Twentyfour_Hour_Clock : in Boolean := False;
      Leading_Zero_In_Hour : Boolean := False;
      Morning_Indicator: in String := "AM";
      Evening_Indicator: in String := "PM";
      Include_Seconds: in Boolean := True;
      Fractional_Digits: in Natural := 3;
      Time_First: in Boolean := False;
      Numeric_Month: in Boolean := False;
      Month_Before_Day: in Boolean := True;
      Punctuation_After_Day: in Boolean := True;
      Punctuation_Character: in Character := ',';

      Sunday: in String := "Sunday";
      Monday: in String := "Monday";
      Tuesday: in String := "Tuesday";
      Wednesday: in String := "Wednesday";
      Thursday: in String := "Thursday";
      Friday: in String := "Friday";
      Saturday: in String := "Saturday";

      January: in String := "January";
      February: in String := "February";
      March: in String := "March";
      April: in String := "April";
      May: in String := "May";
      June: in String := "June";
      July: in String := "July";
      August: in String := "August";
      September: in String := "September";
      October: in String := "October";
      November: in String := "November";
      December: in String := "December";

    package Generic_Time_IO is

      function Date_Time (As_Of: in Time := Clock) return String;

      procedure Put_Date_Time(As_Of: in Time := Clock);

      procedure Put_Date_Time(File: in Ada.Text_IO.File_Type;
                              As_Of: in Time := Clock);

      function Date (As_Of: in Time := Clock) return String;

      procedure Put_Date (As_Of: in Time := Clock);

      procedure Put_Date(File: in Ada.Text_IO.File_Type;
                         As_Of: in Time := Clock);

      function Time_Of_Day (As_Of: in Time := Clock) return String;

      procedure Put_Time(As_Of: in Time := Clock);

      procedure Put_Time(File: in Ada.Text_IO.File_Type;
                         As_Of: in Time := Clock);

    end Generic_Time_IO;

end Ada.Time_IO;

****************************************************************

From: Randy Brukardt
Sent: Thursday, June 5, 2003  3:40 PM

> Of course the real need is for a simple to use Time_IO package.  The
> problem is internationalization.  I think the right solution
> would be to
> have a package Ada.Time_IO with lots of customization options, and a
> dozen or so pre-instantiations such as Ada.Time_IO.American,
> Ada.Time_IO.Engish, Ada.Time_IO.French, Ada.Time_IO.Spanish,
> Ada.Time_IO.French_Canadian and so on.  (And yes, the right way to do
> this is with about twenty-three generic parameters including the names
> of the months, the names of the weekdays and so on.)
>
> Might as well put a straw man out there. A trivial alternative would be
> to make Ada.Time_IO an empty package with Generic_Time_IO as a child.

I agree that a Time_IO is needed, but it's not the only Time enhancement
that's needed. We provided a number of missing features in Claw.Time (some
of which are provided in GNAT's libraries as well):

 -- Day-of-the week;
 -- Duration splitters/constructors (to Hours/Minutes/Seconds, which is
deceptively easy to write incorrectly. The Gnat version I looked at was
implemented incorrectly and would give the wrong answer in some cases);
 -- Math with a wider range than Duration, for calculating elapsed time and
operation launch times in programs that are going to run more than one day.
Consider an operation that runs once a week, or a program that reports its
"Up time" periodically. (I did this by adding a bound of operations on
"Day_Count" [a number of days], but that was not completely satisfactory.
Perhaps allowing the number of seconds to be expressed as a Long_Float would
have been better.;
 -- Basic time-zone functions (To_UTC_Time, To_Local_Time);
 -- And a function Time_Image.

For Time_Image, I used a set of function parameters to control the
representation (getting the localization info from Windows). It still wasn't
that satisfactory, which is one of the main reasons I never proposed a set
of Time packages.

I found that it was necessary to rename it (to change the defaults) almost
every time it was used, because so many different formats are needed. It
hardly ever has been the case that I used the existing defaults (because it
had too much precision, or too little, or the format was specified by an
external force [such as the times in HTTP]). That, I suppose, argues that
the generic approach isn't that bad.

One thing that is clearly missing from Robert's suggestion is a way to print
elapsed times, which is a common requirement. You can do so as
Duration'Image, but usually you'd rather have Hours:Minutes:Seconds (and
again, you may need more than one day here, so it often is
Days:Minutes:Seconds).

Of course, all of the this stuff can be built yourself, or scarfed off of
the Internet, but it is so common that it really should be in the standard.
(The same arguments that applied to Ada.Directories apply here, including
availablity to every C programmer.)

****************************************************************

From: Robert Dewar
Sent: Thursday, June 5, 2003  4:51 PM

here are packages that GNAT provides:

(I do not agree with the 23 generic parameters approach, this seems a perfect
example of letting best be the enemy of good :-)

------------------------------------------------------------------------------
--                                                                          --
--                         GNAT RUN-TIME COMPONENTS                         --
--                                                                          --
--                G N A T . C A L E N D A R . T I M E _ I O                 --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--            Copyright (C) 1999-2003 Ada Core Technologies, Inc.           --
--                                                                          --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
-- apply solely to the  contents of the part following the private keyword. --
--                                                                          --
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT 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  distributed with GNAT;  see file COPYING.  If not, write --
-- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
-- MA 02111-1307, USA.                                                      --
--                                                                          --
-- As a special exception,  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  GNU  General  Public  License.  This exception does not --
-- however invalidate  any other reasons why  the executable file  might be --
-- covered by the  GNU Public License.                                      --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

--  This package augments standard Ada.Text_IO with facilities for input
--  and output of time values in standardized format.

package GNAT.Calendar.Time_IO is

   Picture_Error : exception;
   --  Exception raised for incorrect picture

   type Picture_String is new String;
   --  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 :
   --
   --          %    a literal %
   --          n    a newline
   --          t    a horizontal tab
   --
   --          Time fields:
   --
   --          %H   hour (00..23)
   --          %I   hour (01..12)
   --          %k   hour ( 0..23)
   --          %l   hour ( 1..12)
   --          %M   minute (00..59)
   --          %p   locale's AM or PM
   --          %r   time, 12-hour (hh:mm:ss [AP]M)
   --          %s   seconds  since 1970-01-01  00:00:00 UTC
   --                (a nonstandard extension)
   --          %S   second (00..59)
   --          %T   time, 24-hour (hh:mm:ss)
   --
   --          Date fields:
   --
   --          %a   locale's abbreviated weekday name (Sun..Sat)
   --          %A   locale's    full   weekday   name,    variable   length
   --                  (Sunday..Saturday)
   --          %b   locale's abbreviated month name (Jan..Dec)
   --          %B   locale's    full    month    name,   variable    length
   --                  (January..December)
   --          %c   locale's date and time (Sat Nov 04 12:02:33 EST 1989)
   --          %d   day of month (01..31)
   --          %D   date (mm/dd/yy)
   --          %h   same as %b
   --          %j   day of year (001..366)
   --          %m   month (01..12)
   --          %U   week number  of year with  Sunday as first day  of week
   --                  (00..53)
   --          %w   day of week (0..6) with 0 corresponding to Sunday
   --          %W   week number  of year with  Monday as first day  of week
   --                  (00..53)
   --          %x   locale's date representation (mm/dd/yy)
   --          %y   last two digits of year (00..99)
   --          %Y   year (1970...)
   --
   --          By default,  date pads numeric fields with zeroes.  GNU date
   --          recognizes the following nonstandard numeric modifiers:
   --
   --          -    (hyphen) do not pad the field
   --          _    (underscore) pad the field with spaces
   --
   --  Here are some GNAT extensions to the GNU Date specification:
   --
   --          %i   milliseconds (3 digits)
   --          %e   microseconds (6 digits)
   --          %o   nanoseconds  (9 digits)

   ISO_Date : constant Picture_String;
   --  This format follow 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;
   --  This format is the common US date format: "MM/DD/YY",
   --  month and day number, two digits year separated by slashes.

   European_Date : constant Picture_String;
   --  This format is the common European date format: "DD/MM/YY",
   --  day and month number, two digits year separated by slashes.

   function Image
     (Date    : Ada.Calendar.Time;
      Picture : Picture_String)
      return    String;
   --  Return Date as a string with format Picture.
   --  raise Picture_Error if picture string is wrong

   procedure Put_Time
     (Date    : Ada.Calendar.Time;
      Picture : Picture_String);
   --  Put Date with format Picture.
   --  raise Picture_Error if picture string is wrong

private
   ISO_Date      : constant Picture_String := "%Y-%m-%d";
   US_Date       : constant Picture_String := "%m/%d/%y";
   European_Date : constant Picture_String := "%d/%m/%y";

end GNAT.Calendar.Time_IO;

****************************************************************

From: Robert I. Eachus
Sent: Thursday, June 5, 2003  6:53 PM

> (I do not agree with the 23 generic parameters approach, this seems a perfect
> example of letting best be the enemy of good :-)

My strawman actually has 31 parameters.  Instantiating it with other
than named parameter association would be painful.

But the intent was to have the generic present, and a dozen or so
children that deal with the necessary localizations.  That way we
wouldn't have various countries arguing about the "correct" way to do
things, just providing instantiations.

As for the GNAT packages I have used them on occasion. As with my
proposal the problem is that the user doesn't want to deal with all the
syntax and semantic necessary to provide choices.  If I were to propose
the GNAT packages for standardization, the first thing I would do would
be increase the number of constant formats  and hide the complete
generality--really documentation in the GNAT version--from 'normal'
users.  No reason for it not to be there for users who insist on doing
their own layout.  But users who just want to print a date shouldn't
have to spend an hour or more figuring out how to do it.

 From my point of view though, the painful part is days of the week.  I
think it is almost criminal that Ada.Calendar doesn't have this function:

type Weekday is (Sunday, Monday, Tuesday, Wendesday, Thurday, Friday,
Saturday);

function Day_of_Week (T: in Time) return Weekday;

I have code for the above, Dave Emery has also written a version, etc.
But it should be in the standard library. The implementation is trivial
for the format of many hardware system clocks, but a hardware
independent version is half a page of code.

****************************************************************

From: Randy Brukardt
Sent: Thursday, June 5, 2003  8:55 PM

I don't like the 23 generic (or non-generic, in the Claw case) much, either.

But I don't see much to recommend the GNAT package, either. (Indeed, I
studied this approach when I create Claw.Time; Windows has a very similar
time formatting routine.)

I didn't use it because the formatting strings aren't at all Ada-like:
they're case-sensitive (at least picture strings in Annex F aren't
case-sensitive), and they look like C. In addition, we have a problem if we
tried to use this in the Ada standard, because we don't have a Locale (which
this package leans on heavily). Perhaps we need a Locale, but if Time_IO is
a can of worms, Locale is a dump truck of worms. I don't think we have the
time to do it.

As I said previously, I don't think that the 23 parameter approach works,
either. (Based on my experience with the routine in Claw.Time.)

What we need, of course is a Q&D routine with little or control on the
output format at all. After all, the primary need for these routines is for
debugging output. If they happen to provide some specific format that
someone needs, great, but that shouldn't be the focus.

For formatting beyond that, it would be much better to give the users a
proper set of splitters (Hour/Minute/Second + Day_of_the_Week) and let them
format it themselves.

But I don't have much hope that we can agree on that, so we necessarily will
end up with something that tries to be all things to all people -- a quest
that is doomed and will be a major time sink.

****************************************************************

From: Robert I. Eachus
Sent: Thursday, June 5, 2003  9:08 PM

That's why I thought the (actually) 31 parameter generic was the way to
go.  At least 99% of the users will with Ada.Time_IO.American,
Ada.Time_IO.English, Ada.Time_IO.French, or whatever and never see the
ugly generic they instantiate.  As for those who want to spend time
arguing for another standard instance, they can either write it or go
away.  Some of those instances will make it into the standard, and those
that don't will still be available to those who wrote them.

As for me, I have another project I am working on now.  But I can go
ahead and implement the generic, and either put up my own web site or
get someone who already runs one to collect generic instantiations.  I
don't know what the names of the months are in Polish or Hungarian, and
I don't care.  But someone who does can put together an instance in less
than an hour.

****************************************************************

From: Robert Dewar
Sent: Thursday, June 5, 2003  10:09 PM

> But I don't have much hope that we can agree on that, so we necessarily will
> end up with something that tries to be all things to all people -- a quest
> that is doomed and will be a major time sink.
                                     ^^^^

:-)

****************************************************************

From: Pascal Leroy
Sent: Wednesday, September 24, 2003  3:21 AM

[This is part of a private conversation on RFC 1123 and ISO 8601 between Randy
and Pascal; it's included here for the various web references. - ED]

> I chose it simply because it is useful in practice. It's the
> only standard time format that I've ever come across in
> practice. I've never heard of ISO 8601; I don't doubt that it
> is easier to use. (I would have preferred an all-numeric
> format for obvious reasons). Is there a reference to it that
> doesn't cost $500?

See http://www.cl.cam.ac.uk/~mgk25/iso-time.html.  ISO 8601 is the
format recommended by the W3C consortium.  See
http://www.w3.org/TR/NOTE-datetime and http://www.w3.org/Protocols/Time/
for details and links.

> First of all, RFC 1123 is trivial to parse: all the fields
> (including the spaces) are
> fixed width. That is, it isn't parsed at all - you just take
> the appropriate slices and stuff them into Integer'Value.

This is not quite true as some of the fields are optional (time fraction
and day of week) and the month may be either numerical or alphabetical.
So a bit more analysis than just "taking the appropriate slices" is
needed (I suppose that you want Value to be able to parse all strings
that can be produced by Image).  But this point is unimportant, as
writing the implementation of Value cannot take more than one hour
anyway.

I am more concerned by the fact that the output format doesn't sort.  I
have found in many practical instances that using the ISO date format
makes things much easier because you get sorting for free (e.g. in
filenames or log records).

> Second, it certainly isn't dependent on US culture at all.
> This would be a very unusual date format to see in a US
> document. Certainly, it is dependent on English (for the days
> of week and month names), but the order of the items is wrong
> for the US (it is always month first around here).

True.  However the thing that I found amusing is the description of
timezones in RFC 822 (as you realize the time format in RFC 1123 is
really the same as that in RFC 822, except for a few details like "oh,
yeah, the year 2000!").  The timezones supported by RFC 822 are UT, GMT,
EST, EDT, CST, CDT, MST, MDT, PST, PDT and no others.  If that's not
US-centric, then what is?  (I realize that you don't include the
timezone in your format, and wisely so, because a timezone can really
have any name you like.)

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM


Firstly a tpyo:

    function Day_of_Week (Time : Time) return Days_in_Week_Type;

should be:

    function Day_of_Week (T : Time) return Days_in_Week_Type;

(can't have parameter name matching the parameter type name)
and shouldn't:

    subtype Second_Duration is Day_Duration range 0.0 .. 1.0;

be:

    subtype Second_Duration is Day_Duration
       range 0.0 .. Day_Duration'Pred (1.0);

as a value of '1.0' should really be added to the 'Second' count
not Sub_Second.

****************************************************************

From: Thomas Wolf
Sent: Friday, October 17, 2003  5:50 AM

Some more comments:

1. Week Start
-------------

The proposed package Ada.Calendar.Operations has

    -- Day of the week:

    type Days_in_Week_Type is
      (Sunday, Monday, Tuesday, Wednesday, Thursday,
       Friday, Saturday);

ISO-8601 defines the week to start on Monday. I believe if
Ada 0X (also an ISO-standard) should define it's representation
for day-in-week in accordance with ISO 8601, i.e.

    type Days_in_Week_Type is
      (Monday, Tuesday, Wednesday, Thursday,
       Friday, Saturday, Sunday);

While it may be true that some algorithms such as Zeller's
congruence for computing the day of the week have orginally
been developed with 0=sunday, 1=monday, it is trivial to
map their results onto an ordering where
Days_In_Week_Type'First = Monday.

It's not a big issue, but I think an ISO standard for Ada 0X
should not gratuitously introduce an ordering different from
the already existing ISO 8601. (The situation for e.g. C may
have been different, for ISO 8601 didn't exist -- I think so,
at least -- when the C89 was put together.)

2. Images
---------

As for date/time images, I'd suggest that the ARG also considers
following the ISO 8601 format.

Furthermore, I'm personally convinced that image functions that
include a textual day or month representation like "Mon" or "Dec"
are a bad idea. Day and month names are highly locale-specific
(or, if you prefer, language-specific). Better leave that to
the applications using this. (And given a Day_Of_Week function,
it's no big deal to generate any string image one might want for
any Day_Of_Week_Type value.)

Just as an idea: in my own utility packages, I have

   type Date_Format is (DMY, MDY, YMD);
   --  Day-Month-Year, Month-Day-Year, Year-Month-Day.

   function Image
     (Date      : in Ada.Calendar.Time;
      Format    : in Date_Format := YMD;
      Separator : in String      := "-";
      Padding   : in Boolean     := True)
     return String;
   --  Individual date components are separated by the given
   --  Separator.
   --
   --  If Padding is true, day and month numbers smaller than
   --  10 have a leading zero.
   --
   --  Examples: (assuming Padding = True)
   --
   --  03-OCT-2001 yields
   --
   --  Format = MDY, Separator = "/"   ==> 10/03/2001    (English)
   --  Format = DMY, Separator = ". "  ==> 03. 10. 2001  (German)
   --  Format = YMD, Separator = "-"   ==> 2001-10-03    (ISO 8601)
   --  Format = YMD, Separator = ""    ==> 20011003
   --
   --  With the default arguments, the function returns the ISO 8601
   --  date representation.

(I also have individual Image functions for Ada.Calendar.Day_Duration,
producing HH:MM:SS[.Fraction], for I find it useful to keep date and
time formatting separate.)

3. Extending the range of Ada.Calendar.Time
-------------------------------------------

AI-351 mentions in its discussion section

> [Open issue: Should we increase the year range in Calendar to
> 1600..2400? This would potentially require two more bits in the
> Time value. 1600 is used as the lower bound, as current calendar
> wasn't used universally until around that date. But it would
> avoid Ada's own Y2.1K problem.]

I suppose "current calendar" means "Gregorian calendar". Well,
that one wasn't used "universally" (let's restrict that to
planet Earth :-) until way later. For the gory details of when
which region/country switched from the Julian to the Gregorian
calendar, see the Calendar FAQ at
<http://www.tondering.dk/claus/calendar.html>, question 2.2.4.

But even without looking there: Russia changed as late as 1918!

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  6:11 AM

One other question...

why extend via a child package rather than just adding the
new routines to the existing Ada.Calendar package?

****************************************************************

From: Jean-Pierre Rosen
Sent: Friday, October 17, 2003  6:18 AM

From: "Thomas Wolf" <twolf@acm.org>
> ISO-8601 defines the week to start on Monday. I believe if
> Ada 0X (also an ISO-standard) should define it's representation
> for day-in-week in accordance with ISO 8601, i.e.

I definitely support this. Many (and I believe most) countries start
weeks on Monday.

> 2. Images
> ---------
As 0.02Euros input, here is what I use for my own Image/Value of time:

   -- Syntax of format strings:
   -- %Y : Year number (4 digits!)
   -- %M : Month number
   -- %D : Day number
   -- %h : Hours
   -- %m : minutes
   -- %s : seconds
   -- %c : hundredth of second (cents :-)
   -- %<char> : <char> unchanged. Useful for %%
   -- Any other character is copied verbatim on output, and
   -- must be matched exactly on input.
   -- A misformed input string to Value raises Time_Error.
   -- Value is somewhat tolerant: if the input string is to short,
defaults
   -- are taken for the missing fields (taken from the current date for
the
   -- date, and 0:0:0.0 for the time).
   -- Extra spaces are allowed in front of numeric values.
   -- In any case, it is guaranteed that a string produced by Image with
a
   -- format can be parsed by Value with the same format.
   Compact  : constant String := "%Y%M%D%h%m%s%c";
   European : constant String := "%D/%M/%Y %h:%m:%s";
   British  : constant String := "%M/%D/%Y %h:%m:%s";
   ISO      : constant String := "%Y/%M/%D %h:%m:%s.%c";

  function Image (Item : Time;   Format : String) return String;
  function Value (Item : String; Format : String) return Time;


Moreover, I found it useful to add these:
  function Min (Left, Right : Time) return Time;
  function Max (Left, Right : Time) return Time;

(And I can provide a free implementation of these functions to whoever
needs them).

****************************************************************

From: Robert A. Duff
Sent: Friday, October 17, 2003  8:03 AM

Thomas Wolf says:

> ...ISO-8601 defines the week to start on Monday.

I know, and I find that annoying.  I mean, the convention that the week
starts on Sunday predates ISO by thousands of years, and this fact is
well documented.  When (and why) did various countries switch?

> As for date/time images, I'd suggest that the ARG also considers
> following the ISO 8601 format.

Yes, I agree with *that*.

> Furthermore, I'm personally convinced that image functions that
> include a textual day or month representation like "Mon" or "Dec"
> are a bad idea.

I don't agree.  Of course, as an English speaker, I'm biased.
But we spell "begin" and "Put_Line" and "True" and everything else in
English.  Why should days of the week be different?

Unless Ada goes all the way to supporting locales (which seems like too
much), we should just use "Sunday", etc.

> AI-351 mentions in its discussion section
>
> > [Open issue: Should we increase the year range in Calendar to
> > 1600..2400? This would potentially require two more bits in the
> > Time value. 1600 is used as the lower bound, as current calendar
> > wasn't used universally until around that date. But it would
> > avoid Ada's own Y2.1K problem.]
>
> I suppose "current calendar" means "Gregorian calendar". Well,
> that one wasn't used "universally" (let's restrict that to
> planet Earth :-) until way later. For the gory details of when
> which region/country switched from the Julian to the Gregorian
> calendar, see the Calendar FAQ at
> <http://www.tondering.dk/claus/calendar.html>, question 2.2.4.
>
> But even without looking there: Russia changed as late as 1918!

I don't understand the issue.  Who cares when and where our current
calendar was adopted.  It's *our* calendar, and we can use it perfectly
well to talk about dates thousands of years ago (or in 1917).  The fact
that the people living thousands of years ago used a different calendar
(or, if you go back far enough, had no idea what a calendar *is*) seems
irrelevant to me.  What am I missing?

****************************************************************

From: Tucker Taft
Sent: Friday, October 17, 2003  8:29 AM

The ARG came up with almost all of the same suggestions
at its review of this AI at our recent ARG meeting.  A new
version will be forthcoming shortly that uses ISO 8601,
drops all textual aspects in the image/value functions,
etc.

****************************************************************

From: Robert A. Duff
Sent: Friday, October 17, 2003  9:26 AM

Did they also vote that Boolean'Image should return a locale-dependent
result?!

****************************************************************

From: Tucker Taft
Sent: Friday, October 17, 2003  10:25 AM

Non.   ;-)

****************************************************************
From: Thomas Wolf
Sent: Friday, October 17, 2003  8:54 AM

On 17 Oct 2003 at 9:03, Bob Duff wrote:

> Thomas Wolf says:
>
> > ...ISO-8601 defines the week to start on Monday.
>
> I know, and I find that annoying.  I mean, the convention that the week
> starts on Sunday predates ISO by thousands of years, and this fact is
> well documented.  When (and why) did various countries switch?

Is this relevant? On which day a week starts in real life is a highly
subjective matter. ISO has defined something which at least is not
complete nonsense (they didn't define, say, Thursday to be the start
of a week). So why should Ada depart from the definition given in
another ISO standard? (BTW, I'd have to look this up, but doesn't the
ISO week number also depend on the day defined to be the start of the
week?)

> > As for date/time images, I'd suggest that the ARG also considers
> > following the ISO 8601 format.
>
> Yes, I agree with *that*.
>
> > Furthermore, I'm personally convinced that image functions that
> > include a textual day or month representation like "Mon" or "Dec" are
> > a bad idea.
>
> I don't agree.  Of course, as an English speaker, I'm biased.
> But we spell "begin" and "Put_Line" and "True" and everything else in
> English.  Why should days of the week be different?

Juat to avoid any confusion: I was writing about the contents of the
string generated by Image, not about the fact that the enumeration
literals are spelled using the English day names.

> Unless Ada goes all the way to supporting locales (which seems like too
> much), we should just use "Sunday", etc.

As the spelling of the enumeration literal, yes. But an image function
producing strings containing "Sunday" or "Sun" will not be very helpful
wherever the string representation should be in some other language.

I believe one would be better off with an Image function that didn't
include day (or month) names in the generated string and have an
application add or insert the appropriate strings in the appropriate
lanugages.

I'm not suggesting Ada should support locales.

> > AI-351 mentions in its discussion section
> >
> > > [Open issue: Should we increase the year range in Calendar to
> > > 1600..2400? This would potentially require two more bits in the Time
> > > value. 1600 is used as the lower bound, as current calendar wasn't
> > > used universally until around that date. But it would avoid Ada's
> > > own Y2.1K problem.]
> >
> > I suppose "current calendar" means "Gregorian calendar". Well,
> > that one wasn't used "universally" (let's restrict that to
> > planet Earth :-) until way later. For the gory details of when
> > which region/country switched from the Julian to the Gregorian
> > calendar, see the Calendar FAQ at
> > <http://www.tondering.dk/claus/calendar.html>, question 2.2.4.
> >
> > But even without looking there: Russia changed as late as 1918!
>
> I don't understand the issue.  Who cares when and where our current
> calendar was adopted.  It's *our* calendar, and we can use it perfectly
> well to talk about dates thousands of years ago (or in 1917).  The fact
> that the people living thousands of years ago used a different calendar
> (or, if you go back far enough, had no idea what a calendar *is*) seems
> irrelevant to me.  What am I missing?

Maybe the author of the AI knows. I just mentioned this because I don't
understand the reasoning in the sentence "1600 is used as the lower
bound, as [the] current calendar wasn't used universally until around
that date.", which is not mine, but is taken verbatim from the AI.
Hence I pointed out that this reasoning is bogus. So, why 1600?

****************************************************************

From: Robert A. Duff
Sent: Friday, October 17, 2003  9:58 AM

Thomas Wolf said:

> On 17 Oct 2003 at 9:03, Bob Duff wrote:
>
> > Thomas Wolf says:
> >
> > > ...ISO-8601 defines the week to start on Monday.
> >
> > I know, and I find that annoying.  I mean, the convention that the week
> > starts on Sunday predates ISO by thousands of years, and this fact is
> > well documented.  When (and why) did various countries switch?
>
> Is this relevant? On which day a week starts in real life is a highly
> subjective matter. ISO has defined something which at least is not
> complete nonsense (they didn't define, say, Thursday to be the start
> of a week). So why should Ada depart from the definition given in
> another ISO standard?

Why should ISO depart from a definition that dates back thousands of
years?  Grr.  If ISO defines the "North Pole" to be in Antarctica,
should we all obey?

I suppose you're right, though -- Ada pretty much has to obey ISO on
the weekday point.  Grumble.

I'm still curious to know which countries think that Monday is the first
day, and when they started thinking that, and why.  Anybody know?
And was ISO following their lead, or the other way around?

(By the way, in the U.S., the "weekend" means "Saturday and Sunday",
even though Sunday is not at the "end".  Strange.)

>... (BTW, I'd have to look this up, but doesn't the
> ISO week number also depend on the day defined to be the start of the
> week?)

Probably.

> Juat to avoid any confusion: I was writing about the contents of the
> string generated by Image, not about the fact that the enumeration
> literals are spelled using the English day names.

Yes, I understood that.  But given the existence of (for example)
Boolean'Image, there is no law saying "Ada shall not have predefined
stuff that prints out messages in English".

It would be great if Ada could support Internationalization, and support
it well.  But that's too hard (I think we all agree), especially since
"do it well" probably means fitting in well with
operating-system-dependent support for locales.  Given that, it seems
silly to forbid the standard from having something that's useful for at
least *some* programs.

But it's not important, and I don't care much one way or the other,
and I'll shut up and quit arguing about it.

> I'm not suggesting Ada should support locales.

Yes, I understood that, too.

> Maybe the author of the AI knows. I just mentioned this because I don't
> understand the reasoning in the sentence "1600 is used as the lower
> bound, as [the] current calendar wasn't used universally until around
> that date.", which is not mine, but is taken verbatim from the AI.
> Hence I pointed out that this reasoning is bogus. So, why 1600?

Yeah.  Why not 1, for that matter?

Or should we call it 0001?  ;-)

I suppose the issue is how many bits are needed to represent it.

There's a reason not to include negative years -- there is no year 0 in
our calendar, so that would mess up calculations.

****************************************************************

From: Thomas Wolf
Sent: Friday, October 17, 2003  10:06 AM

> Did they also vote that Boolean'Image should return a locale-dependent
> result?!

I hope not. But why should they? For me, the argument about
day and month names in strings returned from the image function
for Time has nothing to do with the question whether
Boolean'Image (True) = "TRUE" or Day_In_Week_Type'Image (Sunday)
= "SUNDAY". That's just fine.

But including the day name in a time string generated by the Image
function for type Time is something else: the day name is not
a characteristic of Time itself; it is just a name. As such it
doesn't belong into the result returned by the standard Image
function for the type.

Or what would you think of Integer'Image (0) = "Zero"??

****************************************************************

From: Tucker Taft
Sent: Friday, October 17, 2003 10:32 AM

> ...
> I'm still curious to know which countries think that Monday is the first
> day, and when they started thinking that, and why.  Anybody know?
> And was ISO following their lead, or the other way around?
>
> (By the way, in the U.S., the "weekend" means "Saturday and Sunday",
> even though Sunday is not at the "end".  Strange.)

I am surprised by your vehemence on this.  I personally much
prefer weekly calendars where saturday and sunday are at the
"end," and I have always thought of Sunday as the 7th day,
not the 1st day.  I suspect this may be semi-cultural and semi-religious.
I realize that on most monthly calendars (in the U.S.), the left-most
column is generally Sunday, but I never took that to mean that Sunday
was the "first" day of the week.  Hmmmm....

I just took a look at my Palm organizer, and it has a settable preference
for whether the first day of the week is Sunday or Monday.
Interesting.

In any case, I recommend that everyone wait for the newer
revision of this AI, and make comments relative to that, as
it will be largely rewritten based on the recent ARG discussions.

****************************************************************

From: Erhard Ploedereder
Sent: Friday, October 17, 2003  9:20 AM

> > Furthermore, I'm personally convinced that image functions that
> > include a textual day or month representation like "Mon" or "Dec"
> > are a bad idea.

> I don't agree.  Of course, as an English speaker, I'm biased.
> But we spell "begin" and "Put_Line" and "True" and everything else in
> English.  Why should days of the week be different?

I must admit that this enumeration type had me worried, too,
wrt. international acceptance. It is the first instance, where a truly
every-day word is cast into language concrete, with an immediate consequence
on program output. I eventually convinced myself that all other options were
inferior.

However, in defining ancillary semantics, we should make sure that we do not
impose implicit semantics anywhere that render a facility useless, if the
output is intended to read Lundi or Montag, and there is no simple
write-around.

For 'Image on the Enumtype, there is an easy writearound.

A predefined function that gives me the whole shebang of say
   2003-Mar-18, Wed, 10:00 p.m.
without being able to somehow localize it to read
   2003-Mr-18, Mi, 22:00
would run into significant political difficulty.

****************************************************************

From: Peter Hermann
Sent: Friday, October 17, 2003   6:51 AM

On Fri, Oct 17, 2003 at 12:49:37PM +0200, Thomas Wolf wrote:
> ISO-8601 defines the week to start on Monday. I believe if
> Ada 0X (also an ISO-standard) should define it's representation
> for day-in-week in accordance with ISO 8601, i.e.
>
>     type Days_in_Week_Type is
>       (Monday, Tuesday, Wednesday, Thursday,
>        Friday, Saturday, Sunday);

100% agreement.

useful for own definitions like e.g.
subtype working_days is days_in_week_type range monday..friday;
subtype weekend is ... etc.

--------------------------------------------------------------------

>    --  03-OCT-2001 yields
>    --
>    --  Format = MDY, Separator = "/"   ==> 10/03/2001    (English)

is useful for certain sorting needs within one year.

>    --  Format = DMY, Separator = ". "  ==> 03. 10. 2001  (German)

may be useful for rare sorting needs.

>    --  Format = YMD, Separator = "-"   ==> 2001-10-03    (ISO 8601)
>    --  Format = YMD, Separator = ""    ==> 20011003

is indeed useful for most sorting needs.

--------------------------------------------------------------------

> > [Open issue: Should we increase the year range in Calendar to
> > 1600..2400? This would potentially require two more bits in the
> > Time value. 1600 is used as the lower bound, as current calendar
> > wasn't used universally until around that date. But it would
> > avoid Ada's own Y2.1K problem.]

should be considered.
implications on calculations of differences have to be taken
into account.

-------------------------------------------------------------------

this code may stimulate, too:
http://www.csv.ica.uni-stuttgart.de/homes/ph/adapilotresources/basic_tools/calenday.ads
( + ...adb  ;-)

****************************************************************

From: John Halleck
Sent: Friday, October 17, 2003  10:01 AM

> One other question...
>
> why extend via a child package rather than just adding the
> new routines to the existing Ada.Calendar package?

  Well, Several obvious but trivial reasons immediately
  occur to me.

     1) one trivial point is that if you add a child package
        you don't break any existing code.
        If you extend a package you stand SOME chance of using
        some names that duplicate what you have chosen.

     2) If it is NOT a child package, you now have two different
        packages (the old one and the new extended one) that have
        the same name, and knowing a site has Ada.Calendar doesn't
        tell you which one it is.  (But knowing they have
        Ada.Calendar.someextentionorother tells you a lot.)

   I'm sure that others on this list can suggest even more compelling
   reasons.

> [...]

****************************************************************

From: Peter Hermann
Sent: Friday, October 17, 2003  10:33 AM

On Fri, Oct 17, 2003 at 03:53:54PM +0200, Thomas Wolf wrote:
> > Unless Ada goes all the way to supporting locales (which seems like too
> > much), we should just use "Sunday", etc.
>
> As the spelling of the enumeration literal, yes. But an image function
> producing strings containing "Sunday" or "Sun" will not be very helpful
> wherever the string representation should be in some other language.

As a German I can live with
   type day_name is (mon,tue,...,sun);
   type month_name is (jan,feb,...,dec);
   type boolean is (false,true);

and using these as indices into my locales when needed.

> I believe one would be better off with an Image function that didn't
> include day (or month) names in the generated string and have an
> application add or insert the appropriate strings in the appropriate
> lanugages.


> I'm not suggesting Ada should support locales.

me too: no overkill.

****************************************************************

From: Erhard Ploedereder
Sent: Friday, October 17, 2003 11:34 AM


> I'm still curious to know which countries think that Monday is the first
> day, and when they started thinking that, and why.  Anybody know?

Germany definitely starts weeks on Monday.

As to origins, I am rather certain that the cause is the traditional
counting of Christianity to have Sunday as the 7th day of the week, a day of
rest, church going and singing hosianahs. Justification taken from
Genesis. This goes back to the very origins of Church, Popes, Patriarchs,
i.e., nearly 2000 years. Why they chose Sunday to be the holy day instead
of Saturday, is an easy guess.

I wouldn't be surprised, if the answer were the same for almost all European
countries, since the Church in its various incarnations used to have a lot
of influence on the secular European world. (Even in the US, despite
separation of Church and State, the secular "day of rest" is the Sunday.)

As to the ISO decision: simply look at the above and the majority situation
of countries active and voting in ISO.

All this not in terms of justification, only explanation. If you take Judaic
tradition, the week starts on Sunday. If you're Moslem, the week starts on
Saturday, doesn't it?  And I have no idea how Hinduism and Buddhism have
decided on this question. Or, if you have a hankering for Napoleon, he tried
to introduce the 10-day week, a singularly unsuccessful attempt :-)

****************************************************************

From: Adam Beneschan
Sent: Friday, October 17, 2003 12:18 PM

I don't think this is correct.  The seventh day of the week from
Genesis, the day God rested, i.e. the "sabbath", has always been
associated with Saturday.  In fact, the word for Saturday is "sabato"
in Italian, and I believe it's similar in some other languages.
Sunday is identified as the Christian holy day because it's the day of
Jesus' resurrection (according to the Gospels, Jesus was crucified on
the day before the Sabbath, and resurrected on the day after).  As I
recall reading, the early Christians observed both---they observed the
Sabbath as a day of rest and the following day as a celebration of the
resurrection.  I'm not sure at what point the observance of the
Sabbath generally stopped (there were theological reasons why it was
no longer considered necessary, according to some blurbs I've read).
But I'm pretty sure that Christianity has always identified Saturday,
not Sunday, as the seventh day.  So the idea of a week starting on
Monday and ending in Sunday is more likely a more contemporary idea.

I could be wrong about some of this, though.

****************************************************************

From: Jeffery Carter
Sent: Friday, October 17, 2003  1:23 PM

Thomas Wolf wrote:
>
>     type Days_in_Week_Type is
>       (Sunday, Monday, Tuesday, Wednesday, Thursday,
>        Friday, Saturday);

Personally, I think this type should be named Day_Of_Week_Type, or even
just Day_Name (regardless of the order of the days). Days in week is 7.

> Furthermore, I'm personally convinced that image functions that
> include a textual day or month representation like "Mon" or "Dec"
> are a bad idea. Day and month names are highly locale-specific
> (or, if you prefer, language-specific). Better leave that to
> the applications using this. (And given a Day_Of_Week function,
> it's no big deal to generate any string image one might want for
> any Day_Of_Week_Type value.)

PragmARC.Date_Handler has extensive image functions that can be
customized if desired to handle any local names that can be expressed as
type String (lines may wrap):

    -- Image operations:

    -- Image functions with a Zero_Fill parameter may have extra leading characters in the result.
    -- If Zero_Fill, these will be '0'; otherwise they will be ' '.

    -- Provide the image of any year CE:
    function Year_Image_Short (Year : Positive; Zero_Fill : Boolean := True) return String;
    -- Returns the decimal image of Year rem 100.
    -- If Zero_Fill, result will always be 2 characters long. Otherwise, result will be 1 or 2 characters long.

    function Year_Image_Long  (Year : Positive; Zero_Fill : Boolean := True; Width : Positive := 4) return String;
    -- Returns the decimal image of Year. Result will be large enough to hold this image, or Width characters long,
    -- whichever is larger.

    type Case_Selection is (Lower, Mixed, Upper, As_Is); -- Determines the formatting of month names

    type Name_List is array (Calendar.Month_Number) of Unbounded_String; -- Used to provide month names

    Default_Short_Name : constant Name_List := (01 => To_Unbounded_String ("Jan"),
						02 => To_Unbounded_String ("Feb"),
                                                03 => To_Unbounded_String ("Mar"),
						04 => To_Unbounded_String ("Apr"),
                                                05 => To_Unbounded_String ("May"),
						06 => To_Unbounded_String ("Jun"),
                                                07 => To_Unbounded_String ("Jul"),
						08 => To_Unbounded_String ("Aug"),
                                                09 => To_Unbounded_String ("Sep"),
						10 => To_Unbounded_String ("Oct"),
                                                11 => To_Unbounded_String ("Nov"),
						12 => To_Unbounded_String ("Dec") );
                                                -- Default "short" month names

    Default_Long_Name  : constant Name_List := (01 => To_Unbounded_String ("January"),
                                                02 => To_Unbounded_String ("February"),
                                                03 => To_Unbounded_String ("March"),
                                                04 => To_Unbounded_String ("April"),
                                                05 => To_Unbounded_String ("May"),
                                                06 => To_Unbounded_String ("June"),
                                                07 => To_Unbounded_String ("July"),
                                                08 => To_Unbounded_String ("August"),
                                                09 => To_Unbounded_String ("September"),
                                                10 => To_Unbounded_String ("October"),
                                                11 => To_Unbounded_String ("November"),
                                                12 => To_Unbounded_String ("December") );
                                                -- Default "long" month names

    function Month_Image_Numeric (Month : Calendar.Month_Number; Zero_Fill : Boolean := True) return String;
    -- Returns the decimal image of Month.
    -- If Zero_Fill, result will always be 2 characters long. Otherwise, result will be 1 or 2 characters long.

    function Month_Image_Alpha (Month : Calendar.Month_Number; Casing : Case_Selection := Mixed; Name : Name_List) return String;
    -- Returns To_String (Name (Month) ), formatted as directed by Casing.

    -- Renamings for default month names:
    function Month_Image_Short
       (Month : Calendar.Month_Number; Casing : Case_Selection := Mixed;
        Name : Name_List := Default_Short_Name)
    return String renames Month_Image_Alpha;
    function Month_Image_Long
       (Month : Calendar.Month_Number; Casing : Case_Selection := Mixed;
        Name : Name_List := Default_Long_Name)
    return String renames Month_Image_Alpha;

    function Day_Image (Day : Calendar.Day_Number; Zero_Fill : Boolean := True) return String;
    -- Returns the decimal image of Day.
    -- If Zero_Fill, result will always be 2 characters long. Otherwise, result will be 1 or 2 characters long.

    type AM_PM_ID is (AM, PM);
    type AM_PM_List is array (AM_PM_ID) of Unbounded_String;

    Default_AM_PM_Name : constant AM_PM_List := (AM => To_Unbounded_String (" am"), PM => To_Unbounded_String (" pm") );

    function Hour_Image_12 (Hour : Hour_Number;
                            AM_PM : AM_PM_List := Default_AM_PM_Name; Zero_Fill : Boolean := True) return String;
    -- If Hour = 0, Image is "12". If Hour in 1 .. 12, Image is image of Hour. Otherwise, Image is image of Hour - 12.
    -- If Hour < 12, returns Image & To_String (AM_PM (AM) ). Otherwise, returns Image & To_String (AM_PM (PM) ).
    -- If Zero_Fill, Image will always be 2 characters long. Otherwise, Image will be 1 or 2 characters long.

    function Hour_Image_24 (Hour : Hour_Number; Zero_Fill : Boolean := True) return String;
    -- Returns the decimal image of Hour.
    -- If Zero_Fill, result will always be 2 characters long. Otherwise, result will be 1 or 2 characters long.

    function Minute_Image (Minute : Minute_Number; Zero_Fill : Boolean := True) return String;
    -- Returns the decimal image of Minute.
    -- If Zero_Fill, result will always be 2 characters long. Otherwise, result will be 1 or 2 characters long.

    function Seconds_Image (Seconds : Minute_Duration;
                            Zero_Fill : Boolean := True; Aft : Natural := 0) return String;
    -- Returns the decimal image of Seconds, with Aft digits after the decimal point.
    -- If Aft = 0, result will not contain a decimal point.
    -- If Aft = 0 and Zero_Fill, result will always be 2 characters long.
    -- If Aft = 0 and not Zero_Fill, result will be 1 or 2 characters long.
    -- If Aft > 0 and Zero_Fill, the portion of result left of the decimal point will always be 2 characters long.
    -- Otherwise, the portion of result left of the decimal point may be 1 or 2 characters long.
    -- If Seconds = Minute_Duration'Last, returns the image of 0.0.

    function Image (Date : Calendar.Time) return String;
    -- Splits Date into Year, Month, Day, Hour, Minute, and Seconds, then
    -- returns the 23-character string resulting from
    --    Year_Image_Long (Year)    & ' ' &
    --    Month_Image_Short (Month) & ' ' &
    --    Day_Image (Day)           & ' ' &
    --    Hour_Image_24 (Hour)      & ':' &
    --    Minute_Image (Minute)     & ':' &
    --    Seconds_Image (Seconds, Aft => 2);

This last is a quick way to obtain a default full image of a Time.
Naturally, the package also provides Split to obtain hours, minutes, and
seconds, and a Day_Of_Week function.

If the day name is desired in an image, Day_Of_Week may be used; the
return value may be used to index an array of local day names if the
values of the enumeration are not satisfactory.

Components may be arranged in any order, with any separators, as
required by local standards.

So far, no user has requested any additional image functionality.

The PragmAda Reusable Components are available from

http://home.earthlink.net/~jrcarter010/pragmarc.htm

should you want to inspect this package further

****************************************************************

From: Robert A. Duff
Sent: Friday, October 17, 2003  2:34 PM

> As to the ISO decision: simply look at the above and the majority situation
> of countries active and voting in ISO.

Fascinating.  Sorry for some off-topic chatting, but...

I didn't *really* mean to bring religion into this discussion,
but that's where our 7-day week notion comes from, and no matter what
religion you are, or none, you have to admit this is where it
originates.

The book of Genesis, in the Jewish Torah (which is also part of the
Christian Bible) in chapter 1, explains how God created the world in 6
days.  In 2(1-2) it says something about how God rested on the seventh
day.  [The rest of chapter 2 tells a *different* story about
world-creation, contradicting chapter 1; this is the story of Adam and
Eve.]

Later parts of the Torah define the seventh day as the sabbath, i.e. day
of rest.  This is the day known as Saturday in English (which I guess
comes from the Roman god Saturn, which has nothing to do with either
Judaism or Christianity).  But I believe in some European languages
(Italian and Spanish maybe?) this day is still called sabat or something
like it.

I thought Christians still view the sabbath as the last day of the week,
but they just don't celebrate it anymore; they instead celebrate Sunday,
because that's the day Jesus was resurrected.  I had no idea that in
Europe that meant a redefinition of "sabbath" or of "last day of week".
I just thought Christians celebrate the first day of the week.

These days, we can't truly appreciate the notion of sabbath, since we
have a 40-hour work week, and we get to rest on both Saturday *and*
Sunday.

> All this not in terms of justification, only explanation. If you take Judaic
> tradition, the week starts on Sunday. If you're Moslem, the week starts on
> Saturday, doesn't it?

I don't know.  Muslims do their main worship on Friday, I believe, but I
don't know if they define that as the last day of the week.

>...And I have no idea how Hinduism and Buddhism have
> decided on this question. Or, if you have a hankering for Napoleon, he tried
> to introduce the 10-day week, a singularly unsuccessful attempt :-)

Yeah, Napoleon's experiment was interesting.  ;-)

Anyway, I guess Ada should do what ISO wants in this regard.

But I'm used to Sunday being the *first* day of the week, and
I will never buy a calendar that shows otherwise, no matter what
pretty pictures it shows.

****************************************************************

From: Alexandre E. Kopilovitch
Sent: Friday, October 17, 2003  3:41 PM

>if you have a hankering for Napoleon, he tried
>to introduce the 10-day week, a singularly unsuccessful attempt :-)

In Soviet Union, in 1920th and/or 30th, Communists repeated this attempt -
they decided that holidays must be 5, 15 and 25 each month, but retreated after
some time.

****************************************************************

From: Gary Dismukes
Sent: Friday, October 17, 2003  3:58 PM

> > One other question...
> >
> > why extend via a child package rather than just adding the
> > new routines to the existing Ada.Calendar package?
>
>   Well, Several obvious but trivial reasons immediately
>   occur to me.
>
>      1) one trivial point is that if you add a child package
>         you don't break any existing code.
>         If you extend a package you stand SOME chance of using
>         some names that duplicate what you have chosen.
> ...

More specifically, adding new declarations to existing predefined
packages runs the risk of causing ambiguities in existing applications
that have use clauses.  Generally we want to avoid causing that kind
of incompatibility.

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  5:41 PM

If you're already in the habit of using a use clauses, you still run
this risk if you "with" and "use" the new package...

Sorry, but (as a user) it just looks gratuitous to me :-(

****************************************************************

From: Randy Brukardt
Sent: Friday, October 17, 2003  6:00 PM

Sigh. Anytime you add a "with" or "use", you should expect things to break.
But that can only happen in *new* or *modified* code. What we're concerned
about is *existing* code that is recompiled with compiler that happens to
support Ada 200Y features. This should work, unmodified. That's especially
important as we're expecting Ada 200Y to be adopted incrementally, not all
at once as Ada 95 was. If someone doesn't use new features, their code
should continue to work. (There are a couple of cases where that won't be
true, but we believe that they are unlikely to occur in practice. Extra
overloadings of "Split" are much more likely to cause trouble.)

In any case, AI-351/01 was a straw man proposed by me in order to get a
discussion going at the ARG level. That goal was wildly successful. :-) I'd
suggest waiting for the next version before commenting, as a lot of things
will be different. (No one yet has complained about leap seconds, which was
the topic that managed to dominate the ARG discussion.)

****************************************************************

From: Pascal Obry
Sent: Saturday, October 18, 2003  1:44 AM

 > Sorry, but (as a user) it just looks gratuitous to me :-(

It avoids dragging a bunch of routines that you maybe do not need. This
helps minimize the compilation time, the link time and also the size of the
executable. I think all this is really sufficient to use child packages when
possible.

****************************************************************

From: Martin Dowie
Sent: Saturday, October 18, 2003  2:30 AM

> Sigh. Anytime you add a "with" or "use", you should expect things to break.
> But that can only happen in *new* or *modified* code. What we're concerned

Or when I decide to:
  a) put my code through a new compiler, or
  b) put my code through a new compiler for a new language standard. :-)

I mean, really, what's the worst that's going to happen? The compiler is going
to tell me there is an ambiguous call, I look up the new RM (or porting guide,
someone is going to provide a porting guide, like last time, yes?) and I see that
I can now either bin my routine as the lanuage now has the routine I need
built-in, or use my 'trusted' routine, by making the call unambiguous and use
which ever one I want.

As a user (again!) - I can live with this!! It isn't as if the routine (esp. 'Split', which
I agree is the likeliest 'culprit') is going to do anything different to what I actually
want...

If we change which language standard we are working to (and compiler), we
know in advance there may be some cost and changes required - this one
looks trivial and a child package, to add the routines that should have been
there to start with, just looks 'kludgy'...

> suggest waiting for the next version before commenting, as a lot of things

Ok - can't wait for the new proposal! :-)

****************************************************************

From: Nick Roberts
Sent: Friday, October 17, 2003  3:51 PM

"Robert A Duff" <bobduff@TheWorld.com> wrote:

> I suppose you're right, though -- Ada pretty much has to obey
> ISO on the weekday point.  Grumble.

It does if it is to remain an ISO standard: ISO mandates that its standards
must be based on other ISO standards wherever applicable (as I'm sure you
know, Bob :-)

> I'm still curious to know which countries think that Monday is
> the first day, and when they started thinking that, and why.
> Anybody know? And was ISO following their lead, or the other
> way around?

ISO 8601 itself acknowledges that people from different cultural and
religious backgrounds recognise different days as being the first day of the
week, and it states that the decision to plump for Monday is based purely on
the fact that the vast majority of businesses around the world use Monday as
the first day of the week in calculating week numbers (within the year). In
fact, this actually means that a week is considered to fall within a certain
year if its Thursday does.

> >... (BTW, I'd have to look this up, but doesn't the ISO week
> > number also depend on the day defined to be the start of
> > the week?)
>
> Probably.

Yes it does.

> ... But given the existence of (for example) Boolean'Image,
> there is no law saying "Ada shall not have predefined stuff
> that prints out messages in English".

Indeed. Especially since there is also no law that says an Ada compiler
cannot have a non-standard mode in which it prints predefined stuff in
another language. But I agree that it isn't necessary for the Ada standard
to provide images of the day or month names, when this is functionality that
can almost trivially be supplied by the user.

> It would be great if Ada could support Internationalization,
> and support it well.  But that's too hard (I think we all agree),
> especially since "do it well" probably means fitting in well with
> operating-system-dependent support for locales.

Handling time locales, as well as language locales, well is a fantastically
complicated business. The GNU stuff has a huge file that contains
information about timezones (and daylight saving times) around the world
which is not only current but also historic! No way can that kind of thing
be put into the principal Ada standard.

It could be made some sort of secondary standard, maybe. If so, then frankly
I'd more happily support a standard that was independent of programming
language and operating system (perhaps being based on an OMG IDL module).

> Given that, it seems silly to forbid the standard from having
> something that's useful for at least *some* programs.

It seems reasonable to me for the standard to define enumeration types for
day of the week and month of the year with English names for the enumeration
literals. The user can then very easily supply arrays of ((un)bounded?)
strings to produce names in another language. This technique is often used
to make a Boolean value produce "No" and "Yes", "Non" and "Oui", or
whatever.

> > Maybe the author of the AI knows. I just mentioned this
> > because I don't understand the reasoning in the sentence
> > "1600 is used as the lower bound, as [the] current calendar
> > wasn't used universally until around that date.", which is
> > not mine, but is taken verbatim from the AI. Hence I
> > pointed out that this reasoning is bogus. So, why 1600?
>
> Yeah.  Why not 1, for that matter?
>
> Or should we call it 0001?  ;-)

The SQL-92 standard (ISO 9075:1992(E)) defines its year type to have the
range 0001 to 9999. Myself, I would support the standard changing
Ada.Calendar to say:

   subtype Year_Number is Integer range [implementation defined];

and simply stipulating that the implementation-defined range must minimally
encompass [1901,2099].

This would allow a bigger year range to be provided (with a standard name),
but its actual range could be chosen to be most appropriate for the
implementation. It's a compromise that has worked well for Integer itself.

> There's a reason not to include negative years -- there is no
> year 0 in our calendar, so that would mess up calculations.

One could, perhaps, posit the rule that the year n CE always equates to the
year 1-n BC (as well as to the year n AD). Perhaps more sensibly one could
posit that any year n CE for n < N does not determinately equate to any year
AD or BC, where you can argue about N as much as you like (is it 1582, for
example?). In short, there's no point in worrying about year 0 CE, or
negative years CE; astronomers don't (they cheerfully talk about negative
years in the millions, although they do all their calculations in JD).

****************************************************************

From: Dan Eilers
Sent: Saturday, October 18, 2003  5:54 PM

Thomas Wolf wrote:
> ISO-8601 defines the week to start on Monday.  ...

I'm not so sure this is true.

Unfortunately, ISO-8601 apparently isn't available on the web.
Can anyone quote the part that "defines the week to start on Monday"?

ISO has a web page that informally describes ISO-8601, at:
  http://www.iso.ch/iso/en/prods-services/popstds/datesandtime.html

This web page describes ISO-8601 as a standard for writing dates
unambiguously, not a standard for arranging the layout of columns
on monthly calendars, or for specifying the internal representation
of week-day enumeration types used in programming languages.
If this web page is correct in describing the purpose and scope of
ISO-8601, then I would consider Ada to be in perfectly fine conformance
if it provided facilities for printing dates in all the ISO-8601 formats,
regardless of what internal representation is used for a week-day
enumeration type in package Calendar.

My understanding from the ISO web page is that for the purpose of
printing dates in an alternative week-date format used by certain
commercial and industrial processes, the week-date format is computed
by using a formula that assigns Monday=1 and Sunday=7.  It is of
course perfectly reasonable for certain commercial and industrial
processes to use formulas that consider Monday=1, since Monday is
generally considered to be the first day of a work week.  But from
what I can tell, this use of Monday=1 in ISO 8601 is solely for the
limited purpose of calculating week-dates in this alternative format,
rather than a broad requirement that "weeks must start on Monday".
Since this format is explicitly described as an "alternate", I think
Ada would be perfectly correct in using the more conventional
definition of Sunday as the first day of the week.

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************

From: Martin Dowie
Sent: Friday, October 17, 2003  2:46 AM

****************************************************************


Questions? Ask the ACAA Technical Agent