3

これは誰もやるべきではないように思えますが、私は組み込みシステム (OpenWRT) 用のカーネル モジュールに取り組んでおり、その中にand型とand関数は含まれているようですtime.h 、 , , は含まれていないようです。、または重要なことに、タイプ。timespectime_tclock_gettimegmtimelocaltimectimetimetm

gmtime から自分の構造体にリターン ポインターをキャストしようとすると、segfault が発生します。

したがって、私は 2 つの方法のいずれかで問題を解決することに満足していると思います。不足している型にアクセスする方法、または UNIX タイムスタンプを分解するための独自の方法をロールする方法を理解するのは素晴らしいことです。

4

3 に答える 3

5

これは正確である必要があります ( 1900 年の CE エポックの代わりに Common Era を使用してstruct tm、のカットダウンの模倣を記入します):year

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*month/12 は、カレンダーの 30/31 日のシーケンスを生成する巧妙なトリックです。この計算は、3 月に始まり最後の修正までの年で機能します。これにより、閏日が「年」の終わりになるため、作業が簡単になります。

于 2009-08-14T01:44:11.493 に答える
0

Atime_tは 1970 年 1 月 1 日 UTC からの秒数であるため、UTC で結果が必要な場合、月、日、年に分解することはそれほど難しくありません。グーグル"gmtime source"で入手できるソースがたくさんあります。ほとんどの組み込みシステムは、タイムゾーンの設定と環境に依存するため、ローカル時間の処理が少し難しくなるため、省略しています。

于 2009-08-14T00:25:45.693 に答える
0

ユーザー空間では、glibc は時間表現の「ローカル」部分の処理に関して多くの作業を行います。カーネル内では、これは利用できません。必要に応じてユーザー空間で行う必要がある場合は、おそらくモジュール内でこれを気にしようとしないでください。

于 2009-08-13T22:56:21.007 に答える