CでUNIX時間を分解する方法
-
16-09-2019 - |
質問
これは誰もやるべきではないことのように思えますが、私は組み込みシステム (OpenWRT) 用のカーネル モジュールに取り組んでいます。 time.h
する を含む timespec
そして time_t
種類と、 clock_gettime
そして gmtime
機能しますが、 ない 含む localtime
, ctime
, time
, 、または、批判的に言えば、 tm
タイプ。
gmtime から独自の構造体にリターン ポインタをキャストしようとすると、セグメンテーション違反が発生します。
したがって、私は 2 つの方法のいずれかで問題を解決できれば満足だと思います。欠落している型にアクセスする方法を見つけ出すか、あるいは、UNIX タイムスタンプを分解する独自の方法を開発する方法を見つけることができれば素晴らしいと思います。
解決
このは正確でなければなりません(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日シーケンスを生成するための巧妙なトリックです。計算は、うるう日は「年」の終わりに落ちるので、物事が容易になり最後にフィックスアップ、までは月にスタートの年で動作します。
他のヒント
ユーザ空間のglibcで時間表示の「ローカル」の部分を処理に関して多くの作業を行います。カーネル内でこれは使用できません。必要であれば、おそらくあなたはモジュール内でこれを気にしようとすべきではない、ユーザー空間でそれを行うます。
あ time_t
は 1970 年 1 月 1 日 (UTC) からの秒数なので、UTC での結果が必要な場合、これを月、日、年に分解することはそれほど難しくありません。があります 大量のソースが利用可能 グーグルで 「GMタイムソース」. 。ほとんどの組み込みシステムは、タイムゾーン設定と環境に依存するため、ローカル時間処理が少し難しいため、ローカル時間処理を省略します。