I know that size_t is unsigned and hence negative values are not allowed, time_t is to the best of my knowledge signed, so I am allowed to assign -1 to a size_t. However, for time_t I'm not entirely sure. If I follow the definition through the header files I end up here:
typedef __time_t time_t;
, then here:
__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch. */
and finally
#define __TIME_T_TYPE __SYSCALL_SLONG_TYPE
I'm not too sure what a __SYSCALL_SLONG_TYPE is, but I guess it is a signed long. Unfortunately, even after doing this trace, I can only hope that other c++11 platforms have the same implementation. I'm still not sure that this will be legal and well-defined for all of them:
size_t foo = -1;
Of course it makes sense to make a time_t signed, since one can have negative time offsets, for example to model time zones. But on the other hand it makes sense to have it unsigned, because there are a lot of seconds to count after 1970. So common sense goes both ways :) Googling on time_t returned this:
"For historical reasons, it is generally implemented as an integral value representing the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC (i.e., a unix timestamp). Although libraries may implement this type using alternative time representations."
Source: http://www.cplusplus.com/reference/ctime/time_t/
and on the same page: "Portable programs should not use values of this type directly, but always rely on calls to elements of the standard library to translate them to portable types."
So time_t is not at all well-defined on all systems, however, time() returns a time_t: so I wouldn't be the first to export it in an interface. What other type should I use?
I'm asking for these two reasons:
Question: Since time_t is not a well-defined time representation on all platforms, what kind of data type that is (1) fast and (2) comparable can I use that is portable?
For example, regarding the ordering of time_t:
#include <iostream>
#include <ctime>
#include <cstring>
int main() {
struct tm tm_a, tm_b;
memset(&tm_a, 0, sizeof(struct tm));
memset(&tm_b, 0, sizeof(struct tm));
if(strptime("2014-01-01 12:00:00", "%Y-%m-%d %H:%M:%s", &tm_a) && strptime("2014-01-01 11:59:59", "%Y-%m-%d %H:%M:%s", &tm_b)) {
if(mktime(&tm_a) > mktime(&tm_b)) std::cout << "time_t ordering OK." << std::endl;
else std::cout << "time_t ordering tainted" << std::endl;
} else std::cout << "failed to parse time" << std::endl;
return 0;
}
Will time_t be untainted on all platforms?
(time_t)(-1)
already means "this is not a valid time", regardless of what time_t
actually is. The standard function mktime
returns this value on error, so can you.
The C and C++ standards say nothing about encoding of time in time_t
. The standard function difftime
computes time difference in seconds, as a double
, between two times represented as time_t
, and that's the only blessed way to order time_t
values chronologically. However, the POSIX standard specifies that time_t
is the time in seconds, so on a POSIX system it is OK to compare time_t
directly with <
.
Note that both C and POSIX permit time_t
to be any arithmetic type (not just integral).