你知道计算 Unix 时间和日期的 C 宏吗? [英] Do you know of a C macro to compute Unix time and date?

查看:30
本文介绍了你知道计算 Unix 时间和日期的 C 宏吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有人知道/有一个 C 宏来从硬编码的日期和时间计算静态 Unix 时间,如下所示:

I'm wondering if someone knows/has a C macro to compute a static Unix time from a hard coded date and time as in:

time_t t = UNIX_TIMESTAMP(2012, 5, 10, 9, 26, 13);

我正在研究这个,因为我想要一个数字静态时间戳.这将在整个软件中执行数百次,每次都有不同的日期,我想确保它很快,因为它每秒会运行数百次.多次转换日期肯定会减慢速度(即调用 mktime() 比在适当位置编译静态数字慢,对吗?)

I'm looking into that because I want to have a numeric static timestamp. This will be done hundred of times throughout the software, each time with a different date, and I want to make sure it is fast because it will run hundreds of times every second. Converting dates that many times would definitively slow down things (i.e. calling mktime() is slower than having a static number compiled in place, right?)

[2012 年 11 月 23 日进行了更新以尝试使此段落更清晰]

[made an update to try to render this paragraph clearer, Nov 23, 2012]

更新

我想通过有关正在使用的流程的更多信息来澄清这个问题.当我的服务器收到请求时,对于每个请求,它都会启动一个新进程.该过程会不断使用新插件进行更新,并且此类更新通常需要数据库更新.那些必须只运行一次.要知道是否需要更新,我想使用 Unix 日期(这比使用计数器更好,因为计数器更容易偶尔中断.)

I want to clarify the question with more information about the process being used. As my server receives requests, for each request, it starts a new process. That process is constantly updated with new plugins and quite often such updates require a database update. Those must be run only once. To know whether an update is necessary, I want to use a Unix date (which is better than using a counter because a counter is much more likely to break once in a while.)

插件将因此接收更新信号并调用它们的 on_update() 函数.在那里我想做这样的事情:

The plugins will thus receive an update signal and have their on_update() function called. There I want to do something like this:

void some_plugin::on_update(time_t last_update)
{
  if(last_update < UNIX_TIMESTAMP(2010, 3, 22, 20, 9, 26)) {
    ...run update...
  }
  if(last_update < UNIX_TIMESTAMP(2012, 5, 10, 9, 26, 13)) {
    ...run update...
  }
  // as many test as required...
}

如您所见,如果我每次都必须计算 unix 时间戳,这可能代表每个进程的数千次调用,如果您每秒收到 100 次点击 x 1000 次调用,那么您本可以拥有编译器时浪费了 100,000 次调用在编译时计算一次这些数字.

As you can see, if I have to compute the unix timestamp each time, this could represent thousands of calls per process and if you receive 100 hits a second x 1000 calls, you wasted 100,000 calls when you could have had the compiler compute those numbers once at compile time.

将值放入静态变量没有意义,因为此代码将在每次进程运行时运行一次.

Putting the value in a static variable is of no interest because this code will run once per process run.

请注意,last_update 变量会根据被点击的网站(它来自数据库)而变化.

Note that the last_update variable changes depending on the website being hit (it comes from the database.)

代码

好的,我现在得到了代码:

Okay, I got the code now:

// helper (Days in February)
#define _SNAP_UNIX_TIMESTAMP_FDAY(year) \
    (((year) % 400) == 0 ? 29LL : \
        (((year) % 100) == 0 ? 28LL : \
            (((year) % 4) == 0 ? 29LL : \
                28LL)))

// helper (Days in the year)
#define _SNAP_UNIX_TIMESTAMP_YDAY(year, month, day) \
    ( \
        /* January */    static_cast<qint64>(day) \
        /* February */ + ((month) >=  2 ? 31LL : 0LL) \
        /* March */    + ((month) >=  3 ? _SNAP_UNIX_TIMESTAMP_FDAY(year) : 0LL) \
        /* April */    + ((month) >=  4 ? 31LL : 0LL) \
        /* May */      + ((month) >=  5 ? 30LL : 0LL) \
        /* June */     + ((month) >=  6 ? 31LL : 0LL) \
        /* July */     + ((month) >=  7 ? 30LL : 0LL) \
        /* August */   + ((month) >=  8 ? 31LL : 0LL) \
        /* September */+ ((month) >=  9 ? 31LL : 0LL) \
        /* October */  + ((month) >= 10 ? 30LL : 0LL) \
        /* November */ + ((month) >= 11 ? 31LL : 0LL) \
        /* December */ + ((month) >= 12 ? 30LL : 0LL) \
    )

#define SNAP_UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
    ( /* time */ static_cast<qint64>(second) \
                + static_cast<qint64>(minute) * 60LL \
                + static_cast<qint64>(hour) * 3600LL \
    + /* year day (month + day) */ (_SNAP_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * 86400LL \
    + /* year */ (static_cast<qint64>(year) - 1970LL) * 31536000LL \
                + ((static_cast<qint64>(year) - 1969LL) / 4LL) * 86400LL \
                - ((static_cast<qint64>(year) - 1901LL) / 100LL) * 86400LL \
                + ((static_cast<qint64>(year) - 1601LL) / 400LL) * 86400LL )

警告:不要使用这些宏来动态计算日期.它比 mktime() 慢.话虽如此,如果您有一个硬编码的日期,那么编译器将在编译时计算 time_t 值.编译速度较慢,但​​反复执行速度较快.

WARNING: Do not use these macros to dynamically compute a date. It is SLOWER than mktime(). This being said, if you have a hard coded date, then the compiler will compute the time_t value at compile time. Slower to compile, but faster to execute over and over again.

推荐答案

POSIX 中的公式:

The formula is in POSIX:

tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
    (tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
    ((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400

来源:XBD 4.15 秒自 Epochhttp://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15

Source: XBD 4.15 Seconds Since the Epoch http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15

这篇关于你知道计算 Unix 时间和日期的 C 宏吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆