سؤال

يبدو أن هذا شيء لا ينبغي لأحد أن يفعله أحد، لكنني أعمل على وحدة نواة لنظام مضمن (OpenWrt) الذي يبدو فيه time.h يفعل تشمل timespec و time_t أنواع، و clock_gettime و gmtime وظائف، ولكن يفعل ليس تضمن localtime, ctime, time, ، أو، نقدي، tm يكتب.

عندما أحاول إلقاء مؤشر الإرجاع من GMTITT إلى بنية خاصة بي، أحصل على Segfault.

لذلك أعتقد أنني سأكون راضيا لحل المشكلة إما من طريقتين - سيكون من الرائع معرفة كيفية الوصول إلى هذا النوع المفقودين، أو بدلا من ذلك، كيفية لفة طريقة خاصة بي لتحليل طابع الزمني UNIX.

هل كانت مفيدة؟

المحلول

يجب أن يكون هذا دقيقا (يملأ تقليد خفض struct tm, ، لي year يستخدم العصر المشترك بدلا من 1900 CE Epoch):

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 هو عدد الثواني منذ 1 يناير 1970 UTC تحلل ذلك في الشهر واليوم والسنة ليست صعبة حيث تريد أن تكون النتيجة في UTC. هناك حفنة من المصدر المتاحة بواسطة googling. "GMTATE Source". وبعد تغادر معظم الأنظمة المضمنة معالجة التوقيت المحلي لأنها أكثر صعوبة بقليل بسبب الاعتماد على إعداد TimeZone والبيئة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top