Hi Benoît,

On Sat, May 13, 2017 at 07:32:10AM +0200, Benoît GARNIER wrote:
> Le 12/05/2017 à 15:54, Willy Tarreau a écrit :
> > Hi Benoît,
> >
> > On Thu, May 04, 2017 at 08:50:33AM +0200, Benoît GARNIER wrote:
> > (...)
> >> If you do the following operation : time_t => localtime() => struct tm
> >> => timegm() => time_t, your result will be shift by the timezone time
> >> offset (but without any DST applied).
> >>
> >> Technically, if you live in Great Britain, the operation will succeed
> >> during winter (but will offset the result by 1 hour during summer, since
> >> DST is applied here).
> > So in short you're saying that we should always use mktime() instead ?
> >
> > Willy
> 
> No, not at all !!! To sum up, these are the basic functions to work with
> time :
> 
> - time() return a time_t which is timezone agnostic since it's just a
> precise moment in time (it represents the same moment for everybody)
> 
> - localtime() takes this time_t and build a representation of this time
> in the current time zone (struct tm)
> 
> - mktime() take a struct tm representing a specific time in the current
> timezone et return a time_t
> 
> gmtime() and timegm() are the same as localtime() and mktime() but will
> ignore the timezone and DST: they only work with UTC time.
> 
> So you can use timegm() on a struct tm only if you know that struct tm
> represents a GMT time (for example if it was build with gmtime()).
> 
> Similarly, using mktime() is only valid if this struct tm represents the
> time in the current time zone (i.e. if it was build with localtime()
> with the same timezone).
> 
> For example if you parse a log file with GMT time in it you'll use
> timegm() to build a time_t representing the precise time of the log.
> 
> If you parse a file with local time in it, you'll use mktime() but
> you'll also have to know what was the timezone used to build it.
> 
> 1) Time zone agnostic: time()
> 2) Current time zone: localtime() and mktime()
> 3) UTC time: gmtime() and timegm()
> 
> As a rule of thumb, you cannot mix functions in categories 2 and 3.

OK thank you, that's perfectly clear now and it makes sense. Thierry
told me that he purposely used timegm() because he wanted UTC. Man
pages recommend not to use it because it's obsolete and suggest to
use setenv(TZ)+tzset()+mktime() !!! It's amazing to read something
that stupid in man pages written 10 years after everyone started to
write threaded applications! I found that in practice many people
use a hand-written timegm() function which does all the computation
by hand, just like those of us who have known MS-DOS used to do 30
years ago, so I think we'll have to go down that route for a more
portable implementation :-/  At least this will also save us from
accidently using implementations where timegm() is a wrapper on
setenv+tzset+mktime()...

Thanks for your explanations!

Willy

Reply via email to