问题
I think the following program should output the seconds to 1970 for the first day of every year from 1AD to 1970, preceded by the size of time_t
on the system it's compiled on (CHAR_BIT
is a macro so I think you can't just copy the compiled executable around and assume it's correct though in practice everything uses 8 bit char
s these days).
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void do_time(int year)
{
time_t utc;
struct tm tp;
memset(&tp, 0, sizeof(tp));
tp.tm_sec = 0;
tp.tm_min = 0;
tp.tm_hour = 0;
tp.tm_mday = 1;
tp.tm_mon = 0;
tp.tm_year = year - 1900;
tp.tm_wday = 1;
tp.tm_yday = 0;
tp.tm_isdst = -1;
printf("%d %ld\n",year, mktime(&tp));
}
int main(){
printf("time_t is %lu bits\n",sizeof(time_t)*CHAR_BIT);
for (int i = 1; i<1971; i++)
do_time(i);
exit(0);
}
However on OS X (10.11.3 15D21) this only works for years >= 1902, despite time_t
being 64 bit signed. I could potentially understand if the programmers at Apple were lazy and didn't support any years before 1970, but correct behaviour going back to 1902 and then stopping looks more like an error on my part.
回答1:
Consulting the C standard:
The range and precision of times representable in
clock_t
andtime_t
are implementation-defined. [..][N1570 §7.27.1/4] (emphasis mine)
And further down, regarding mktime
:
The
mktime
function returns the specified calendar time encoded as a value of typetime_t
. If the calendar time cannot be represented, the function returns the value(time_t)(-1)
.[N1570 §7.27.2.3/3]
As such, as long as the return value of mktime
is (time_t)(-1)
for the years where it's not working ... you're on your own.
Actually, IMO, the standard is a bit quiet about all of this:
[..]
int tm_year; // years since 1900
[..][N1570 §7.27.1/4]
This could mean (positive) years since 1900, but then why use a signed integer.
As a side note: On my system (Linux 3.14.40 x86_64 glibc-2.21), I get ...
time_t is 64 bits
1 -62135600008
...
1969 -31539600
1970 -3600
Considering the work around part: You can of course look at libc implementations that are doing what you want and try to use their code (if that's possible with respect to any licences you need to obey). Here's the one my system uses.
回答2:
In UNIX OS there are often 64 bit-enabled versions of time functions. OS X may have something similar though I couldn't find it with my quick searching. See 64 bit unix timestamp conversion for more information.
EDIT: I found a Mac to test this on and it does not appear to have a mktime64 function unfortunately. I did find this this library that might work as a work-around though I haven't tested it personally.
来源:https://stackoverflow.com/questions/35300453/am-i-using-tm-mktime-wrong-and-if-not-is-there-a-workaround