2012-07-02 63 views
1

在嘗試編寫比給定時間少返回24小時的代碼時,mktime()顯示不一致的輸出。我計算它類似於:current_time(GMT) - 86400應該返回正確的值。我們所需要做的就是根據輸入時間來計算;我們使用mktime()來更改時間並獲取GMT時間,然後進行常規計算。我在下面列出了我的代碼。mktime顯示不一致的輸出

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

int main() 
{ 
    time_t currentTime, tempTime; 
    struct tm *localTime; 

    time(&currentTime); 
    //localTime = localtime(&currentTime); 
    localTime = gmtime(&currentTime); //get the time in GMT as we are in PDT 

    printf("Time %2d:%02d\n", (localTime->tm_hour)%24, localTime->tm_min); 
    localTime->tm_hour = 19; // Set the time to 19:00 GMT 
    localTime->tm_min = 0; 
    localTime->tm_sec = 0; 
    tempTime = mktime(localTime); 
    //tempTime = mktime(localTime) - timezone; 

    printf("Current time is %ld and day before time is %ld\n", currentTime, (currentTime - 86400)); 
    printf("Current timezone is %ld \n", timezone); 

    printf("New time is %ld and day before time is %ld\n",tempTime, (tempTime - 86400)); 
} 

但是,當我們檢查,便回來後不正確的電話呼叫mktime()輸出。以下是上述程序的輸出。

$ ./a.out 
Time 11:51 
Current time is 1341229916 and day before time is 1341143516 
New time is 1341284400 and day before time is 1341198000 
$ ./print_gmt 1341229916 
Mon Jul 2 11:51:56 2012 
$ ./print_gmt 1341143516 
Sun Jul 1 11:51:56 2012 
$ ./print_gmt 1341284400 
Tue Jul 3 03:00:00 2012 
$ ./print_gmt 1341198000 
Mon Jul 2 03:00:00 2012 
$ date 
Mon Jul 2 04:52:46 PDT 2012 

現在,如果我們取消註釋其中減去時區(存在於time.h中)的線,則如預期的輸出。下面是在上面的程序

$ ./a.out 
. . . 
Current timezone is 28800 
. . . 

時區的價值那麼,爲什麼是有mktime()這種不一致的行爲雖然手冊頁不提的時區的這種調整。 在進行此類轉換時是否有某些我們錯過的內容?

在此先感謝。

+0

'timezone'來自哪裏? – alk

+1

'mktime()'假設本地時間不是輸入UTC(又名GMT)。因此,如果不在格林威治,它會增加一個時間轉移。 – alk

+0

@alk,'timezone'是_X/Open System Interfaces Extension_的一部分,在'time.h'中被定義爲'extern long timezone;'。 –

回答

2

我認爲這個問題是在這裏:

The mktime() function shall convert the broken-down time, expressed as local time, in the structure pointed to by timeptr, into a time since the Epoch value...

注意的話local time。 C標準有他們太多在mktime()說明:

The mktime function converts the broken-down time, expressed as local time, in the structure pointed to by timeptr into a calendar time value with the same encoding as that of the values returned by the time function.

gmtime(),而另一方面,生產時間在GMT/UTC,而不是在您的時區:

The gmtime() function shall convert the time in seconds since the Epoch pointed to by timer into a broken-down time, expressed as Coordinated Universal Time (UTC).

編輯:如果您只想要以前的格林威治標準時間19:00,您可以這樣做:

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

int main(void) 
{ 
    time_t currentTime; 
    struct tm *brokenDownTime; 

    time(&currentTime); 

    // get the time in GMT as we are in PDT 
    brokenDownTime = gmtime(&currentTime); 
    printf("Current Time (GMT): %2d:%02d\n" 
      " seconds since Epoch: %ld\n", 
      brokenDownTime->tm_hour, 
      brokenDownTime->tm_min, 
      (long)currentTime); 

    // "Unwind" time to 0:00:00 (assuming time_t is an integer): 
    currentTime /= 24 * (time_t)3600; 
    currentTime *= 24 * (time_t)3600; 

    brokenDownTime = gmtime(&currentTime); 
    printf("Time at the beginning of the current GMT day: %2d:%02d\n" 
      " seconds since Epoch: %ld\n", 
      brokenDownTime->tm_hour, 
      brokenDownTime->tm_min, 
      (long)currentTime); 

    // Add 19 hours: 
    currentTime += 19 * (time_t)3600; 

    brokenDownTime = gmtime(&currentTime); 
    printf("Time at 19:00:00 of the current GMT day: %2d:%02d\n" 
      " seconds since Epoch: %ld\n", 
      brokenDownTime->tm_hour, 
      brokenDownTime->tm_min, 
      (long)currentTime); 

    // Subtract 1 day: 
    currentTime -= 24 * (time_t)3600; 

    brokenDownTime = gmtime(&currentTime); 
    printf("Time at 19:00:00 of the previous GMT day: %2d:%02d\n" 
      " seconds since Epoch: %ld\n", 
      brokenDownTime->tm_hour, 
      brokenDownTime->tm_min, 
      (long)currentTime); 

    return 0; 
} 

輸出:

Current Time (GMT): 13:23 
    seconds since Epoch: 1341235429 
Time at the beginning of the current GMT day: 0:00 
    seconds since Epoch: 1341187200 
Time at 19:00:00 of the current GMT day: 19:00 
    seconds since Epoch: 1341255600 
Time at 19:00:00 of the previous GMT day: 19:00 
    seconds since Epoch: 1341169200 
+0

其實我使用的是使用localtime()的代碼,但因爲我們需要在GMT時間進行計算,而不是當前系統時間,因爲解決方案運行在不同的時區,所以我在考慮mktime可以將GMT時間作爲輸入,然後執行轉換。 – Abhinav

+0

查看問題中的更新是否有幫助。 –

1

mktime(3)使用電流時區來執行轉換。這有點含糊地寫在the standard

本地時區信息應被設置爲雖然mktime()稱爲tzset()

1

mktime specification狀態,它的參數表示「破舊的時間,表示爲本地時間」。所以你傳遞給mktime的任何東西都必須在當地時間,而不是GMT。您的變量localTime的名稱中有local,但實際上是從gmtime獲得的,因此其結果描述的是GMT中的最近時間。將其傳遞給mktime是不一致的。

1

您沒有說明無論你是在POSIX(類似的)目標或一些古怪的系統工作,但在前者的情況下,你可以只使用POSIX公式轉換時間分解爲time_t

tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 + 
    (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 - 
    ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400 

來源:http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15

0

在某些系統上還有一個timegm功能應該做正確的事。
我剛剛在Linux上檢查過,它產生了正確的值(例如timegm(gmtime(time))== time)。

Here's如何在Windows中使用它。
這裏是一個similar answer