Version 1.3 of ai12s/ai12-0336-1.txt
!standard 9.6.1(6/2) 19-06-06 AI12-0336-1/02
!standard 9.6.1(35/2)
!standard 9.6.1(40/2)
!standard 9.6.1(42/3)
!standard 9.6.1(90/2)
!standard 9.6.1(91/2)
!class binding interpretation 19-06-04
!status work item 19-06-04
!status received 19-05-30
!priority Low
!difficulty Easy
!qualifier Omission
!subject Meaning of Time_Offset
!summary
UTC_Time_Offset means Calendar time - UTC time.
Time_Zone = 0 means the time zone of Calendar.
!question
(1) 9.6.1(42/3) says the return value of UTC_Time_Offset is a number of
minutes, the result of subtracting the implementation-defined time
zone of Calendar from UTC time, at [a specific time].
This is in direct contradiction to the second paragraph of the
!discussion in AI05-0119: "The intent is that UTC_Time_Offset means
local-time - UTC-time.".
It's also contrary to the ramification of 9.6.1(42.a.1/3).
Is the normative wording correct? (No.)
!recommendation
(See Summary.)
!wording
Add after 9.6.1(6/2):
function Local_Time_Offset (Date : Time := Clock) return Time_Offset
renames UTC_Time_Offset;
Add after 9.6.1(35/2):
function Local_Image (Date : Time;
Include_Time_Fraction : Boolean := False) return String is
(Image (Date, Include_Time_Fraction, Local_Time_Offset (Date)));
Modify 9.6.1(40/2):
Type Time_Offset represents {for a given locality at a given moment} the
number of minutes {the local time is,
at that moment, ahead (+) or behind (-) Coordinated Universal Time
(abbreviated UTC). Redundant[ The zero value
of type Time_Offset represents UTC}
[difference between UTC the implementation-defined time zone used
by Calendar and another time zone].
Modify 9.6.1(42/3):
Returns, as a number of minutes, {the Time_Offset of}[the result of
subtracting] the implementation-defined time zone of Calendar [from UTC
time], at the time Date. If the time zone of the Calendar
implementation is unknown, then Unknown_Zone_Error is raised.
Delete the second sentence of AARM 9.6.1(42.a/2).
Modify 9.6.1(90/2):
The implementation-defined time zone of package Calendar may, but need not,
be the local time zone. {Local}[UTC]_Time_Offset always returns the difference
relative to the implementation-defined time zone of package Calendar. If
{Local}[UTC]_Time_Offset does not raise Unknown_Zone_Error, UTC time can be
safely calculated (within the accuracy of the underlying time-base).
Modify 9.6.1(91/2):
Calling Split on the results of subtracting
Duration({Local}[UTC]_Time_Offset*60) from Clock provides the components
(hours, minutes, and so on) of the UTC time. In the United States, for example,
{Local}[UTC]_Time_Offset will generally be negative.
!discussion
As the questioner states, AI05-0119-1 clearly states that UTC_Time_Offset
means local-time - UTC-time. The wording change from that AI resulted in
"...the result of subtracting the implementation-defined time
zone of Calendar, and UTC time". During Ada 2005 review, Canada noted that
the wording was still ambigious, so ", and" was changed to "from". But
apparently no one noticed that this is backwards of the intent.
Note that Ada is strongly typed, and so should the definition of Ada: a
"time" and a "time zone" are not the same thing. Subtracting time zones is
not well-defined, so we have to talk about subtracting times in particular
time zones.
----
In researching this question, we tried a program provided by the questioner
on all of the Ada 2005 compilers that we are aware of. All of the compilers
that implement Ada.Calendar.Formatting except one (the least used one,
still in beta) treated Time_Offset = 0 as UTC time.
Enforcing the RM as written would therefore break any existing code that
uses Ada.Calendar.Formatting (with the exception of the author's program
that triggered this discussion).
We therefore redefine Time_Offset to match the compilers, and add versions
of some of the functions that provide the originally intended functionality.
We used the prefix "Local_" to represent times for the "implementation-defined
time zone of Calendar". Formally, since the time zone of Calendar need not be
local, the correct name would be something like:
Implementation_Defined_Time_Zone_of_Calendar_Image (...)
But this appears to have a small usability problem. :-) The original intent
was that Image would do this, and we don't want to have to write too much more
to get that original intent.
We added a renamed version of UTC_Time_Offset names Local_Time_Offset, as that
better represents the meaning of the function with the change in the definition
of Time_Offset. Note that the actual result of the function is unchanged.
We also added Local_Image, to provide the image of the Ada.Calendar time
without having to call Local_Time_Offset.
We considered defining Local_xxx versions of all of the other subprograms in
Ada.Calendar.Formatting that take Time_Zone parameters.
For Value and Time_Of, there is a problem: the correct time zone
to use could depend on the result of the function -- which of course depends
on the time zone passed in. For most uses, this is unlikely to be an issue,
so we could define a version based on the current time zone, but that could
get incorrect answers near a time zone change. (To get certain correct answers,
one could iterate until the result was the same for two successive iterations,
but such an iteration is not guaranteed to terminate, so it's impractical to
use it in the language definition).
We did not define new versions of Split in part because we aren't defining
most of the other routines (as noted above), and simply because there are three
versions with a bunch of parameters each, so these definitions would add quite
a bit of text to the package. Local_Year, Local_Month, and so on don't seem
useful enough to define.
======
Note again that this change is inconsistent with the Ada 2012 definition.
So far as we are aware, only the beta 3.2.1 Janus/Ada follows the Ada 2012
definition, so this inconsistency is not going to arise in practice.
!ASIS
No ASIS effect.
!ACATS test
An ACATS C-Test should be constructed to check that Time_Zone = 0 means
Calendar time. One way to do that is to compare the result of
Ada.Calendar.Split to Ada.Calendar.Formatting.Split with Time_Zone = 0,
as well as Ada.Calendar.Image with Time_Zone = 0.
!appendix
!topic Confusing definition of UTC Time
!reference Ada 2012 AARM 9.6.1 (42/3)
!from Simon Wright 2019-05-30
!keywords UTC
!discussion
First off, let me clarify I'm not addressing the complex questions of
the changeover to/from daylight-saving or leap seconds, addressed at
length in AI05-0119.
(42/3) says the return value of UTC_Time_Offset is a number of
minutes, the result of subtracting the implementation-defined time
zone of Calendar from UTC time, at [a specific time].
This is in direct contradiction to the second paragraph of the
!discussion in AI05-0119: "The intent is that UTC_Time_Offset means
local-time - UTC-time.".
It's also contrary to the ramification of (42.a.1/3).
At the moment, I'm on British Summer Time, and the time is 18:01. In
GMT that would be 17:01. GNAT thinks the UTC_Time_Offset is +60, which
makes sense to me since we put the clocks forward in March.
As a side issue, aren't "implementation-defined time zone of Calendar"
and "UTC Time" incommensurate? I'm pretty sure I know what is meant,
"the time returned by Calendar.Clock (whose time zone is
implementation-defined)".
****************************************************************
From: Tucker Taft
Sent: Thursday, May 30, 2019 1:55 PM
Interesting! This appears to be due to an "editorial" shift in wording as
part of AI05-0269-1 from "subtracting A and B" to "subtracting A from B"
which inverts the meaning. It would be interesting to know what most
compilers do here (at least the ones that don't always return zero!).
****************************************************************
From: Randy Brukardt
Sent: Friday, May 31, 2019 12:07 AM
Janus/Ada, at least, returns a negative number here in Wisconsin. I would
hope that implementers read the AARM note and match that (sounds like GNAT
does that, anyway). But the wording does seem backwards. Sigh - another AI.
****************************************************************
From: Tucker Taft
Sent: Friday, May 31, 2019 6:43 AM
Actually, I described the change incorrectly. It went from "the difference
between A and B" to "subtracting A from B." Unfortunately "difference between"
is itself somewhat ambiguous, but in any case, the final wording is
unambiguous, but wrong ... ;-)
****************************************************************
From: Randy Brukardt
Sent: Tuesday, June 4, 2019 8:59 PM
...
> As a side issue, aren't "implementation-defined time zone of Calendar"
> and "UTC Time" incommensurate? I'm pretty sure I know what is meant,
> "the time returned by Calendar.Clock (whose time zone is
> implementation-defined)".
I think any good Ada compiler would reject an expression between two different
types. Unfortunately, there's no ARM compiler.
Anyway, the better question is how to repair it. My first thought was to
describe it as the difference between two time zones:
Modify 9.6.1(42/3):
Returns, as a number of minutes, the result of subtracting {the time zone of
UTC time from} the implementation-defined time zone of Calendar[ from UTC
time], at the time Date. If the time zone of the Calendar implementation is
unknown, then Unknown_Zone_Error is raised.
...but this is a bit weird because most of us think of time zones as names
like UTC or BST or CDT. What is the result of subtracting "UTC" - "CDT"?
(-300 is the intended answer, but there doesn't seem to be an operator).
So it seems like we need a bigger change:
Modify 9.6.1(42/3):
Returns, as a number of minutes, the result of subtracting {the UTC time
corresponding to Date from} the {time in} the implementation-defined time zone
of Calendar[, at the time]{ corresponding to} Date. If the time zone of the
Calendar implementation is unknown, then Unknown_Zone_Error is raised.
[Recall that "Date" is the parameter to UTC_Time_Offset.]
Is this latter wording OK, or should we do something else???
****************************************************************
From: Tucker Taft
Sent: Tuesday, June 4, 2019 9:26 PM
> Is this latter wording OK, or should we do something else???
This doesn't work for me. You are implying that the value of time is time-zone
dependent. That is not true on any Unix-like system. The value of "time" is
the same on all Unix systems at any given moment, being defined as the number
of seconds since some particular moment in history (e.g. Jan 1, 1970, GMT).
I think we need to talk about the number of minutes since the local midnight,
say, and do the computation in terms of that value, perhaps modulo 24*60.
We probably should start by defining what we mean by "time zone" since the
term is used repeatedly. If that definition is described, for the purposes of
this section, as a number of minutes the local time is ahead of (+) or
behind (-) UTC, then I think the rest becomes trivial.
Here is my attempt:
Modify 9.6.1(40/2):
{For the purposes of this subclause, the /time zone/ for a given locality is
defined in terms of the number of minutes the local time is ahead (+) or
behind (-) UTC.} Type Time_Offset represents the number of minutes
difference between the implementation-defined time zone used by Calendar and
another time zone.
Now we can modify 9.6.1(42/3):
Returns, as a number of minutes, [the result of subtracting] the
implementation-defined time zone of Calendar [from UTC time], at the time
Date. If the time zone of the Calendar implementation is unknown, then
Unknown_Zone_Error is raised.
****************************************************************
From: Randy Brukardt
Sent: Tuesday, June 4, 2019 10:50 PM
...
> This doesn't work for me. You are implying that the value of time is
> time-zone dependent. That is not true on any Unix-like system. The
> value of "time" is the same on all Unix systems at any given moment,
> being defined as the number of seconds since some particular moment in
> history (e.g. Jan 1, 1970, GMT).
I've never understood this argument. We can say "time" is whatever we want it
to be, it doesn't necessarily have anything to do with how it is represented
on a particular system. Moreover, even on systems that use a raw counter, you
still have to know what time zone the counter represents, or you couldn't
possibly split the value properly. 1042 seconds since a base date is not a
time, 1042 since some date in UTC is a time.
Put another way, the time zone for a time value might be implicit, or it might
be determined some other way, but there has to be one for any value of time.
Be that as it may, I know that this argument is non-terminating, so let's move
on.
> I think we need to talk about the number of minutes since the local
> midnight, say, and do the computation in terms of that value, perhaps
> modulo 24*60.
>
> We probably should start by defining what we mean by "time zone" since
> the term is used repeatedly. If that definition is described, for the
> purposes of this section, as a number of minutes the local time is
> ahead of (+) or behind (-) UTC, then I think the rest becomes trivial.
>
> Here is my attempt:
>
> Modify 9.6.1(40/2):
>
> {For the purposes of this subclause, the /time zone/ for a given
> locality is defined in terms of the number of minutes the local time
> is ahead (+) or behind (-) UTC.} Type Time_Offset represents the
> number of minutes difference between the implementation-defined time
> zone used by Calendar and another time zone.
The (minor) problem here is that type Time_Offset and the virtual type time
zone are very different for no obvious reason. Obviously, whomever read this
at AdaCore interpreted it to be the former (which one can read fairly easily
on Linux) and never really looked at the actual words (or decided the apply
the Dewar rule without telling anyone).
One has to wonder if we really should have these two separate declarations,
especially since it appears that only Janus/Ada does this right (that is,
following the RM definition). Times would work slightly better if UTC was the
default time zone (getting UTC wouldn't depend on the time zone, which is
error-prone). Of course, the practical results wouldn't change much (whatever
the underlying system does would still be used).
A second question is whether we need to define UTC. I presume we're using the
term from some other standard, but here it just appears out of the blue. We
don't ever define it in the AARM notes. An undefined term is supposed to be
in the dictionary or the mathematical reference. I can't check the dictionary
(don't have that one), but it's not in the mathematical reference. It's of
course defined in Wikipedia, but we can't use that in the RM. At a minimum,
we ought to use the full English name "Coordinated Universal Time" once, so
people can look it up.
> Now we can modify 9.6.1(42/3):
>
> Returns, as a number of minutes, [the result of subtracting] the
> implementation-defined time zone of Calendar [from UTC time], at the
> time Date. If the time zone of the Calendar implementation is unknown,
> then Unknown_Zone_Error is raised.
I guess I don't like that this definition no longer has any (obvious)
relationship to UTC. OTOH, if we changed Time_Offset to the GNAT definition,
this would always return 0 (and we'd need to add Local_Time_Offset to the
spec). But I don't have a better idea, so I suppose I should shut up.
****************************************************************
From: Joey Fish
Sent: Wednesday, June 5, 2019 4:03 AM
>This doesn't work for me. You are implying that the value of time is
>time-zone dependent. That is not true on any Unix-like system.
Why is this an issue? Why should the Ada standard's notion of time be at all
linked to Unix? [or Windows, or VMS, or anything?]
In fact, some of the biggest warts are due to importing and accommodating
unix/c follies, with anonymous access types leading the charge.
>I think we need to talk about the number of minutes since the local
>midnight, say, and do the computation in terms of that value, perhaps
>modulo 24*60.
I'm not sure that is a good idea. (I'm currently working night-shift, so I
come in and work before midnight and finish after midnight; so while it's
simple to say "I worked 10 hours" denoting them in "minutes since [local]
midnight" wouldn't be very nice.)
I do know ISO 8601 was recently updated, perhaps looking at that would be
helpful.
****************************************************************
From: Thomas Quinot
Sent: Wednesday, June 5, 2019 4:27 AM
> Modify 9.6.1(40/2):
>
> {For the purposes of this subclause, the /time zone/ for a given locality
> is defined in terms of the number of minutes the local time is ahead (+)
> or behind (-) UTC.} Type Time_Offset represents the number of minutes
> difference between the implementation-defined time zone used by Calendar
> and another time zone.
However keep in mind that if you understand time zone as a single UTC offset
then this depends not just on the locality but also on the specific point in
time, due to daylight saving time issues. (IOW the UTC offset is a function
of both the locality **and the point in tiem**).
****************************************************************
From: Tucker Taft
Sent: Wednesday, June 5, 2019 7:12 AM
>> Modify 9.6.1(40/2):
>>
>> {For the purposes of this subclause, the /time zone/ for a given locality
>> is defined in terms of the number of minutes the local time is ahead (+)
>> or behind (-) UTC.} Type Time_Offset represents the number of minutes
>> difference between the implementation-defined time zone used by Calendar
>> and another time zone.
>
> However keep in mind that if you understand time zone as a single UTC
> offset then this depends not just on the locality but also on the
> specific point in time, due to daylight saving time issues. (IOW the
> UTC offset is a function of both the locality **and the point in
> tiem**).
Good point. That should probably be more explicit, as it is in the
definition of UTC_Time_Offset. Perhaps:
{For the purposes of this subclause, the /time zone/ for a given locality at
a given moment is defined in terms of the number of minutes the local time is,
at that moment, ahead (+) or behind (-) UTC.}
****************************************************************
From: Dirk Craeynest
Sent: Wednesday, June 5, 2019 4:32 AM
> > We probably should start by defining what we mean by "time
> > zone" since the term is used repeatedly. If that definition
> > is described, for the purposes of this section, as a number
> > of minutes the local time is ahead of (+) or behind (-) UTC,
> > then I think the rest becomes trivial.
> >
> > Here is my attempt:
> >
> > Modify 9.6.1(40/2):
> >
> > {For the purposes of this subclause, the /time zone/ for a
> > given locality is defined in terms of the number of minutes
> > the local time is ahead (+) or behind (-) UTC.} Type
> > Time_Offset represents the number of minutes difference
> > between the implementation-defined time zone used by Calendar
> > and another time zone.
> The (minor) problem here is that type Time_Offset and the virtual
> type time zone are very different for no obvious reason. [...]
The definition proposed above is not what is commonly understood by "time
zone" (a region with uniform time), but is a value: the time offset in that
region versus UTC.
Hence using UTC_Time_Offset or UTC_Offset for this value is probably more
appropriate. And that value could then be of type Time_Offset...
(See also https://en.wikipedia.org/wiki/List_of_UTC_time_offsets.)
About:
> Times would work slightly better if UTC was the default time zone
Note that strictly speaking UTC is not a time zone: it is a time standard
(Coordinated Universal Time).
****************************************************************
From: Tucker Taft
Sent: Wednesday, June 5, 2019 3:00 PM
> Hence using UTC_Time_Offset or UTC_Offset for this value is probably
> more appropriate. And that value could then be of type Time_Offset...
I was trying to minimize wording changes here, since we are just fixing a bug.
The existing wording uses the term "time zone" without defining it, and that
has led to some confusion. We could reword this whole section probably, but I
don't think that is justified to just fix this current bug.
****************************************************************
!topic Time_Zone parameter to Calendar.Formatting subprograms
!reference Ada 2012 AARM 9.6.1
!from Simon Wright 2019-05-30
!keywords UTC
!discussion
Many of the subprograms (e.g. Hour) take a Time_Zone parameter which
defaults to 0.
It's been suggested that this default means "in the local time zone".
GNAT's treatment is to regard 0 as meaning "in UTC". This seems
reasonable, since Time_Offset'(0) is what you get when calling
UTC_Time_Offset in time zone GMT.
Neither ARM nor AARM seem to define the behaviour.
****************************************************************
From: Tucker Taft
Sent: Thursday, May 30, 2019 1:49 PM
Doesn't 9.6.1(40/2) answer this question? Here it is:
Type Time_Offset represents the number of minutes difference between
the implementation-defined time zone used by Calendar and another time
zone.
If a value of this type is zero, that implies you are interested in an answer
that is relevant to the time zone used by Calendar. And as you suggest, that
is determined by calling UTC_Time_Offset.
So what additional words would you expect to see in the RM?
****************************************************************
From: Simon Wright
Sent: Thursday, May 30, 2019 3:18 PM
>Doesn't 9.6.1(40/2) answer this question? Here it is:
>
> Type Time_Offset represents the number of minutes difference between
> the implementation-defined time zone used by Calendar and another time
> zone.
>
>If a value of this type is zero, that implies you are interested in an answer
>that is relevant to the time zone used by Calendar. And as you suggest, that
>is determined by calling UTC_Time_Offset.
Given the first sentence, not sure the second is relevant?
I do see what you mean, eventually, but both I and GNAT's implementors seem to
have got it wrong. In my case, perhaps because being in BST at the moment, the
60 minutes difference between BST and UTC is the same as the 60 minutes added
when we went to daylight savings. Or perhaps, UTC being universal, I convinced
myself that a Time_Zone parameter of 0 must mean UTC.
If I run the attached program on GNAT (macOS & Linux) I get
$ date
Thu 30 May 2019 20:55:48 BST
$ ./time_zone
UTC_Time_Offset: 60
Time_Zone default: 2019-05-30 19:55:52
Time_Zone offset: 2019-05-30 20:55:52
so to get local time I had to use Time_Zone => UTC_Time_Offset (Now).
>So what additional words would you expect to see in the RM?
Add to 9.6.1(40/2) "Thus, when 0 is passed as the Time_Zone parameter in
subprograms below, this means to use the time zone used by Calendar."
Alternatively, add to 9.6.1(53/2) "When 0 is passed as the Time_Zone parameter
in this and in subprograms below, this means to use the time zone used by
Calendar."
--- Attached program:
with Ada.Calendar.Formatting;
with Ada.Calendar.Time_Zones;
with Ada.Text_IO;
procedure Time_Zone is
Now : constant Ada.Calendar.Time := Ada.Calendar.Clock;
Offset : constant Ada.Calendar.Time_Zones.Time_Offset
:= Ada.Calendar.Time_Zones.UTC_Time_Offset (Now);
begin
Ada.Text_IO.Put_Line
("UTC_Time_Offset: " & Offset'Image);
Ada.Text_IO.Put_Line
("Time_Zone default: "
& Ada.Calendar.Formatting.Image (Now));
Ada.Text_IO.Put_Line
("Time_Zone offset: "
& Ada.Calendar.Formatting.Image (Now, Time_Zone => Offset));
end Time_Zone;
****************************************************************
From: Tucker Taft
Sent: Thursday, May 30, 2019 5:16 PM
>>Doesn't 9.6.1(40/2) answer this question? Here it is:
>>
>> Type Time_Offset represents the number of minutes difference between
>> the implementation-defined time zone used by Calendar and another time
>> zone.
>>
>>If a value of this type is zero, that implies you are interested in an answer
>>that is relevant to the time zone used by Calendar. And as you suggest, that
>>is determined by calling UTC_Time_Offset.
>
>Given the first sentence, not sure the second is relevant?
I am not sure what the above refers to. There are three sentences above, one
copied from the reference manual, and two that were my conclusions based on
that. What did you think was not relevant?
>I do see what you mean, eventually, but both I and GNAT's implementors seem to
>have got it wrong. In my case, perhaps because being in BST at the moment, the
>60 minutes difference between BST and UTC is the same as the 60 minutes added
>when we went to daylight savings. Or perhaps, UTC being universal, I convinced
>myself that a Time_Zone parameter of 0 must mean UTC.
But it seems pretty clear from the description that a time zone parameter of 0
means "Calendar's timezone." Of course, what does it mean to talk about
Calendar's timezone if time (as returned by Calendar.Clock) is internally
*always* number of seconds since some absolute time in the past? Well it is
defined by what "Calendar.Split" does. An invariant should be that
Calendar.Split and Calendar.Formatting.Split return essentially the same thing
when the Time_Offset parameter is zero.
>If I run the attached program on GNAT (macOS & Linux) I get
>
>
>$ date
>Thu 30 May 2019 20:55:48 BST
>$ ./time_zone
>UTC_Time_Offset: 60
>Time_Zone default: 2019-05-30 19:55:52
>Time_Zone offset: 2019-05-30 20:55:52
>
>so to get local time I had to use Time_Zone => UTC_Time_Offset (Now).
That seems a bit weird. Of course what the system "date" program does is
another question -- it need not match what Calendar.Split does. But based on
your program, it looks like Calendar.Formatting.Image when given an offset of
zero gives UTC, even though the UTC_Time_Offset indicates that Calendar.Split
gives BST. So somebody is lying!
>So what additional words would you expect to see in the RM?
>
>Add to 9.6.1(40/2) "Thus, when 0 is passed as the Time_Zone parameter in
>subprograms below, this means to use the time zone used by Calendar."
So, to be clear, this is formally redundant with what is there now -- you just
are suggesting it would help clarify the meaning?
>Alternatively, add to 9.6.1(53/2) "When 0 is passed as the Time_Zone
>parameter in this and in subprograms below, this means to use the time zone
>used by Calendar."
So again, you are not saying there is anything wrong, but are suggesting that
this extra wording would be helpful for understanding. Am I understanding you
correctly?
<time_zone.adb>
There does seem to be a bug in the RM 9.6.1(42/3) (from your other Ada Comment)
about the definition of UTC_Time_Offset which should be <calendar-time> - UTC,
rather than UTC - <calendar-time>, and perhaps also a bug in GNAT, in that if
Time_Zone => 0, then you should be getting the same info as returned by
Calendar.Split when you call Calendar.Formatting.Image/Split/etc.
Clearly not too many folks are using this Calendar.Formatting package!
****************************************************************
From: Randy Brukardt
Sent: Friday, May 31, 2019 12:05 AM
> That seems a bit weird. Of course what the system "date" program does
>is another question -- it need not match what Calendar.Split does. But
>based on your program, it looks like Calendar.Formatting.Image when
>given an offset of zero gives UTC, even though the UTC_Time_Offset
>indicates that Calendar.Split gives BST. So somebody is lying!
This is indeed the exact problem. This came up with Simon was trying to use
my GNAT grading tools on his Linux box. One of the tools is called "Tstamp"
which just outputs a formatted time stamp to Standard Output. Simon was
having problems because the time reported by the tests (via the ACATS Report
package didn't match that of Tstamp.
The ACATS Report package originated in Ada 83 and thus uses Ada.Calendar.Split
to display a time value.
When I wrote Tstamp, since it only needed to work with GNAT, I simplified my
life and used Ada.Calendar.Formatting.Image. On Windows, I got the same result
for each (although I'm not certain which *compiler* I used to compile Tstamp).
But that isn't true on Linux, apparently.
>>> So what additional words would you expect to see in the RM?
>>Add to 9.6.1(40/2) "Thus, when 0 is passed as the Time_Zone parameter
>>in subprograms below, this means to use the time zone used by Calendar."
>So, to be clear, this is formally redundant with what is there now --
>you just are suggesting it would help clarify the meaning?
I couldn't convince myself that it was "formally redundant" as you claim, and
I obviously failed to convince Simon. In any event, someone didn't understand
it and it would help to say this.
Note that this case could be (and should be!) tested by an ACATS test, but I
would want to be sure that we all agree that the RM says Time_Zone => 0 means
Calendar's time zone before spending the effort on it. (Essentially, call
Calendar.Split on a time, and make sure that Calendar.Formatting.Split with
the default time zone of 0 gets the same answers, as well as
Calendar.Formatting.Image.)
...
>There does seem to be a bug in the RM 9.6.1(42/3) (from your other Ada
>Comment) about the definition of UTC_Time_Offset which should be
><calendar-time> - UTC, rather than UTC - <calendar-time>, and perhaps
>also a bug in GNAT, in that if Time_Zone => 0, then you should be
>getting the same info as returned by Calendar.Split when you call
>Calendar.Formatting.Image/Split/etc.
>
>Clearly not too many folks are using this Calendar.Formatting package!
The ACATS grading tools do use it. It would be good for it to work the same on
all compilers (and certainly on all GNATs), else the grading tools will be
wonky.
****************************************************************
From: Simon Wright
Sent: Friday, May 31, 2019 7:50 AM
...
>>>If a value of this type is zero, that implies you are interested in an answer
>>>that is relevant to the time zone used by Calendar. And as you suggest, that
>>>is determined by calling UTC_Time_Offset.
>>
>>Given the first sentence, not sure the second is relevant?
>
>I am not sure what the above refers to. There are three sentences above, one
>copied from the reference manual, and two that were my conclusions based on
>that. What did you think was not relevant?
I meant the 2nd and 3rd sentences, sorry. I think the conclusion of the
discussion (so far) is that if (2nd sentence) I want answers relevant to
Calendar's time zone I just supply an offset of 0, (3rd sentence) no need to
invoke UTC_Time_Offset at all.
...
>So again, you are not saying there is anything wrong, but are suggesting that
>this extra wording would be helpful for understanding. Am I understanding
>you correctly?
Yes, exactly.
>Clearly not too many folks are using this Calendar.Formatting package!
Or maybe GNAT users, including myself, are being lazy & adopting a "suck it
and see" approach.
****************************************************************
From: Tucker Taft
Sent: Friday, May 31, 2019 3:11 PM
...
>I meant the 2nd and 3rd sentences, sorry. I think the conclusion of the
>discussion (so far) is that if (2nd sentence) I want answers relevant to
>Calendar's time zone I just supply an offset of 0, (3rd sentence) no need
>to invoke UTC_Time_Offset at all.
No need to do so, but if you wanted to find out what was the timezone of
package Calendar, you could use UTC_Time_Offset to do so,
...
>>So again, you are not saying there is anything wrong, but are suggesting
>>that this extra wording would be helpful for understanding. Am I
>>understanding you correctly?
>Yes, exactly.
OK, thanks for clarifying.
>>Clearly not too many folks are using this Calendar.Formatting package!
>Or maybe GNAT users, including myself, are being lazy & adopting a "suck it
>and see" approach.
Could be!
****************************************************************
From: Randy Brukardt
Sent: Tuesday, June 4, 2019 9:36 PM
> If I run the attached program on GNAT (macOS & Linux) I get
>
> $ date
> Thu 30 May 2019 20:55:48 BST
> $ ./time_zone
> UTC_Time_Offset: 60
> Time_Zone default: 2019-05-30 19:55:52
> Time_Zone offset: 2019-05-30 20:55:52
>
> so to get local time I had to use Time_Zone => UTC_Time_Offset
(Now).
If I run this program on Janus/Ada on Windows, I get:
D:\Testing\Win\console>time
The current time is: 21:11:22.97
Enter the new time:
D:\Testing\Win\console>tz
UTC_Time_Offset: -300
Time_Zone default: 2019-06-04 21:11:28
Time_Zone offset: 2019-06-05 02:11:28
But if I run the program using GNAT, I get:
D:\Testing\Win\console>time
The current time is: 21:15:00.35
Enter the new time:
D:\Testing\Win\console>tz
UTC_Time_Offset: -300
Time_Zone default: 2019-06-05 02:15:02
Time_Zone offset: 2019-06-04 21:15:02
Wonder what ObjectAda does?
****************************************************************
From: Randy Brukardt
Sent: Wednesday, June 5, 2019 6:31 PM
> Wonder what ObjectAda does?
I sent PTC and Irvine this program (being the only other Ada 2005 compilers I
know of).
Irvine responded that they don't implement Ada.Calendar.Formatting.
PTC sent a bunch of test results (in pretty screen grabs that I can't
reasonably reproduce here). They pointed out that Simon had used the
Object'Image, which is only a Ada 2012/TC1 feature. After fixing that
problem, they reported the following results (hand keyed from the graphics,
so if they don't make sense, blame me, not PTC).
For ObjectAda 10.1:
[...]> date
Wed Jun 5 10:29:48 PDT 2019
[...]> time_zone.exe
UTC_Time_Offset: -420
Time_Zone default: 2019-06-05 17:29:52
Time_Zone offset: 2019-06-05 10:29:52
----
For ApexAda v5.2:
[...]$ date
Wed Jun 5 12:49:48 EDT 2019
[...]$ ./timezone
UTC_Time_Offset: -480
Time_Zone default: 2019-06-05 12:49:55
Time_Zone offset: 2019-06-05 04:49:55
They also ran a copy of the ObjectAda program in France, giving:
[...]> date
Wed Jun 5 10:29:48 PDT 2019
[...]> time_zone.exe
UTC_Time_Offset: 120
Time_Zone default: 2019-06-05 08:49:07
Time_Zone offset: 2019-06-05 10:49:07
=========================================================
Conclusion: I'm apparently the only one that actually read the RM definition
and implemented it exactly. Everyone else implemented the Time_Zone value as
being an offset from UTC, or didn't implement it at all.
Given the disruption inherent in forcing almost every compiler to change to
the intended definition (which would break any existing code that is expecting
a particular result, other than mine!), I think we have no choice but to
revise the definition of Time_Offset to match that Tucker called "time zone".
This is annoying in that the intent was that the default for Image would be
the local time (not UTC). Short of adding additional routines, though, I don't
see a way to do that and also change the RM meaning of Time_Offset.
So, I would propose the following changes:
(1) Change the definition of Time_Offset to match that Tucker used for
"time zone". We probably could drop that definition.
(2) Add a renaming of UTC_Time_Offset called Local_Time_Offset (which is a
better name for this concept after the inversion of the meaning of
Time_Offset).
(3) Add Local_Image, which would be defined to be Image (Time,
Include_Time_Fraction, Local_Time_Offset(Time));
Perhaps we should add a matching Local_Value, but that's problematical to
define as the time offset to use possibly depends on the result. (It's much
less likely to be a problem in practice, so maybe some English definition is
enough.)
I don't think it pays to add Local_ versions of all of the Time_Of and Split
routines, as there are five of them (and the definition of Local_Time_Of
would have the same problem as Local_Value).
What do you all think???
****************************************************************
From: Joey Fish
Sent: Thursday, June 6, 2019 3:49 AM
> This is annoying in that the intent was that the default for Image would be
> the local time (not UTC). Short of adding additional routines, though, I
> don't see a way to do that and also change the RM meaning of Time_Offset.
I think the image should be in local time, isn't that [messing around with UTC
and such] what the formatting/time_zones/conversion children of Ada.Calendar
are about?
****************************************************************
From: Tucker Taft
Sent: Thursday, June 6, 2019 12:53 PM
Perhaps we could add a default for UTC_Time_Offset/Local_Time_Offset to be
Calendar.Clock? Then you can just write "Local_Time_Offset" and use it as a
default on a renaming of some of these routines to be Local_*.
Too bad this was so unclear to begin with, but it sounds like there couldn't
have been much use of these features so far, given the semi-random results
that are produced.
****************************************************************
From: Randy Brukardt
Sent: Thursday, June 6, 2019 3:10 PM
> Perhaps we could add a default for
> UTC_Time_Offset/Local_Time_Offset to be Calendar.Clock?
That *is* the default to UTC_Time_Offset.
> Then
> you can just write "Local_Time_Offset" and use it as a default on a
> renaming of some of these routines to be Local_*.
I thought of that, but it would be wrong for Local_Image and the like, as it
wouldn't take into account time zone changes (i.e. summer/daylight saving
time) for some times. For *inbound* times, it seems nasty to get the time
zone wrong just so we can write a renaming. After all, the reason for having
a time parameter is to avoid that sort of glitch. (And since Clock is
relatively expensive, it probably would be faster to use the passed in time
-- not that that would often matter.)
We could do that for *outbound* items (Value and Time_Of), should we try to
support those.
> Too bad this was so unclear to begin with, but it sounds like there
> couldn't have been much use of these features so far, given the
> semi-random results that are produced.
Well, all of the compilers 'cept mine do the same thing (and mine hasn't been
released yet), so its probably the case that most users got a surprising
answer once, changed their code, and moved on. This probably never would have
shown up had I not created a library that actually followed the RM and then
used it in a publicly posted program. When someone (Simon) tried to use the
program on GNAT, then the difference showed up, and Simon was good enough to
raise it here (I don't know that I would have).
So it's quite possible this stuff is used a decent amount, just with a
different expectation than the RM has.
****************************************************************
From: Randy Brukardt
Sent: Thursday, June 6, 2019 8:33 PM
>>This is annoying in that the intent was that the default for Image would be
>>the local time (not UTC). Short of adding additional routines, though,
>>I don't see a way to do that and also change the RM meaning of Time_Offset.
>I think the image should be in local time, isn't that [messing around
>with UTC and such] what the formatting/time_zones/conversion children
>of Ada.Calendar are about?
True, but we also have an obligation to standardize existing practice when
possible. Do we want to break everyone's code in this area?
I'm suggesting that we split the baby by defining Local_Image to give the
Calendar result and leave the existing Image to do what it does on all of the
existing compilers except mine. (And note that Image is already in the
"formatting/time_zones/conversion children of Ada.Calendar"; we're not talking
about any change to Ada.Calendar.) It's not perfect but it is the least
disruptive option. (It also would allow Ada runtimes to represent Time
primarily in UTC time internally; I suspect that is the cause of this
confusion.)
***************************************************************
Questions? Ask the ACAA Technical Agent