[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
what shall we do with the drunken time_t ?
From: |
Bruno Haible |
Subject: |
what shall we do with the drunken time_t ? |
Date: |
Tue, 25 Apr 2017 00:40:18 +0200 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-72-generic; KDE/5.18.0; x86_64; ; ) |
Hi Paul, all,
I'm trying to port utimens and futimens to native Windows. A major problem
is the semantic of time_t on native Windows. An experiment (at the end of this
mail) shows that:
* While on POSIX systems, time_t is the number of seconds since 1970-01-01
00:00:00 UTC/GMT [1][2], on native Windows, this is not the case. The
Microsoft doc is ambiguous [3]
"The time function returns the number of seconds elapsed since midnight
(00:00:00), January 1, 1970, Coordinated Universal Time (UTC), according
to the system clock."
What the MSVC library returns, is local time minus DST shift.
In other words, because of
local_time = utc_time + timezone + dst_shift
the time_t on native Windows is
utc_time + timezone
* On mingw, there is additionally a stat() bug. If you have DST today, mingw
behaves as if you have DST throughout the year.
* The gmtime function is useless: since time_t is (utc_time + timezone),
it produces a time string that represents (gmt_time + timezone) as well.
What can we do?
(a) Accept the non-POSIX definition of time_t, and tell programmers not
to use gmtime() when they want UTC time.
(b) Make time_t be like on POSIX, by overriding time(), stat(), fstat(),
and similar functions.
I'm in favour of (b), because
* Programs that need UTC usually do so because they exchange data with
other machines, and this messes up with the native Windows notion of time_t.
* POSIX also has APIs with 'struct timeval' (whose first element is a time_t),
and utime(), and they also become problematic when time_t is offset by a
timezone.
Opinions?
Bruno
[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html
[2]
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
[3] https://msdn.microsoft.com/en-us/library/1f4c8f33.aspx
====================== Print st_mtime of an existing file ================
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (int argc, char *argv[])
{
if (argc != 2) { fprintf (stderr, "Usage: stat-file FILE\n"); exit (1);
}
const char *filename = argv[1];
struct stat buf;
if (stat (filename, &buf) < 0) { perror("stat"); exit(1); }
time_t tt = buf.st_mtime;
int day = tt / (24*3600);
int hour = (tt / 3600) % 24;
int seconds = tt % 3600;
fprintf (stdout, "mtime = %d %d %d\n", day, hour, seconds);
fprintf (stdout, "as GMT: %s\n", asctime (gmtime (&tt)));
fprintf (stdout, "as localtime: %s\n", asctime (localtime (&tt)));
}
================================ Results ===========================
(I am in CEST, i.e. GMT+1 with DST since end of March.)
A file last touched on 2016-11-27 18:32 GMT:
$ ls -l t.tar
-rw-r--r-- 1 bruno None 10240 Nov 27 19:32 t.tar
Cygwin:
mtime = 17132 18 1920
as GMT: Sun Nov 27 18:32:00 2016 (correct)
as localtime: Sun Nov 27 19:32:00 2016 (correct)
msvc:
mtime = 17132 19 1920
as GMT: Sun Nov 27 19:32:00 2016 (off by 1 h)
as localtime: Sun Nov 27 19:32:00 2016 (correct)
mingw:
mtime = 17132 20 1920
as GMT: Sun Nov 27 20:32:00 2016 (off by 2 h)
as localtime: Sun Nov 27 20:32:00 2016 (off by 1 h)
A file last touched on 2017-04-05 01:49 GMT:
$ ls -l n.txt
-rw-r--r-- 1 bruno None 93 Apr 5 03:49 n.txt
Cygwin:
mtime = 17261 1 2961
as GMT: Wed Apr 5 01:49:21 2017 (correct)
as localtime: Wed Apr 5 03:49:21 2017 (correct)
msvc:
mtime = 17261 2 2961
as GMT: Wed Apr 5 02:49:21 2017 (off by 1 h)
as localtime: Wed Apr 5 03:49:21 2017 (correct)
mingw:
mtime = 17261 2 2961
as GMT: Wed Apr 05 02:49:21 2017 (off by 1 h)
as localtime: Wed Apr 05 03:49:21 2017 (correct)
- what shall we do with the drunken time_t ?,
Bruno Haible <=
Re: what shall we do with the drunken time_t ?, Bruno Haible, 2017/04/29