问题
In this answer I proposed that marihikari use the standard functionality of mktime rather than trying to implement his own Gregorian calendar system.
I wrote this function to demonstrate how mktime
could be used to accomplish this:
bool leap_year(int year) {
tm bar = { 0, 0, 0, 29, 1, year - 1900 };
mktime(&bar);
return bar.tm_mday == 29 && bar.tm_mon == 1 && bar.tm_year == year - 1900;
}
Testing this with:
cout << "2000: " << leap_year(2000) << "\n2001: " << leap_year(2001) << "\n2004: " << leap_year(2004) << "\n1900: " << leap_year(1900) << "\n2100: " << leap_year(2100) << endl;
Yielded the correct result in Clang 3.7.0:
2000: 1
2001: 0
2004: 1
1900: 0
2100: 0
But an incorrect result in gcc 5.1.0:
2000: 1
2001: 0
2004: 1
1900: 1
2100: 1
And an incorrect result in Visual Studio 2015:
2000: 1
2001: 0
2004: 1
1900: 1
2100: 0
I assume this is a bug in gcc 5.1.0 and Visual Studio 2015?
回答1:
mktime:
Converts local calendar time to a time since epoch as a
time_t
object.time->tm_wday
andtime->tm_yday
are ignored. The values in time are permitted to be outside their normal ranges.
...
If the conversion is successful, the time object is modified. All fields of time are updated to fit their proper ranges.
mktime
will return:
Time since epoch as a
time_t
object on success or -1 if time cannot be represented as atime_t
object.
It is not specified however what efforts the implementation must make to convert the tm
. So as long as the time is converted or static_cast<time_t>(-1)
is returned the requirements for mktime
have been filled.
Meaning that the following function will work on all platforms that correctly support mktime
:
bool leap_year(int year) {
tm bar = { 0, 0, 0, 29, 1, year - 1900 };
return static_cast<time_t>(-1) != mktime(&bar) && bar.tm_mday == 29 && bar.tm_mon == 1 && bar.tm_year == year - 1900;
}
来源:https://stackoverflow.com/questions/33477379/mktime-only-handling-leap-years-on-clang