I use
Offset : Constant Time_Offset := UTC_Time_Offset;
and include "Time_Zone=>Offset" in calendar routines
(for example in the functions Time_Of, Split, Value
within the packages Ada.Calendar.Formatting and
Ada.Calendar.Time_Zones).
I find this a but "artificial". How should one do it?
reinert
Sorry for bringing you bad news, but unfortunately there is no way to
handle UTC in Ada. The standard is broken in this respect. I discussed this
in this group earlier and in Ada-Comment too.
The short answer is that if you wanted to deal with UTC, you should have a
look at the implementation of Ada.Calendar.Time provided by your compiler
and then act accordingly.
A longer answer is that UTC_Time_Offset is not necessarily constant. Thus
your way is possibly wrong. Here we come to the inconsistency of the
standard. How does UTC_Time_Offset depend on Time in its turn depends on
what is *Time*. Your solution presumes that Time is UTC (i.e. UTC +
constant offset). This might be wrong, because the standard gives strong
indications that Time is in fact local time = political time. In this case
the offset would depend on the current UTC, and could not depend on Time as
the function UTC_Time_Offset pretends. Offset is not a function of
political time (it is not a function at all). In short, it is broken.
I cannot tell for sure, but it seems that GNAT implementation is Time =
UTC. I.e. Clock does not jump when daylight saving time comes and thus
Split may yield rubbish...
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Dmitry raises some issue which I'm sure the ARG are looking at but you
_might_ be perfectly ok if all you're doing reading log files, etc and
not actually trying to combine this with a clock your program is
reading and expecting them to tie together with the time on your wrist
watch. And if your log didn't come from a run over summer-time
changes, leap seconds etc on an OS that actually dealt with such
things.
Cheers
-- Martin
So you say that if I make sure nobody runs my program code
on an advanced computer over summer-time changes, leap seconds etc
- my program may go correct ?
reinert
> What is the "natural"/best way to make an Ada program treat
> time/calendar data in UTC ? The quetion is about treating old
> measurements/data tagged with UTC time.
In that case I would probably load the data into a data structure
composed with the necessary precision and ranges. It might make sense
to reuse some of the subtypes from Ada.Calendar when constructing the
data structure.
Greetings,
Jacob
--
Beware of people with Gnus, they may Hurd you.
Without know what you're doing it's hard to say. If you're just using
UTC as a timetag then absolutely you should be ok.
The problems are when the 'real world' goes and changes what 'time' is
- e.g. clocks going forward and backwards, inserting leap seconds.
These sort of things make sensible time computations hard, e.g. what
does "1:30am" mean if the clocks have gone back an hour for winter at
2am? Is it the first 1:30am or the second that night? (can't remember
if it 2am->1am or 3am->2am or something else but you get the idea).
Also leap seconds are interested into OS tables 'retrospectively' - if
you are interested in the difference between to time and need seconds
or better accuracy you again could be in trouble. Do you know your OS
accounts for leap-seconds? If so, do you know if the leap seconds
table is up-to-date?
Cheers
-- Martin
> These sort of things make sensible time computations hard, e.g. what
> does "1:30am" mean if the clocks have gone back an hour for winter at
> 2am? Is it the first 1:30am or the second that night?
I'd say that depends on the OS you run your program on (and its
configuration).
On a Linux system with hardware clock configured to run on UTC, this isn't a
problem, because the real (local) time is calculated from this and the
timezone setting.
OTOH, on a Linux system configured to run on local time, it may be as you
describe (I never ever did that so I don't know for sure).
Bye...
Dirk
Exactly - and the times in the original question may not even have
come from the computer doing the calculations - they could be a log
from e.g. a Sat Nav - what would it be doing?
Cheers
-- Martin
I did hope I could use the Ada calendar routines to process
"historical" data tagged with UTC - independent of where
in the world I run the program.
I (at least) want my computations to be independent of the local
time of the computer. My program should e.g. give the same result
when running on a computer in Alaska or Australia. 2 + 2 = 4 all
over the world ! :-) And I was born 12 March UTC independet of
the "local time" of my computer !
Yes, I know that UTC has its weakness that has to be considered
in applications. Anyway, when giving an UTC date/time to a computer
program, this should not be affected if the computer change time zone
when processing? A travelling computer may run a program many days
and while it is passing many time zones. Consider, for examlpe,
a web camera/sensor related program on a car/truck driving from coast
to coast in USA or Canada ! One has frequently to update
UTC_Time_Offset
in order to handle input data correct if one wants to tagg events
with UTC?
reinert
>Anyway, when giving an UTC date/time to a computer program, this should
>not be affected if the computer change time zone when processing? A
>travelling computer may run a program many days and while it is passing
>many time zones.
Ada.Calendar.Clock can only give your program a reading of the
computer's clock. If you keep changing the computer's clock as you
travel, you will need to inform the data logging program of each change in
UTC offset. The simpler approach would be to set the computer's clock to
UTC at the beginning of the trip and not change it as you travel.
> Ada.Calendar.Clock can only give your program a reading of the
> computer's clock. If you keep changing the computer's clock as you
> travel, you will need to inform the data logging program of each change in
> UTC offset. The simpler approach would be to set the computer's clock to
> UTC at the beginning of the trip and not change it as you travel.
I know this is what Windows[1] does, but it isn't what a Real OS (tm)
would do (I know there are problems if you dual-boot with Windows and
a real OS, better to use VMware running on your native OS perhaps).
[1] Has Vista been fixed in this respect?
What I mean is that one should keep the internal clock set to UTC (I'm
not being picky about leap seconds here, if the OP needs to be that
will perhaps be more complicated) and change the time zone setting to
correspond to the time zone in which one finds oneself.
The last time I ran Windows outside a virtual environment it would
change the system (bios) clock on DST change. I don't know what it
does if you change the TZ.
TZ/DST info updates (caused by political changes) appear magically
through the ether from one's OS vendor.
with Text_IO,Ada.Calendar,Ada.Calendar.Formatting;
use Text_IO,Ada.Calendar,Ada.Calendar.Formatting;
procedure t1 is
package Int_Io is new Text_IO.Integer_Io (Integer);
use Int_Io;
Time1 : Time;
begin
Time1 := Value("1970-01-01 00:00:00");
Put(Image(Time1));New_Line;
Put(Image(Ada.Calendar.Time_Of(1970,1,1,Duration(0))));
end t1;
This gives (on my linux computer):
1970-01-01 00:00:00
1969-12-31 23:00:00
The last output line here reflects the fact that Ada takes
"local time" from the computer - and the result would be
different if I wait to run my program till next Monday
(this weekend we change to summer daylight saving time).
I would expect that time zones should be explicite - and this would
help programmers to avoid misstakes (which is an argument for Ada).
I made and error due to this my confusion - am I just to much of a
newbie ?
reinert
No. It reflects the fact that Image takes an Ada.Calendar.Time_Zones.Time_Offset
parameter (Time_Zone) that defaults to 0 (UTC). Image is therefore converting
the supplied time from your computer's offset
(Ada.Calendar.Time_Zones.UTC_Time_Offset) to the default offset of 0. Your
offset seems to be 60 (GMT + 1 hr). To get the image of what you passed to it,
you must specify an offset of UTC_Time_Offset.
The 1st value comes out as expected because Value also takes an
Ada.Calendar.Time_Zones.Time_Offset parameter (Time_Zone) that defaults to 0
(UTC). It is therefore taking the supplied string, interpreting it as a time in
UTC, and converting it to the corresponding time for your computer's offset
(UTC_Time_Offset). When you pass this time to Image with the default for
Time_Zone, the conversion is then reversed as described above.
You can compare the representations provided by Image with the values obtained
by Ada.Calendar.Split to observe the conversions that the operations in
Ada.Calendar.Formatting perform.
Two comments on your code: "with Ada.Calendar.Formatting;" makes Ada,
Ada.Calendar, and Ada.Calendar.Formatting visible; there is no need to also with
Ada.Calendar.
I cannot understand why you would say "Duration (0)" when "0.0" is clearer and
shorter.
--
Jeff Carter
"My mind is a raging torrent, flooded with rivulets of
thought, cascading into a waterfall of creative alternatives."
Blazing Saddles
89
I thought "Offset" was reletive to UTC - not relative
to the "local" time.
So
Time1 := Value("1970-01-01 00:00:00",Time_Zone => UTC_Time_Offset);
gives UTC for the local "input" time "1970-01-01 00:00:00" ?
How do I best "input"/enter UTC time (so a reader of the program
also understand it - an independent of the computer local time)?
reinert
On 27 Mar, 18:58, "Jeffrey R. Carter"
------------------------------------------------
with Text_IO;
use Text_IO;
with Ada.Calendar.Formatting,Ada.Calendar.Time_Zones;
use Ada.Calendar,Ada.Calendar.Formatting,Ada.Calendar.Time_Zones;
procedure t1 is
package Int_Io is new Text_IO.Integer_Io (Integer);
use Int_Io;
Time1,Time2 : Time;
begin
Time1 := Value("1970-01-01 00:00:00");
Time2 := Ada.Calendar.Time_Of(1970,1,1,0.0);
Put("Time1: ");Put(Image(Time1));New_Line;
Put("Time2: ");Put(Image(Time2));New_Line;
Put("UTC_Time_Offset: ");Put(Integer(UTC_Time_Offset),8);
end t1;
------------------------------------
This gives the following output on my computer:
Time1: 1970-01-01 00:00:00
Time2: 1969-12-31 23:00:00
UTC_Time_Offset: 120
The first line I now understand reflects that both "Value"
and "Image" has parameter Time_Zone = 0 (UTC). I.e. "Time1"
can be understood to have value 1970-01-01 00:00:00 (UTC).
"But "Time2" is 1970-01-01 00:00:00 *minus* one hour (only), and
UTC_Time_Offset = 120 (2 hours).
I would expect that it should be UTC - 2 hours
(i.e. 1969-12-31 22:00:00 and *not* 1969-12-31 23:00:00) ?
I here fight with my intuition :-)
reinert
On 27 Mar, 18:58, "Jeffrey R. Carter"
<spam.jrcarter....@nospam.acm.org> wrote:
Time1 uses Ada.Calendar.Formatting.Value, with a default Time_Zone of 0.
In contrast, Time2 is the result ofAda.Calendar.Time_Of, which is local
time. I'm guessing you're on Summer (Daylight) time, now; but back on
New Year's day of 1970, you were on standard time.
Here is an example that highlights some of the differences:
with Ada.Calendar; use Ada.Calendar;
with Ada.Calendar.Formatting;
with Ada.Calendar.Time_Zones;
use type Ada.Calendar.Time_Zones.Time_Offset;
with Ada.Text_IO; use Ada.Text_IO;
procedure Times is
T : Time := Clock;
D : Time_Zones.Time_Offset;
begin
D := Time_Zones.UTC_Time_Offset(T);
Put("UTC_Time_Offset: "); Put(D'Img); New_Line;
Put("GMT: "); Put(Formatting.Image(T)); New_Line;
Put("Local: "); Put(Formatting.Image(T, False, D)); New_Line;
Put_Line("--");
T := Time_Of(1970, 1, 1, 0.0);
Put(Formatting.Image(T)); New_Line;
Put(Formatting.Image(T, False, -300)); New_Line;
Put_Line("--");
T := Formatting.Time_Of(1970, 1, 1, 0.0);
Put(Formatting.Image(T)); New_Line;
Put(Formatting.Image(T, False, -300)); New_Line;
Put(Formatting.Image(T, False, +60)); New_Line;
end times;
Here's what I see in a New York time zone:
./times
UTC_Time_Offset: -240
GMT: 2009-03-30 13:43:26
Local: 2009-03-30 09:43:26
--
1970-01-01 05:00:00
1970-01-01 00:00:00
--
1970-01-01 00:00:00
1969-12-31 19:00:00
1970-01-01 01:00:00
> I here fight with my intuition :-)
You may want to use the "use" clause a little more sparingly
--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
No, as I understand it, this gives the system time equivalent of 1970-01-01
00:00:00 in a location where the local time offset is UTC_Time_Offset at that
time. Note that UTC_Time_Offset is the current offset for the system; it may be
different from the system's offset at the given time.
> How do I best "input"/enter UTC time (so a reader of the program also
> understand it - an independent of the computer local time)?
If I understand your problem correctly, you only want to input and output UTC
times, and perform basic arithmetic on them. You never want to mix UTC with
local/zoned times.
I'd probably limit myself to the operations in Ada.Calendar. You'll need to
create your own Image and Value operations (PragmARC.Date_Handler may be helpful
for that). The operations in Ada.Calendar (except Clock) are ignorant of time
zones, and so will give you meaningful values.
If you need to mix UTC with time zones then things get more complicated.
The PragmARCs are at
http://pragmada.home.mchsi.com/
--
Jeff Carter
"I don't know why I ever come in here. The
flies get the best of everything."
Never Give a Sucker an Even Break
102
I suspect you've recently gone on
daylight-savings/summer/whatever-it's-called-where-you-are time, which is UTC
+02:00 (120 mins), but on 1970 Jan 01 you were on regular time, which is UTC +01:00.
And giving the argument "Time1" to UTC_Time_Offset" like this:
UTC_Time_Offset(Time1)
insted of only UTC_Time_Offset (which is the same
as "UTC_Time_Offset(Clock))", then I get consistency:
Time1: 1970-01-01 00:00:00
Time2: 1969-12-31 23:00:00
UTC_Time_Offset: 60
Lesson learned: "remember the argument for UTC_Time_Offset" ! :-)
reinert
PS, new program code:
-----------------------------------------------------------------------------
with Text_IO;
use Text_IO;
with Ada.Calendar.Formatting,Ada.Calendar.Time_Zones;
-- with Ada.Calendar.Aritmetric;
use Ada.Calendar,Ada.Calendar.Formatting,Ada.Calendar.Time_Zones;
procedure t1 is
package Int_Io is new Text_IO.Integer_Io (Integer);
use Int_Io;
Time1,Time2 : Time;
begin
Time1 := Value("1970-01-01 00:00:00");
Time2 := Ada.Calendar.Time_Of(1970,1,1,0.0);
Put("Time1: ");Put(Image(Time1));New_Line;
Put("Time2: ");Put(Image(Time2));New_Line;
Put("UTC_Time_Offset: ");Put(Integer(UTC_Time_Offset(Time1)),8);
end t1;
On 30 Mar, 18:52, "Jeffrey R. Carter"
Assuming the "Real OS (tm)"'s user knows how to set this up (from a
non-eunich who uses a pre-installed Linus that apparently doesn't - the 2nd
distribution that I installed does, and the combination does bad things with
the BIOS clock).
> The last time I ran Windows outside a virtual environment it would
> change the system (bios) clock on DST change. I don't know what it
> does if you change the TZ.
Have you ever checked your MS EULAs to see if running Windows inside a
virtual environment is allowed? (During setup of my latest PC, I was bored
and actually read it - that is explicitly not allowed for Vista, don't know
about previous versions. This despite comments in MS's knowledgebase
articles that imply it's normal.)
--Brian
-- You can surrender without a prayer;
-- but you can never really pray without surrender.
-- You can fight without ever winning;
-- but you can never ever win without a fight.