#969 'set timefmt "%s"' and timecolumn(): incorrect plot


The following commands result in a nonsensical plot with the current CVS version (not tested yet with 4.4.x):

set xdata time
set timefmt x "%s"
set format x "%Y/%m/%d %H:%m"
set xtics rotate
plot '-' using (timecolumn(1)):1

These unix timestamps refer to today, but the plot shows 1970/01/01. There is an additional warning:
empty x range [-9.45734e+08:-9.45734e+08], adjusting to [-9.55192e+08:-9.36277e+08]

Gnuplot's date/time processing is hideously complicated, and I don't yet know where it goes wrong in this case.

I do know however, that the section responsible for the %s format string in time.c's gstrptime() function is incorrect.

    /\* offset from UNIX epoch \(1970\) to gnuplot epoch \*/
    static const long epoch\_offset
        = \(long\)\(\(ZERO\_YEAR - 1970\) \* 365.25\) \* DAY\_SEC;

    when = strtod \(s, &s\) - epoch\_offset;

This formula is off by half a day. It uses an average year length of 365.25 days, which corresponds to one leap day per 4 years. However, there are only 7 leap days in the 30 years between 1970 and 2000. The section above should be replaced with

    when = strtod \(s, &s\) - SEC\_OFFS\_SYS;

By the way, what was the original reason behind choosing 2000 as the epoch? Does this choice have any advantage over the traditional 1970?
If the internal epoch were the same as the system's, there would be no need for this SEC_OFFS_SYS business, and we could also do away with the annoying inconsistency in the behavior of the "%s" format string. As of now, on input it means the number of seconds since 1970, but on output it means the number of seconds since 2000.


  • Péter Juhász

    Péter Juhász - 2011-01-21


    The reason for the first bug is that timecolumn(1) finds the wrong timefmt. 'set timefmt x "%s"' sets the timemft on the x axis only, for the rest of the axes it remains the default, which is "%d/%m/%y,%H:%M". So the first two digits of 1295640000 will be interpreted as 12th day of the month. The rest of the fields of the time/date struct remain zero, thus we get the bogus dates.
    But why 1970, not 2000? It's because the epoch offset gets subtracted even though it shouldn't be in this case.
    Another case where the inconsistency in the meaning of "%s" strikes us, and another argument for scrapping the 2000 epoch and change it to good old 1970, which the rest of the world uses.

  • Stefan Reiser

    Stefan Reiser - 2011-05-29

    But the "timecolumn()" is for converting a string representation of a timestamp to the internal numerical representation 'seconds since 2000'.

    Since you already have that numerical value, you can just write "using 1:1" and it works just fine ...

  • Ethan Merritt

    Ethan Merritt - 2011-06-17

    > The section above should be replaced with
    > when = strtod (s, &s) - SEC_OFFS_SYS;

    Fixed this bit in CVS.

  • Ethan Merritt

    Ethan Merritt - 2011-06-17
    • status: open --> closed

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks