Format specifier to print time(0) in C

前端 未结 5 1626
南方客
南方客 2021-01-22 06:18

We can declare a variable to hold the current time from the system using:

time_t now = time(0);

time(0) can also be use in genera

相关标签:
5条回答
  • 2021-01-22 07:03

    The standard doesn't define what type time_t is; it only has to be a real type capable of representing times. It could be an integer type or a floating-point type (it can't be complex -- fortunately). And it's not necessarily a number of seconds, or milliseconds, or any simple units. It could in principle use ranges of bits to represent months, seconds, days, hours, minutes, and years in that order in binary coded decimal. The most common representation is a 32-bit or 64-bit signed integer representing seconds since 1970-01-01 00:00:00 UTC.

    If you want a completely portable way to print a time_t value, you can detect what kind of type time_t is:

    #include <stdio.h>
    #include <time.h>
    #include <stdint.h>
    int main(void) {
        time_t now = time(NULL);
    
        printf("At the sound of the tone, the time will be ... \a");
    
        if ((time_t)1 / 2 != 0) {
            // time_t is a floating-point type; convert to long double
            printf("%Lf\n", (long double)now);
        }
        else if ((time_t)-1 > (time_t)0) {
            // time_t is an unsigned integer type
            printf("%ju\n", (uintmax_t)now);
        }
        else {
            // time_t is a signed integer type
            printf("%jd\n", (intmax_t)now);
        }
    }
    

    This assumes a C99 or later implementation. If you're stuck with a pre-C99 implementation that doesn't support <stdint.h> and/or the %ju and %jd formats (which you can detect this by testing __STDC_VERSION__), you can convert to long or unsigned long rather than [u]intmax_t. (MinGW probably won't handle printing a long double value correctly, but MinGW uses a signed integer type for time_t so that's not an issue.)

    This will print a raw value that isn't meaningful unless you happen to know how time_t is represented (both what type it is and how it represents the current time). On my system, the current time is 1416589039, which is the number of seconds since 1970-01-01 00:00:00 UTC (a very common representation).

    If you want to know what time it is rather than the raw value returned by the time() function, you should use the functions in <time.h> to generate a human-readable representation of the current time. For example:

    #include <stdio.h>
    #include <time.h>
    #include <stdint.h>
    int main(void) {
        time_t now = time(NULL);
        char s[100];
        strftime(s, sizeof s, "%F %H:%M:%S %Z", localtime(&now));
        printf("The time is now %s\n", s);
    }
    

    which prints (at the moment on my system):

    The time is now 2014-11-21 08:57:19 PST
    
    0 讨论(0)
  • 2021-01-22 07:05

    time_t is defined by C standard, C11, 7.27.1/3 as:

    [...] which are real types capable of representing times;

    That means it could be int, long, unsigned long, double or any other real type. Basically it's an implementation's choice. Similarly, it doesn't define what units time_t returns either, C11, 7.27.2.4/3:

    The time function returns the implementation’s best approximation to the current calendar time. The value (time_t)(-1) is returned if the calendar time is not available. If timer is not a null pointer, the return value is also assigned to the object it points to.

    You'll have to read what your implementation says. The glibc implementation I have on my Linux says, the unit returned by time_t is in seconds. So you could convert it to uintmax_t and print:

    time_t tvalue = time(0);
    printf("%ju", (uintmax_t)tvalue);
    

    Or you could use difftime() which returns a double as difference between two time_t values so that you don't have to worry about the underlying type of time_t.

    0 讨论(0)
  • 2021-01-22 07:09

    On most system time_t is define on the same number of bit than integer and is always positive.

    In this case you can use:

     printf("time: %u", (unsigned int) time(0));
    
    0 讨论(0)
  • 2021-01-22 07:11

    looking into the header file(s) for the time function, you will see that the parameter can be one of two things NULL or address of time_t variable.

    The time() function results for both the parameter and the returned value is the elapsed time, in seconds, since the epoch (currently Jan 1, 1970 00:00 am UTC.) The sizing of the value (on older systems) was 4 bytes (32bits). with recent RTC (RealTimeClock) hardware available, the value 'may' be 8 bytes (64bits) . in any case the value in is seconds since the epoch.

    The 4 byte time values will overflow in 2038, so efforts are being made to either 1) make the time value a larger size or 2) shift the epoch time forward to Jan 1 2000 00:00 am. ( a temporary fix when using older hardware )

    the changing of the time values to 8 bytes is the current preferred method.

    here is a specific quote from google:

    "At 03:14:08 UTC on 19 January 2038, 32-bit versions of the Unix time stamp will cease to work" to paraphase the rest of the quote: the 32 bit value will overflow.

    The functions that handle time, like localtime() strtotime(). etc and the related structs, like tm, are setup to use what ever the system they are running on is returning from the time() function.

    All the processing of the value from the time function should be done using the available functions rather than handling the raw value.

    0 讨论(0)
  • 2021-01-22 07:15

    As already said, standard does not specifies what time_t is. If you want to be sure to use it in a portable way, first convert it to long and then print it as a long. That way your program won't suffer the Year 2038 problem even if 32 bits architectures are still available at that time :-) ...

    time_t t = time(NULL);
    long lt = (t > 0) ? t : (unsigned int) t;
    printf("%ld", lt);
    

    It should work for time_t being a 32 bits signed of insigned integer or a 64 bit integer. My formule will break when time_t will be a negative 64 bits integer, but contact me at that time and I should then be wise enough to find a better solution :-)

    EDIT :

    As noted by chux this is bad if int is only 16 bits. Here is a robust even if ugly way

    union {
        long l;
        unsigned char[1] c;
    } ul;
    time_t t = time(NULL);
    ul.l = 0;
    ul.c[0] = 255;
    if (ul.l < 0) { /* endianness test */
        ul.l = 0;
        memcpy(&ul.l, t&, sizeof(time_t));
    }
    else {
        ul.l = 0;
        memcpy(&ul.l + sizeof(long) - sizeof(time_t), &t, sizeof(time_t));
    }
    printf("%lu", (unsigned long) ul.l);
    

    It should work in any configuration provided sizeof(long)>=sizeof(time_t)

    EDIT 2:

    chux's proposal seems to work on any reasonable cases. There are certainly pathological cases where it could break but on a normal implementation

    time_t t = time(NULL);
    long lt = (t > 0) ? t : t * 1u;
    printf("%ld", lt);
    

    should give correct result.

    0 讨论(0)
提交回复
热议问题