2013-01-02 55 views
7
#include <stdio.h> 
#include <time.h> 

int main(int argc, char* argv[]) 
{ 
    struct tm stm; 
    stm.tm_sec = 27; 
    stm.tm_min = 5; 
    stm.tm_hour = 18; 
    stm.tm_mday = 2; 
    stm.tm_mon = 0; 
    stm.tm_year = 43; 
    stm.tm_wday = 0; 
    stm.tm_yday = 0; 
    printf("%d\n", mktime(&stm)); 
    getchar(); 
    return 0; 
} 

打印-1mktime返回-1時提供的有效結構TM

我是什麼誤會?

[+編輯]這是使用Visual Studio 2012與32位目標。我想後續的問題是'什麼是推薦的方法來存儲任意的日期/時間值(即那些可能在1900年之前)?「

+1

爲什麼不檢查'errno'或使用'perror'來找出哪裏出了問題? – 2013-01-02 18:15:20

+0

有人刪除了答案,這是這一年是無效的 - 我使用的是基於1970年而不是1900年的strptime版本。 –

+0

我暫時刪除了我的答案,我需要檢查一些東西(我第一次是對的) – benjarobin

回答

13

在你的情況43(1943)被認爲是無效的一年。原因是mktime返回time_t類型。這種類型沒有真正標準化。什麼文檔說:

time_t類型是代表 秒自00:00小時經過1970年1月1日UTC的數量,的積分值。而且tm_year是自1900年以來

此鏈接 若干年What is ultimately a time_t typedef to?說:

time_t代表秒自Unix 時代的開始數:1970年1月1日午夜(UTC)(不包括閏秒)。 某些系統正確處理負時間值,而其他一些系統做 而不是

如果我們考慮到time_t是一個有符號32位整數,在最好的情況下,您可以創建〜在你的情況13/12/1901和19/1/2038

之間的日期實施不使用time_t的負數部分,因此您無法在1970年之前創建日期爲mktime

+1

實際上,POSIX說'time_t'是一個簽名類型([link](http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to)),所以,當它以32位整數實現時,它*可以用來表達1970年以前的68年。 –

+0

@Mat它真的取決於實現,請完整閱讀Matteo Italia的鏈接http://stackoverflow.com/questions/471248/what-is-finally-a-time-t-typedef-to。 time_t代表自1970年1月1日午夜的UTC時代開始以來的秒數(不包括閏秒)。一些系統正確處理負時間值,而另一些系統則不**。 – benjarobin

+0

這不是因爲time_t被簽名,因此實現了1970年之前的日期計算。 由於該標準對此沒有任何說明,因此可能不會添加1970年以前的日期支持。 – benjarobin

0

您試圖表示日期「1943年1月2日」。
在Unix/Linux系統上,此值不能用time_t值表示,因爲這些系統使用「1970年1月1日」作爲參考日期。

更新:
POSIX指定mktime返回「自Epoch以來的秒數」(其中Epoch = 01-01-1970 00:00:00)的時間。在嚴格的解釋中,1970年1月1日之前的日期因此不能表示,因爲'以來的秒數'本質上是一個正數。

ANSI/ISO C不太清楚mktime的結果爲負值的可能性。

+1

'time_t'是有符號的,1943年沒有超出範圍。 – Mat

2

time_t是您的系統上的一個64位整數,並且您使用錯誤的格式標誌說明符將其打印出來。您需要使用ll修改,以表明它是64位:

time_t t = mktime(&stm); 
printf("%lld", (int64_t)t); // This will be correct if time_t is 32 or 64 bits 

由於時間是時代之前(1970年1月1日),時間就像是-851910873負值,這是十六進制0xffffffffcd38df27作爲一個64位整數。當你試圖以32位整數打印出來時,你會得到高32位,這是0xffffffff或-1(儘管在技術上這是根據C標準的未定義行爲,所以不要依賴這個)。

正如其他人所提到的,time_t的實際尺寸未指定,因此您不應對此作出任何假設。如果你真的需要知道它有多大,最安全的做法是將它擴展到64位。