【问题标题】:fastest way to get time_t from YYYYMMDDHHMMSS string从 YYYYMMDDHHMMSS 字符串中获取 time_t 的最快方法
【发布时间】:2011-09-12 04:20:57
【问题描述】:

这是合法的吗?考虑到格式为 YYYYMMDDHHMMSS 的字符串,我试图尽快到达 time_t。

static time_t ConvertToSecSince1970(char *szYYYYMMDDHHMMSS)
{
struct tm    Tm;    

    memset(&Tm, 0, sizeof(Tm));
    Tm.tm_year = makeInt(szYYYYMMDDHHMMSS +  0, 4) - 1900;
    Tm.tm_mon  = makeInt(szYYYYMMDDHHMMSS +  4, 2) - 1;
    Tm.tm_mday = makeInt(szYYYYMMDDHHMMSS +  6, 2);
    Tm.tm_hour = makeInt(szYYYYMMDDHHMMSS +  8, 2);
    Tm.tm_min  = makeInt(szYYYYMMDDHHMMSS + 10, 2);
    Tm.tm_sec  = makeInt(szYYYYMMDDHHMMSS + 12, 2);
    return mktime(&Tm);
}

如果我使用以下方法创建 TM,似乎会产生相同的答案:

strptime(szYYYYMMDDHHMMSS, "%Y%m%d%H%M%S", &Tm);

我担心 tm_yday、tm_wday、tm_isdst、tm_gmtoff、tm_zone 很重要。我的日期是 UTC,所以我认为 gmtoff = 0 和 tm_zone = 0 可能有效。

顺便说一下,这里是makeInt:

inline int makeInt(const char *p, int size)
{
    const char *endp;
    int intval = 0;

    endp = p + size;
    while (p < endp)
    {
        intval = intval * 10 + *p - '0';
        p++;
    }
    return intval;
}

【问题讨论】:

  • 好吧,你猜怎么着。 mktime 需要 1.6 微秒,因此 getdate / strptime 约为 0.1 微秒而我的代码约为 0.02 微秒这一事实并不重要。瓶颈是 mktime。我想我会根据年、月、日进行查找并添加到秒数。
  • 在你的进程上运行 strace。如果未设置 TZ 环境变量,则一些 glibc 时间函数会执行 stat() 调用,并且可能在每个函数调用中执行更多。 (您可以将其设置为例如 :/etc/localtime 以避免这种情况,如果这是问题所在)

标签: c linux date mktime time-t


【解决方案1】:

除非你确定它太慢,否则你可能最好使用getdate。否则,你正在做的事情看起来相当不错,如果不是有点神秘的话。

【讨论】:

  • +1。我的(适度的)盒子可以每秒执行大约一千万次getdate(未优化的代码)。除非您需要更快,否则我会选择“标准”方法。即使您确实需要它更快,您也可能会发现这很困难。
  • 两个问题。速度很重要,而我正在做的事情已经在推动它了……该死的字符串日期。 GetDate 有效,但时区为 GMT。有任何想法吗。我正在谷歌搜索如何告诉 getdate GMT 或 UTC 中的字符串。
  • @johnny,我很好奇速度要求。你到底在做什么,需要这么快?
  • 我注意到了一件有趣的事情。 getdate 未设置 tm_isdstm、tm_gmtoff 或 tm_zone。你需要给它发送一个归零的 Tm。
  • 来自 getdate(3) 手册页:“在 glibc 中,getdate() 是使用 strptime(3) 实现的”。由于 getdate() 必须迭代尝试不同的格式,它比直接使用已知格式调用 strptime() 慢。
【解决方案2】:

mktime() 忽略 tm_wdaytm_yday 字段,并根据其他字段为它们计算新值。这同样适用于 BSD 扩展 tm_gmtofftm_zone,除了它们是根据本地时区计算的。

但请注意,mktime() 使用 本地 时间,而不是 UTC,因此如果您输入的日期是 UTC,那么您的时区必须设置为 UTC。

【讨论】:

  • 最后一句到底是什么意思?如何将时区设置为 UTC?幸运的是我们的是,但如果不是呢?
  • @johnnycrash:标准 C 中没有办法做到这一点,但在 linux 上,您可以在启动应用程序之前设置 TZ 环境变量。这句话的意思是mktime() 将您的struct tm 解释为本地时区的时间。
【解决方案3】:

一般来说,日期和时间处理有很多棘手的问题,所以我强烈推荐 strptime() 而不是自己动手。如果 strptime() 的性能是瓶颈,请以其他方式解决它,而不是尝试创建更好的 strptime(),例如

  1. 您的字符串以及 time_t(通常使用它)仅提供秒精度,因此您可以缓存转换后的值并每秒仅更新一次。

  2. 首先不要使用字符串形式的时间戳。例如。传递一个 time_t 值(包含由 time() 返回的 Epoch 以来的秒数),并且仅在/如果您需要将其打印/显示给用户/时将其转换为字符串。

【讨论】:

  • 不幸的是,代码有数百万行,而且他们喜欢字符串。但是,基于年 * 12 * 31 + 月 * 31 + 日的查找表在 20 年内
猜你喜欢
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多