从 C 中传递的日期时间生成 UNIX 时间戳

Producing UNIX timestamp out of datetime passed in C

我正在将一个 C 应用程序从 Solaris 移植到 RedHat,但此功能在 RedHat 上不能很好地工作(我需要你的帮助来确定原因):

int toTimestamp (const char *InputDate, const char *DateFormat, time_t *lTimestamp){
    struct tm tm;

    if (NULL == strptime(InputDate, DateFormat, &tm)){
        return FALSE;
    }
    *lTimestamp = mktime(&tm);
    return TRUE;    
}

基本上,它根据指定格式从作为字符串传入的日期时间生成 UNIX 时间戳。

char *effPaymentDate = NULL;
char *CohDueDate = NULL;
//...
effPaymentDate = PayRec->RecDate;//char RecDate[8+1];, value 20141005
CohDueDate = PayRec->DueDate;//char DueDate[8+1];, value 20140820

time_t currentDateUNIX;
time_t DueDateUNIX;
if (FALSE == toTimestamp(CohDueDate, "%Y%m%d", &DueDateUNIX) ||
     FALSE == toTimestamp(effPaymentDate, "%Y%m%d", &currentDateUNIX)) {
  return NULL;
}
//...

但是,它似乎无法正常工作(effPaymentDate 工作正常,CohDueDate 给出了错误的日期 - 即 2543 年)- 知道为什么吗?

长话短说:

您需要在将其传递给 API 之前初始化 tm

memset(&tm, 0, sizeof tm);

为什么?

strptime 可能会在您没有注意到的情况下失败:

$ man strptime

RETURN VALUE
The return value of the function is a pointer to the first character not processed in this function call. In case the input string contains more characters than required by the format string the return value points right after the last consumed input character. In case the whole input string is consumed the return value points to the null byte at the end of the string. If strptime() fails to match all of the for‐ mat string and therefore an error occurred the function returns NULL.

NOTES

In principle, this function does not initialize tm but stores only the values specified. This means that tm should be initialized before the call. Details differ a bit between different UNIX systems. The glibc implementation does not touch those fields which are not explicitly specified, except that it recomputes the tm_wday and tm_yday field if any of the year, month, or day elements changed.

因此,由于 tm 未设置为 0,某些字段可能包含随机值。

此外:

$ man mktime

The mktime() function modifies the fields of the tm structure as follows: tm_wday and tm_yday are set to values determined from the contents of the other fields; if structure members are outside their valid interval, they will be normalized (so that, for example, 40 October is changed into 9 November); tm_isdst is set (regardless of its initial value) to a positive value or to 0, respectively, to indicate whether DST is or is not in effect at the specified time. Calling mktime() also sets the external variable tzname with information about the current timezone.

随机值可能超出范围,mktime尝试对其进行归一化。 虽然它做得很好,但 year 背叛了它!