【问题标题】:How to decompose unix time in C如何在C中分解unix时间
【发布时间】:2010-11-19 11:38:44
【问题描述】:

这似乎是任何人都不应该做的事情,但我正在为嵌入式系统 (OpenWRT) 开发一个内核模块,其中似乎 time.h 确实 包含 @ 987654322@ 和 time_t 类型,以及 clock_gettimegmtime 函数,但 包括 localtimectimetime,或者,重要的是,tm输入。

当我尝试将返回指针从 gmtime 转换为我自己的结构时,我得到一个段错误。

所以我想我会满足于以两种方式中的任何一种来解决问题 - 弄清楚如何访问那个丢失的类型,或者如何使用我自己的方法来分解 unix时间戳。

【问题讨论】:

  • gmtime 是如何在time.h 中声明的?

标签: c linux unix-timestamp time.h


【解决方案1】:

这应该是准确的(填写了struct tm 的缩小版,我的year 使用的是Common Era 而不是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*month/12 是生成日历的 30/31 天序列的巧妙技巧。该计算适用于从 3 月开始直到最后修正的年份,这使事情变得容易,因为闰日落在“年”的末尾。

【讨论】:

  • 与其为神奇的数字道歉,为什么不至少评论一些代码中不太明显的东西呢?此功能将受益于一些相当多的评论。
  • 我添加了一些 cmets,希望对您有所帮助。
【解决方案2】:

在用户空间中,glibc 将在处理“本地”部分时间表示方面做很多工作。在内核中这是不可用的。可能你不应该尝试在你的模块中解决这个问题,如果需要的话在用户空间中进行。

【讨论】:

  • 我最终创建了一个 cron 作业,该作业会定期将日期写入 proc 接口。似乎是迂回的,但它最终是一个比这个计时东西更好的解决方案。所以,是的,从用户空间中提取它是很好的选择。
【解决方案3】:

time_t 是自 1970 年 1 月 1 日 UTC 以来的秒数,因此只要您想要 UTC 格式的结果,将其分解为月、日和年并不难。谷歌搜索"gmtime source" 有一个bunch of source available。大多数嵌入式系统都忽略了本地时间处理,因为由于依赖于时区设置和环境,它有点困难。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 2017-03-05
    • 2012-10-01
    • 2011-03-03
    • 2017-02-20
    相关资源
    最近更新 更多