2012-01-27 60 views
2

set_time()函數應該需要一段特定時間,並將指定的分鐘數添加到此時間,並將其保存在*t中。如何將分鐘添加到包含UTC時間的結構tm?

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

enum {JAN, FEB, MAR, APR, MAY, JUNE, JULY, AUG, SEP, OCT, NOV, DEC}; 

void set_time(struct tm *t, 
       int year, int mon, int day, 
       int hour, int min, int sec, 
       int mins_to_add) 
{ 
    /* Copy all the values. */ 
    t->tm_year = (year - 1900); 
    t->tm_mon = mon; 
    t->tm_mday = day; 
    t->tm_hour = hour; 
    t->tm_min = min; 
    t->tm_sec = sec; 

    // No DST since we are storing UTC time. 
    t->tm_isdst = 0; 

    /* Add minutes to time. */ 
    t->tm_min += mins_to_add; 
    mktime(t); 

    /* Debug print */ 
    printf("%s\n", asctime(t)); 
} 

int main(int argc, char **argv) 
{ 
    struct tm t; 
    set_time(&t, 2011, AUG, 1, 10, 00, 00, 0); 
    return 0; 
} 

那麼,請問set_time()不了了之添加到8月1日10:00:00 2011年但是,如果我的Windows系統設置爲EST時區,輸出我得到的是:Mon Aug 01 11:00:00 2011

的發生錯誤,因爲我做(在上述例中爲0)將在指定的分鐘數到指定時間的任務(8月1日10:00:00 2011在上面的例子)與這部分代碼:

/* Add minutes to time. */ 
    t->tm_min += mins_to_add; 
    mktime(t); 

mktime()被調用來調整所有其他memb如果t->tm_min由於添加而超過59,則該結構的變量。但mktime()struct tm對象的時間視爲當地時間。因此,當它看到2011年8月1日的日期和當地時區爲EST時,它假定需要應用DST,但它發現t->tm_isdst設置爲0(這意味着DST不適用於*t中的時間)。因此,它適用DST,將日期從2011年8月1日10:00:00至2011年8月1日11:00:00調整,並將t->tm_isdst設置爲1

如果我初始化t->tm_isdst1,就不會發生這種問題,因爲mktime()會發現,在*t的時間已經有DST應用到它。然而,如果我要求set_time()向不應用DST的日期添加任何內容(例如Jan 01 10:00:00 2011),那麼結果就會混亂。現在,它會嘗試關閉*t中的DST,從而設置t->tm_isdst設置爲0並重新調整日期至2011年1月1日09:00:00。

因此,如果我希望在指定時間內增加額外小時或從指定時間中減去額外小時,會產生不良影響沒有增加任何內容。發生這種情況的原因是,mktime()發現t->tm_isdst中的DST設置與系統本地時區不符時,它會嘗試通過重新調整*t中的時間來正確設置它。

解決此問題的正確方法是什麼?

+1

密切相關,可以說是一個騙局:http://stackoverflow.com/questions/530519/stdmktime-and-timezone-info。 – ruakh 2012-01-27 23:43:06

+0

ruakh,你提到的帖子是密切相關但不相似的。這裏的問題有一個簡潔的解決方法,它包含從'mktime()'返回的時間戳中減去時區偏移量。但是,我的問題是在'struct tm'對象中添加一定數量的分鐘,並確保'mktime()'由於DST設置不會添加或減去日期以外的任何內容。 – 2012-01-27 23:52:20

回答

1

Windows函數_mkgmtime可以用來代替mktime爲了安全地執行這個轉換(不管本地時區設置)。

+0

DRH,文檔位於http://msdn.microsoft.com/en-us/library/2093ets1(v=vs.80).aspx提及:「指定tm結構時間時,請將tm_isdst字段設置爲:Zero( 0)來指示標準時間有效,大於0的值表示夏時制有效,小於零的值使C運行時庫代碼計算標準時間或夏令時是否在影響。」 - 無論初始化「t-> tm_isdst」爲何,我都會得到相同的答案。所以,我無法理解這個函數究竟如何使用'tm_isdst'。 – 2012-01-28 01:21:13

+0

@Susam Pal我不是100%,但我相信文檔是從'mktime'的文檔中解除的,並且實際上並不適用於'_mkgmtime'。這是基於各種實驗,將'tm_isdst'設置爲不同的值,並設置我的本地時間進出DST,在所有情況下,結果'tm_isdst'設置爲'0'(這是我所期望的UTC), – DRH 2012-01-28 01:29:16

+0

對於那些在Unix上的人,有'timegm',它是'gmtime'(和'timelocal','localtime'的倒數,相當於'mktime')的倒數。 – musiphil 2012-06-20 22:54:56

2

struct tm文檔說

的夏令時標記(tm_isdst的)是...小於零,如果 信息不可用。

我建議你將它設置爲-1,看看是否解決了一些問題。

+1

這可能仍然存在DST轉換的問題,例如'set_time(&t,2011,MAR,13,01,59,00,1);'當地時區PST將返回03:00:00。 – DRH 2012-01-28 00:21:57

+0

@DRH你有沒有試過? – Borodin 2012-01-28 00:52:33

+1

@Borodin是的,但我的評論是不完整的。原始代碼將返回'03:00:00'。更新後的代碼(使用'tm_isdst = -1')返回'01:00:00'。 – DRH 2012-01-28 01:08:55

相關問題