strftime()的输出结果令人困惑

时间:2013-10-12 00:50:52

标签: c date time

在仔细查看time.h之后,我编写了以下函数:

void output_date ( int day, int month, int year ) {
    char buffer[64] = "";
    struct tm *e_time = calloc( (size_t) 1, sizeof(struct tm) );

    e_time->tm_year = year - 1900;
    e_time->tm_mon = month - 1;
    e_time->tm_mday = day;
    e_time->tm_hour = 0;
    e_time->tm_min = 0;
    e_time->tm_sec = 0;
    e_time->tm_isdst = -1;

    /* strftime ( buffer, 64, (char *)0, e_time ); */
    strftime ( buffer, 64, "%a %b %e %H:%M:%S %Z (%z) %Y", e_time );

    printf ( "%s\n", buffer );

    free(e_time);
    e_time = NULL;

}

然后我用一系列可能的输入调用了这个函数,只看到了 奇怪的输出如此:

Sun Jul  8 00:00:00  () 2013
Sun Jul  9 00:00:00  () 2013
Sun Jul 10 00:00:00  () 2013
Sun Jul 11 00:00:00  () 2013
Sun Jul 12 00:00:00  () 2013

当我将格式字符串测试为strftime时,我看到了很好的结果:

$ date -u "+%a %b %e %H:%M:%S %Z (%z) %Y"
Sat Oct 12 00:40:05 GMT (+0000) 2013

我甚至通过调试器单步执行并看到了同样的结果 奇怪的结果:

stopped in main at line 27 in file "flight.c"
   27                       output_date ( day+1, month+1, year );
(dbx) print day+1, month+1, year
day+1 = 1
month+1 = 1
year = 1977

(dbx) step                      
stopped in output_date at line 43 in file "flight.c"
   43       char buffer[64] = "";
(dbx) step
stopped in output_date at line 44 in file "flight.c"
   44       struct tm *e_time = calloc( (size_t) 1, sizeof(struct tm) );
(dbx) step
stopped in output_date at line 46 in file "flight.c"
   46       e_time->tm_year = year - 1900;
(dbx) print e_time
e_time = 0x100101640
(dbx) step        
stopped in output_date at line 47 in file "flight.c"
   47       e_time->tm_mon = month - 1;
(dbx) step
stopped in output_date at line 48 in file "flight.c"
   48       e_time->tm_mday = day;
(dbx) step
stopped in output_date at line 49 in file "flight.c"
   49       e_time->tm_hour = 0;
(dbx) step
stopped in output_date at line 50 in file "flight.c"
   50       e_time->tm_min = 0;
(dbx) step
stopped in output_date at line 51 in file "flight.c"
   51       e_time->tm_sec = 0;
(dbx) step
stopped in output_date at line 52 in file "flight.c"
   52       e_time->tm_isdst = -1;
(dbx) step
stopped in output_date at line 55 in file "flight.c"
   55       strftime ( buffer, 64, "%a %b %e %H:%M:%S %Z (%z) %Y", e_time );
(dbx) print *e_time
*e_time = {
    tm_sec   = 0
    tm_min   = 0
    tm_hour  = 0
    tm_mday  = 1
    tm_mon   = 0
    tm_year  = 77
    tm_wday  = 0
    tm_yday  = 0
    tm_isdst = -1
}
(dbx) step        
stopped in output_date at line 57 in file "flight.c"
   57       printf ( "%s\n", buffer );
(dbx) print buffer
buffer = "Sun Jan  1 00:00:00  () 1977"
(dbx) quit    

事实上,我所得到的只是星期日和正确月份的一周中的一天 用正确的日期和年份。其他似乎并不正确。

我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:1)

您应该在填充结构后调用mktime(e_time),但在调用strftime()之前。您有一些当前未完成的其他结构成员。传递具有未初始化值的结构(或者由于您的calloc()调用而初始化为不正确的值)通常是一件坏事,并且mktime()修改您传递的结构以填充它们

像这样:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void output_date ( int day, int month, int year ) {
    char buffer[64] = "";
    struct tm *e_time = calloc( (size_t) 1, sizeof(struct tm) );

    e_time->tm_year = year - 1900;
    e_time->tm_mon = month - 1;
    e_time->tm_mday = day;
    e_time->tm_hour = 0;
    e_time->tm_min = 0;
    e_time->tm_sec = 0;
    e_time->tm_isdst = -1;

    if ( mktime(e_time) < 0 ) {
        fprintf(stderr, "Error getting calendar time.\n");
        exit(EXIT_FAILURE);
    }

    int n = strftime ( buffer, 64, "%a %b %e %H:%M:%S %Z (%z) %Y", e_time );
    printf("Return from strftime() is %d\n", n);

    printf ( "%s\n", buffer );

    free(e_time);
    e_time = NULL;

}

int main(void) {
    output_date(12, 6, 2013);
    return 0;
}

的产率:

paul@local:~/src/c/scratch$ ./st
Return from strftime() is 36
Wed Jun 12 00:00:00 EDT (-0400) 2013
paul@local:~/src/c/scratch$

答案 1 :(得分:1)

您为字段tm_isdst提供了-1的值,这意味着夏令时不可用,如果夏令时生效,则将其更改为1,或{ {1}}如果不是。

正如@Paul Griffiths所指出的那样,调用0是更好的选择,mktime(e_time)函数将填充细分mktime,因为它会修复像{{1}这样的文件}和e_time也是如此。对于tm_wday字段,它遵循以下规则:

  

tm_day的正值或零值会导致tm_isdst函数最初假定夏令时分别在指定时间内有效或无效。负值会导致它尝试确定夏令时是否在指定时间内有效。