Unix time, UTC time and Time offset

Hello,

I have a TGraph with unix time on the horizontal axis. To display the correct date I am using as offset:
SetTimeOffset("%F 1970-01-01 00:00:00");

in this way the date (day, month, year) is correct but the hour is still one hour larger than it should be: for example I got 16:52:00 when I am expecting 15:52:00 (GMT+1) (or 14:52:00 UTC, so the problem is not the time zone). Then I tried to modify the offset and I found an odd behaviour:
with %F 1970-01-01 01:00:00 I still got 16:52
with %F 1970-01-01 02:00:00 I got 17:52
and so on.
with %F 1970-01-01 00:01:00 I still got 16:52
with %F 1969-31-12 23:00:00 I still got 16:52

So it looks like that if the offset is less than one hour after 1970-01-01 at midnight, it does not work properly. Indeed in the root manual it is stated that the offset should be larger than year 1995 so I am already well outside the accepted values, in any case, since unix time is a frequently used timestamp, I am wondering if there is a solution a part from the one I am going to adopt: subtract the unix time of a date well after year 1995 and then use this date as offset.

                         Thanks

                               Andrea

What is the ROOT version you are using ? on which platform ? can you provide a small macro reproducing the problem ?

the version is 5.18.00 on lxplus. I attach a macro where a TGraph is drawn with three different time offset. The first two looks identical even if the offset are one hour apart. The right time should be 15:52 GMT+1 but I did not get it.

                               Andrea

example.C (767 Bytes)

what date are supposed to be:

float x[]={1204210366,1204210396};

I get 2008 16:51 with the offset: 1970-01-01 00:00:00
is that correct ?

They should be 28 Feb 2008 15:52 (GMT+1) and 28 Feb 2008 15:53 (GMT+1).

                      Andrea

with:

{
float x[]={1204210366,1204210396};
float y[]={1.,2.};

new TCanvas("c1","c1");                                      

TGraph mgr(2,x,y);
mgr.SetMarkerStyle(20);

mgr.Draw("ap");
mgr.GetXaxis()->SetTimeDisplay(1);
mgr.GetXaxis()->SetNdivisions(-503);
mgr.GetXaxis()->SetTimeFormat("%Y %H:%M %F 1970-01-01 00:00:00");   
}

I get the attached plot. Looks correct to me.


The correct time is 15:52 and 15:53 not 16:52 and 16:53.

If you try with 1970-01-01 01:00:00 as offset you will get the same plot.

                              Andrea

I think you should use “gmt” like in the following example:

{
   TDatime da1(2008,02,28,15,52,00);
   TDatime da2(2008,02,28,15,53,00);

   float x[2],y[2];

   y[0] = 1.;
   y[1] = 2.;
   x[0] = da1.Convert();
   x[1] = da2.Convert();

   TGraph mgr(2,x,y);
   mgr.SetMarkerStyle(20);

   mgr.Draw("ap");
   mgr.GetXaxis()->SetTimeDisplay(1);
   mgr.GetXaxis()->SetNdivisions(-503);
   mgr.GetXaxis()->SetTimeFormat("%Y-%m-%d %H:%M"); 
   mgr->GetXaxis()->SetTimeOffset(0,"gmt");
}

Thanks, it works

                 Andrea

Hello,

I was happy with the solution I was given in this thread but now that we have daylight saving time the solution does not work anymore and I start to doubt that the solution was just a patch. Try the following script:

{
TDatime da1(2008,04,28,15,52,00);
TDatime da2(2008,04,28,15,53,00);

int ix[2],iy[2];

iy[0] = 1;
iy[1] = 2;
ix[0] = da1.Convert();
ix[1] = da2.Convert();
cout << ix[0] << " " << ix[1] << endl;

TGraph mgr(2,ix,iy);
mgr.SetMarkerStyle(20);

mgr.Draw(“ap”);
mgr.GetXaxis()->SetTimeDisplay(1);
mgr.GetXaxis()->SetNdivisions(-503);
mgr.GetXaxis()->SetTimeFormat("%Y-%m-%d %H:%M");
mgr->GetXaxis()->SetTimeOffset(0,“gmt”);
}

and you will get the two points plotted with the wrong time labels: 14:51 and 14:53 instead of 15:51 and 15:53. I have checked that the outputs of da1.Convert() and da2.Convert() are the correct one, including the way the DST is treated. So it looks like the problem is in the TimeFormat part.
Can you help me? I am running with root 5.18.00 on lxplus.

                                 Thanks,

                                   Andrea

I’ll look at it. It is true that the time axis label takes care of the summer saving time … that 's not what you want ?

Hi,

I want that it takes DST into account (I mean, that it plots the time as I read in my clock) but it looks like this is not the case: I put as input 15:51 and 15:53 and I found in the plot 14:51 and 14:53. Maybe in the Convert() method of TDatime it is able to detect the correct time zone and DST setting to generate the correct integer value, while in the SetTimeFormat and SetTimeOffset part of the code it does neglect the DST setting when it has to convert from the integer to the time label.

                                                    Andrea

Here is an other example:

{
   auto ct = new TCanvas("ct","Time on axis",0,0,600,400);
   auto ht3 = new TH1F("ht3","ht3",30000,0.,20000.); 
   for (Int_t i=1;i<30000;i++) {
      Float_t noise = gRandom->Gaus(0,120);
      ht3->SetBinContent(i,noise*noise*noise);
   }
   ht3->GetXaxis()->SetLabelSize(0.03);
   TDatime dh(2001,9,23,15,00,00);
   ht3->GetXaxis()->SetTimeDisplay(1);
   ht3->GetXaxis()->SetTimeOffset(dh.Convert());
   ht3->Draw();
}

When I run it the X axis starts exactly at 23h15 as in the variable dh.

Hi,

thanks for your example. I have also looked at the other examples in that page and I have modified my script slightly in this way:

{
int ioff =100000;

//TDatime da(2002,08,01,00,00,00);
//int ioff = da.Convert();

TDatime da1(2008,03,30,01,52,00);
TDatime da2(2008,03,30,03,13,00);

int ix[2],iy[2];

iy[0] = 1;
iy[1] = 2;
ix[0] = da1.Convert()-ioff;
ix[1] = da2.Convert()-ioff;
cout << ix[0] << " " << ix[1] << endl;

TGraph mgr(2,ix,iy);
mgr.SetMarkerStyle(20);

mgr.Draw(“ap”);
mgr.GetXaxis()->SetTimeDisplay(1);
mgr.GetXaxis()->SetNdivisions(-503);
mgr.GetXaxis()->SetTimeFormat("%Y-%m-%d %H:%M");
mgr->GetXaxis()->SetTimeOffset(ioff);

}

So I have:

  1. chosen the dates of the two points across the instant when we changed from no DST to DST this year (on 30/3/2008 night)
  2. I have introduced a offset ioff which I have subtracted from the converted dates and I have added to the TimeOffset of the axis. This offset is either set by hand or according to the TDatime da.

What I found is that the axis are drawn PERFECTLY as long as the offset is more than one hour : ioff > 3600. When I say “perfectly” I mean that also the effect of the DST is taken into account properly: it jumps from 01:59:59 to 03:00:00.
So given the fact that in the page you have linked in your reply it is said that the offset has to be larger than 01/01/1995 00:00:00 while it works even if it is larger than 01/01/1970 01:00:00 I think it is fair to say that there is no bug… maybe you can add a warning in SetTimeOffset if the offset is too small.
On my side I have to change the way I fill an histogram when I have Unixtime timestamps: I have to subtract a fixed offset, fill the histograms or the graph and then set the time offset of the axis with the subtracted offset.

                            Thanks and cheers

                                      Andrea

Thanks for your reply I will try to improve the page I sent you.

Hi,

It looks like there is still some missing pieces.

If I try the two following scripts:

{
TDatime da(2000,01,01,00,00,00);
int ioff = da.Convert();

TDatime da1(2008,03,30,01,52,00);
TDatime da2(2008,03,30,03,13,00);

int ix[2],iy[2];

iy[0] = 1;
iy[1] = 2;
ix[0] = da1.Convert()-ioff;
ix[1] = da2.Convert()-ioff;
cout << ix[0] << " " << ix[1] << endl;

TGraph mgr(2,ix,iy);
mgr.SetMarkerStyle(20);

mgr.Draw(“ap”);
mgr.GetXaxis()->SetTimeDisplay(1);
mgr.GetXaxis()->SetNdivisions(-503);
mgr.GetXaxis()->SetTimeFormat("%Y-%m-%d %H:%M");
mgr.GetXaxis()->SetTimeOffset(ioff);

}

and

{
TDatime da(2000,01,01,00,00,00);
int ioff = da.Convert();

TDatime da1(2008,03,30,01,52,00);
TDatime da2(2008,03,30,03,13,00);

int ix[2],iy[2];

iy[0] = 1;
iy[1] = 2;
ix[0] = da1.Convert()-ioff;
ix[1] = da2.Convert()-ioff;
cout << ix[0] << " " << ix[1] << endl;

TGraph mgr(2,ix,iy);
mgr.SetMarkerStyle(20);

mgr.Draw(“ap”);
mgr.GetXaxis()->SetTimeDisplay(1);
mgr.GetXaxis()->SetNdivisions(-503);
mgr.GetXaxis()->SetTimeFormat("%Y-%m-%d %H:%M %F2000-01-01 00:00:00");

}

I got two different results even if the page you have linked says that the two method to define the offset are equivalent.
With the first script I get the right plot while with the second the dots are in the wrong position. Do you understand it?

                                 Thanks

                                      Andrea

I will look at it. I recommend the 1st technique.

Hi,

I bumped into the same problem and found this old post.
As others, I observe that SetTimeOffset() works only with offsets larger then 3600.
Did any solution come out in the meantime or do I need to shift all my dates to a different t0?
Thank you
Davide

Do you have some simple script showing your problem. This time axis setting as so many special cases that it is better to discuss on some real running script.

I extract a few lines from my code:

{
  TTimeStamp start(2007, 12, 15, 0, 0, 0);
  TTimeStamp stop(2010, 4, 11, 0, 0, 0);
  ULong_t start_time = start.GetSec();
  Int_t start_day = start_time/3600/24;
  ULong_t stop_time = stop.GetSec();
  Int_t stop_day = stop_time/3600/24;
  Int_t nbins = stop_day-start_day;

  TH1F *hlt_vs_day              = new TH1F("hlt_vs_day"           , "Live Time vs day"          , nbins  , start_time, stop_time);
// I fill with times which are UTC and in time_t
  hlt_vs_day           ->GetXaxis()->SetTimeDisplay(1);    
hlt_vs_day           ->GetXaxis()->SetTimeOffset(0, "gmt");  
hlt_vs_day->Draw();
}

if you zoom more and more close to either edge of the x axis until you get into hours, you’ll see that it starts and ends 1h past the dates specified.
Reading above in this post I understand the problem is the same as the one noted by other users.