Le 13/05/2017 à 09:46, Willy Tarreau a écrit :
> On Sat, May 13, 2017 at 08:44:06AM +0200, Benoît GARNIER wrote:
>> Time handling is not easy. I hate to say that, but POSIX and glibc
>> manage to make it even harder. Especially the timezone global handling
>> which is not thread-safe as you pinpointed.
>> Anyway, free conding a simple timegm() is not very hard, since you don't
>> have to take any timezone into account, only leap years.
> That's what I've seen, none of them implement the leap seconds (I thought
> it was needed).

They don't because leap seconds don't exist. Really. The kernel (at
least on Linux) hides this extraneous second(*) from userland.
There are two ways the kernel can do this:
1) skipping it entirely - i.e the kernel will return 23:59:59 during 2
seconds
2) slowly adjusting time returned by the kernel until it matches UTC
time - for a few hours kernel seconds will last longer than a real second
So, at the end of day, from userland point of view, a day always lasts
86400 seconds, even when a leap second is inserted (and although the day
was officially 86401 seconds long).
That means you don't have to worry about leap seconds when making
computations on past dates.
But it can reveal subtle bugs (especially time going backward in the
first case and giving negative values when computing elapsed times).
Measuring elapsed time should preferably done with
clock_gettime(CLOCK_MONOTONIC,...) which is always monotonic, but is
adjusted by NTP (if the internal clock is drifting).
Another variant is clock_gettime(CLOCK_MONOTONIC_RAW,...) which is
monotonic and never adjusted but is specific to Linux > 2.6.28.
(Note: you can still have time going backward in a SMP platform during
task switching since each CPU has its own clock, even thought the kernel
try to compensate for the difference).

(*) Or missing second but that didn't happen in recent history

>> But beware that real timegm() (and mktime()) perform some time
>> normalization on tm_mday (day of the month) or tm_mon (month).
>> For example, they will happily work with fake dates like "March 31st
>> 2017", "February 59th 2017" or even "1st day of 18th month of 2016" and
>> will convert them to "April 1st 2017" internally.
> I've read this and apparently most of the time it's not needed at
> all.
Probably, it depends on the use case.
>> It's very handy when you want to compute date in the future or in the
>> past, you just add/substract values to the corresponding field (day or
>> month) and let mktime() of timegm() do their magic trick.
> Yes, like you do with the "date" command to know what date it will be in
> 1 million seconds for example :-)
Exactly.


Benoît

Reply via email to