comp.lang.ada
 help / color / mirror / Atom feed
From: "Marc A. Criley" <mcNOSPAM@mckae.com>
Subject: Dates and Times in GNAT on Linux
Date: Sun, 13 Sep 2009 10:36:58 -0500
Date: 2009-09-13T10:36:58-05:00	[thread overview]
Message-ID: <95e64$4aad119b$4a336034$30511@API-DIGITAL.COM> (raw)

I'm confused about GNAT's implementation of some aspects of date/time 
processing on Linux. I'm running GNAT GPL 2009 on Ubuntu Linux; I also 
live in the US Central Time Zone and Daylight Savings Time is in effect 
as I write this.

This is probably a stupid misunderstanding or mistaken expectations or 
feature misuse on my part, but I would really like to know what's going on.

Basically what I'm trying to do is take the time I got from from 
Ada.Real.Clock and convert it to a date/time rep.  The result I'm coming 
up with is always an hour off. (DST effect? Read on...) Code will follow 
in a bit.

I discovered that GNAT's implementation of Ada.Real_Time.Clock returns 
the number of seconds since the UTC epoch start, which is very nice and 
very handy.  Using Real_Time.Split I can get that number of seconds into 
a visible type, Seconds_Count.

I can then get the start of the Unix/UTC epoch via:
    UTC_Epoch_Start := Calendar.Time_Of(1970, 1, 1)
                         + Duration(Calendar.Time_Zones.UTC_Offset * 60);
    -- For where I live, right now the UTC_Offset is -300 minutes,
    -- i.e. -5 hours.

Adding the Real_Time seconds count (as a Duration) to UTC_Epoch_Start 
gives a Calendar.Time value containing the current UTC time, from which 
I can generate an image...which is an hour off from the correct value.

So I'm thinking it might be a DST problem, but shouldn't the affected 
Calendar procedures be taking that into account?

I saw that the Ada.Calendar package body uses a C function, 
__gnat_localtime_tzoff(), which has "Parameter 'off' captur[ing] the UTC 
offset which is either retrieved from the tm struct or calculated from 
the 'timezone' extern and the tm_isdst flag in the tm struct." Looking 
at the code for this function it appears that _for_Linux_ the 
implementation ignores the "tm_isdst" value and just uses the 
"tm_gmtoff" value, while for some other Unices it does look at tm_isdst.

I'd like to think there's a good reason for doing that--including me 
being an idiot--but I don't see what's going on. And unfortunately I 
don't yet have a support contract with AdaCore :-)

I hacked together some C and Ada examples to illustrate this:

tmt.c:

#include <time.h>
#include <stdio.h>


void tmt_c_time(time_t rt_secs)
{
   struct tm *local;
   time_t t;

   t = time(NULL);
   printf("secs %d\n", t);
   local = localtime(&t);
   printf("Local time and date: %s\n", asctime(local));
   local = gmtime(&t);
   printf("UTC time and date: %s\n", asctime(local));

   t =  rt_secs;
   printf("rt secs %d (from Ada)\n", t);
   local = localtime(&t);
   printf("Local time and date: %s\n", asctime(local));
   local = gmtime(&t);
   printf("UTC time and date: %s\n", asctime(local));
}

$ gcc -c -g tmt.c

tmtada.adb:

with Text_IO; use Text_IO;

with Ada.Real_Time;  use Ada.Real_Time;
with Ada.Calendar.Formatting;  use Ada.Calendar.Formatting;
with Ada.Calendar.Time_Zones;  use Ada.Calendar.Time_Zones;

procedure Tmtada is

    T : Time := Clock;

    Seconds : Seconds_Count;
    Span    : Time_Span;

    Cal_Time : Ada.Calendar.Time;

    UTC_Epoch : Ada.Calendar.Time;

    procedure Tmt_C_Time(Rt_Secs : Seconds_Count);
    pragma Import(C, Tmt_C_Time, "tmt_c_time");

    use Ada.Calendar;

begin
    Split(T, Seconds, Span);
    Put_Line("Seconds since epoch:" & Seconds'Img);

    UTC_Epoch := Ada.Calendar.Time_Of(1970, 1, 1) +
      Duration(UTC_Time_Offset * 60);
    Cal_Time := UTC_Epoch + Duration(Seconds);

    Put_Line("Time Image          " & Image(Cal_Time));

    New_Line;
    Put_Line("Via C...");
    Tmt_C_Time(Seconds);
end Tmtada;

$ gnatmake -g tmtada -largs tmt.o

Here's what I get from a run:

[95] Marc say: ./tmtada
Seconds since epoch: 1252855814
Time Image          2009-09-13 16:30:14

Via C...
secs 1252855814
Local time and date: Sun Sep 13 10:30:14 2009

UTC time and date: Sun Sep 13 15:30:14 2009

rt secs 1252855814 (from Ada)
Local time and date: Sun Sep 13 10:30:14 2009

UTC time and date: Sun Sep 13 15:30:14 2009

Maybe my conversion from Real_Time.Time to Calendar.Time is flawed...I 
don't know.  Any explanation or clarifications would be much appreciated.

Marc A. Criley
Mckae Technologies
www.mckae.com



             reply	other threads:[~2009-09-13 15:36 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-09-13 15:36 Marc A. Criley [this message]
2009-09-13 16:17 ` Dates and Times in GNAT on Linux Dmitry A. Kazakov
2009-09-13 19:35 ` Jeffrey R. Carter
2009-09-13 20:41   ` Marc A. Criley
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox