I want to make my code more platform-/implementation-independent. I don't know what a time_t
will be implemented as on the platform when the code is being compiled. How do I know the type of t
to determine what format specifier to use?
...
time_t t = time(NULL);
printf("%s", t);
...
You can use
difftime()
to obtain adouble
:It is simple and I think it is portable.
The C standard says
time_t
will be a 'real type' (meaning an integer type or a floating point type, though in practice it is always an integer type).With
time_t
, your best bet is to format it withstrftime()
after analyzing it withlocaltime()
orgmtime()
— this can be done portably.Unportably, you have to determine by some mechanism what is the correct format specifier. You might use
PRI_[Xxodi]_time
andSCN_[Xxodi]_time
or something similar as a non-standard but close-to-standard (without trampling on the reserved namespace — which is names starting PRI or SCN followed by a lower-case letter or X). You use some mechanism to specify that...encapsulating the unportable information in one place.Generally, the way to display the value of a
time_t
is to break down its components to astruct tm
usinggmtime
orlocaltime
and display those or convert them as desired withstrftime
, orctime
to go directly fromtime_t
to a string showing local time.If you want to see the raw value for some purpose, the C standard specifies that
time_t
is real, which means it is integer or floating-point (C 2011 (N1570) 6.2.5 17). Therefore, you should be able to convert it todouble
and print that. There is some possibility thattime_t
can represent values thatdouble
cannot, so you might have to guard against that if you want to take care regarding exotic implementations. Sincedifftime
returns the difference of twotime_t
objects as adouble
, it seems C does not truly supporttime_t
with more precision than adouble
.Usually you can use a cast to convert the operand to some type for which you know the right format.
Your proposed solution:
clearly will not work, since
time_t
is a numeric type, notchar*
.We know, in general, that
time_t
is an arithmetic type. Something like this:is likely to work on most systems. It can fail (a) if
time_t
is an unsigned type no wider thanunsigned long
and the current value oft
exceedsLONG_MAX
, or (b) iftime_t
is a floating-point type.If you have C99 support, you can use
long long
, which is a little better:If you really want to go overboard with portability, you can detect what kind of type
time_t
is:You might want to tweak the
%Lg
format to something like%Lf
or%.10Lf
, depending on what output format you want.Again, this assumes C99 support -- and you'll need
#include <stdint.h>
to makeuintmax_t
andintmax_t
visible.time_t
andclock_t
are a bit unusual, in that the standard says only that they're arithmetic type capable of representing times. (In principle they could be complex types, but I'd say ignoring that possibility is worth the risk.)In most other cases, you'll probably know whether a given type is signed, unsigned, or floating-point, and you can just convert to the widest type of that kind.
Note that if you don't know how
time_t
is represented, you probably won't understand the output of theprintf
(such as1379375215
) either -- unless your goal is to figure that out.(If you were programming in C++ rather than C,
std::cout << t << "\n";
would automatically use the correct overloadedoperator<<
.)If you want human-readable output (like
Mon 2013-09-16 16:46:55 PDT
), you'll want to use one of the conversion functions declared in<time.h>
, such asasctime()
orstrftime()
.