2009-08-13 37 views
3

這看起來似乎任何人都不應該要做的,但我正在一個內核模塊上的嵌入式系統(的OpenWRT),其中似乎time.h確實包括timespectime_t類型和clock_gettimegmtime的功能,但並沒有包括localtimectimetime,或者,關鍵的是,tm類型。如何分解UNIX時間用C

當我嘗試將gmtime的返回指針轉換爲我自己的結構體時,我得到一個段錯誤。

所以我想我會滿足於通過兩種方式解決問題 - 找出如何獲得缺少的類型,或者如何推出我自己的分解方法unix時間戳。

+1

'time.h'中聲明瞭'gmtime'? – caf 2009-08-13 23:08:00

回答

5

這應該是準確的(填寫一份struct tm的切下來的模仿,我year使用,而不是1900 CE時代共同的時代):

struct xtm 
{ 
    unsigned int year, mon, day, hour, min, sec; 
}; 

#define YEAR_TO_DAYS(y) ((y)*365 + (y)/4 - (y)/100 + (y)/400) 

void untime(unsigned long unixtime, struct xtm *tm) 
{ 
    /* First take out the hour/minutes/seconds - this part is easy. */ 

    tm->sec = unixtime % 60; 
    unixtime /= 60; 

    tm->min = unixtime % 60; 
    unixtime /= 60; 

    tm->hour = unixtime % 24; 
    unixtime /= 24; 

    /* unixtime is now days since 01/01/1970 UTC 
    * Rebaseline to the Common Era */ 

    unixtime += 719499; 

    /* Roll forward looking for the year. This could be done more efficiently 
    * but this will do. We have to start at 1969 because the year we calculate here 
    * runs from March - so January and February 1970 will come out as 1969 here. 
    */ 
    for (tm->year = 1969; unixtime > YEAR_TO_DAYS(tm->year + 1) + 30; tm->year++) 
     ; 

    /* OK we have our "year", so subtract off the days accounted for by full years. */ 
    unixtime -= YEAR_TO_DAYS(tm->year); 

    /* unixtime is now number of days we are into the year (remembering that March 1 
    * is the first day of the "year" still). */ 

    /* Roll forward looking for the month. 1 = March through to 12 = February. */ 
    for (tm->mon = 1; tm->mon < 12 && unixtime > 367*(tm->mon+1)/12; tm->mon++) 
     ; 

    /* Subtract off the days accounted for by full months */ 
    unixtime -= 367*tm->mon/12; 

    /* unixtime is now number of days we are into the month */ 

    /* Adjust the month/year so that 1 = January, and years start where we 
    * usually expect them to. */ 
    tm->mon += 2; 
    if (tm->mon > 12) 
    { 
     tm->mon -= 12; 
     tm->year++; 
    } 

    tm->day = unixtime; 
} 

我對所有的幻數道歉。 367 *月/ 12是生成日曆的30/31天順序的巧妙方法。計算的工作時間從3月開始直到最後的修正,這使得事情變得簡單,因爲閏日落在「年」的末尾。

+1

而不是道歉的神奇數字,爲什麼不至少評論一些不太明顯的代碼中的東西?這個功能會受益於一些評論。 – 2009-08-14 01:58:17

+0

我已經添加了一些評論,希望對您有所幫助。 – caf 2009-08-14 03:12:29

0

在用戶空間中,glibc將在處理時間表示的「本地」部分方面做很多工作。在內核中,這是不可用的。也許你不應該在你的模塊中試圖打擾這一點,如果需要在用戶空間中做。

+1

我最終創建了一個定期將日期寫入proc接口的cron作業。看起來很迂迴,但它最終是比這個時機更好的解決方案。所以是的,只需從用戶空間拉入即可。 – mikepurvis 2009-08-20 17:50:01

0

A time_t是自1970年1月1日UTC以來的秒數,因此如果您希望得到UTC結果,那麼將其分解爲月,日和年並不困難。 Googleogging "gmtime source"有一個bunch of source available。由於依賴於時區設置和環境,大多數嵌入式系統都會讓本地時間處理變得更加困難。