2012-08-25 44 views
9

我正在執行下面的代碼。混淆mktime()函數的行爲:將tm_hour計數增加一個

int main() 
{ 
struct tm storage={0,0,0,0,0,0,0,0,0}; 
char *p = NULL; 
p = (char *)strptime("2012-08-25 12:23:12","%Y-%m-%d %H:%M:%S",&storage); 
char buff[1024]={0}; 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
storage.tm_sec += 20; 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
mktime(&storage); 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
return 0; 
} 

如果上述程序執行時,它打印 '2012-08-25 13點23分32秒',而不是 '2012-08-25 12點23分32秒'。請幫助,爲什麼它會增加tm_hour的價值。 如果我在程序中將輸入日期設置爲'2012-02-25 12:23:32',這會正常工作,這很令人困惑。

輸出 - 在我的系統>

[[email protected] root]$ ./a.out 
2012-08-25 12:23:12 
2012-08-25 12:23:32 
2012-08-25 13:23:32 
[[email protected] root]$ 

日期信息, - >

[[email protected] root]$ date 
Sat Aug 25 08:28:26 EDT 2012 
+0

該代碼不顯示小時正在增加。爲此,請將'strptime'的結果以及來自'mktime'的調用結果顯示出來。這將有助於確定實際發生的事情。 –

+0

對不起,我無法解析。它有三個輸出,而不是一個,但沒有表明它們來自哪裏。請更新示例代碼以匹配輸出。 –

回答

11

會發生什麼

您指定的日期有夏令有效但調用mktime時,storage.tm_isdst爲零。 mktime看到了這一點,並認爲「嘿,他們給了我一個日期不正確的夏令時標誌,讓我們修復它」。然後它將tm_isdst設置爲1並更改tm_hour

this答案見。

要修復它

  • 使用timegm代替mktime
  • 設置時區爲UTC調用mktime之前(請參閱從timegm還爲例):
    setenv("TZ", "", 1); 
    tzset(); 
    mktime();
  • 使用一個很好的日期 - (如boost::locale::date_time/boost::date_time,但請閱讀Q &部分在boost::locale::date_time頁面選擇之前)
+1

謝謝,它幫助並解釋我的疑問。現在我需要在兩種類型的系統上運行我的一段代碼(DST開啓和關閉)。例如如果我在調用mktime()之前將tm_isdst = 1放入代碼中,它將在DST關閉的系統上產生不正確的結果(最終會將tm_hour減1)。有沒有其他方法可以在指定的日期添加秒? (它可能是「避免使用mktime()」或「聰明地使用mktime(),它將忽略tm_isdst標誌」) –

+0

@DhirajNeve:我添加了一些修復程序。如果你需要做更多的日期/時間相關的事情,我認爲你應該使用一個好的C++日期/時間庫。 – rve

+0

是不是隻有'timegm' POSIX? – stackptr

4

哇,那裏只是是沒有辦法解決它。它必須是系統實施mktime(3)時的一個錯誤。 mktime(3)不應該改變傳遞給它的 struct tm *

我建議檢查storage.tm_isdst值。嘗試將其設置爲0以確保它不會對DST感到困惑。如果這不起作用,請嘗試將其設置爲-1以使其自動確定適當的值。

mktime - convert broken-down time into time since the Epoch

一個正或0值導致的tm_isdst mktime()最初假定夏令時,分別是或不是在指定的時間的效果。 tm_isdst的負值會導致mktime()嘗試確定夏令時是否對指定時間有效。


我錯mktime(3)不修改struct tm *。標準化該值是正確的行爲。

+0

根據'man mktime'(http://linux.die.net/man/3/mktime)它可以(並確實)改變'stuct tm'。它規範化其值並填寫缺失的字段。 – rve

+0

@rve看起來你是對的。我被誤解了措詞。我認爲這是正常化的目的設置time_t。 –

+0

是的,執行是錯誤的... –