【问题标题】:strtotime function in CC中的strtotime函数
【发布时间】:2015-08-09 19:02:45
【问题描述】:

我正在尝试在 C 中创建一个通用函数,该函数可以将任何格式的任何服务器日志文件中的日期转换为时间戳,因为我想记录潜在黑客破解服务器失败的频率。在 PHP 中我可以使用 strtotime,但我认为 C 中不存在这样的功能。

如果所有日志文件都使用 YYYY-MM-DD HH:MM:SS 形式的相同时间格式,那么我可以使用这样的代码:

//tmadd = 19 bytes as a char reserved for date/time plus trailing null
long result=0;
struct tm x;
if (sscanf(tmadd,"%i-%i-%i %i:%i:%i",&x.tm_year,&x.tm_mon,&x.tm_mday,&x.tm_hour,&x.tm_min,&x.tm_sec) >= 6){x.tm_year-=1900;result=mktime(&x);}

问题是一些日志有几个月作为单词,我还没有找到一个函数来捕获数字等价物。

我希望能够在一个函数中完成整个转换。

是否有一个简单的函数可以用来从任何指定日期以任何通用格式获取原始时间戳?我基本上是在寻找一种方法来推出我自己的 PHP 的 strtotime()。

【问题讨论】:

  • POSIX 有strptime()。 POSIX 不是通用的。
  • @pmg:很好奇:什么是通用的?我只能想到一个人,但这也可能与外星人(是的,来自上面的)编码有问题。
  • 当我在 C 的上下文中听到“通用”时,我将其解释为属于 C99 标准(或者如果“通用”包括 windows,则可能是 C89 标准)。
  • 如果您想捕捉多种格式并进行合理的错误检查,sscanf 可能不是一个好方法。不过,您可以存储多个模式,并逐个检查它们。
  • @pmg:嗯,那将是程序代码。对于数据格式,我实际上会看到更广泛的内容。或者只是坚持 ISO8601。但“普遍”是非常雄心勃勃的。

标签: php c date time strtotime


【解决方案1】:

转换任何时间格式的函数是一个非常雄心勃勃的项目,如查看 PHP strtotime 函数的公认日期格式所示。

但如果您的服务器上使用了一些已知的时间戳格式,您可以单独检查它们:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>

int strtomonth(int *mm, const char *str)
{
    static const char *sname[] = {
        "jan", "feb", "mar", "apr", "may", "jun",
        "jul", "aug", "sep", "oct", "nov", "dec",
        NULL
    };    
    int i;

    for (i = 0; sname[i]; i++) {
        if (strcmp(sname[i], str) == 0) {
            *mm = i + 1;
            return 1;
        }
    }

    return 0;
}

int strtotime(time_t *time, const char *s)
{
    struct tm tm;
    int dd, mm, yy;
    int hrs, min, sec;
    char buf[20];

    if (sscanf(s, "%u-%u-%u %u:%u:%u",
        &yy, &mm, &dd, &hrs, &min, &sec) == 6) goto okay;

    if (sscanf(s, "%u-%19[a-zA-Z]-%u %u:%u:%u",
        &yy, buf, &dd, &hrs, &min, &sec) == 6
        && strtomonth(&mm, buf)) goto okay;

    return 0;

  okay:
    // Do some sanity checking to rule out 2015-mar-35 and such

    tm.tm_sec = sec;
    tm.tm_min = min;
    tm.tm_hour = hrs;
    tm.tm_mday = dd;
    tm.tm_mon = mm - 1;
    tm.tm_year = yy - 1900;

    *time = mktime(&tm);
    return 1;
}

这段相当长但仍然非常粗略的代码,不检查日期和时间是否合理,识别"2015-05-30 18:13:04""2015-may-30 18:13:04"两种格式。您可以在遇到它们时添加更多。

goto 可能很难看,但我认为它是一个很好的方法来获取最后的通用代码。月份查找非常粗略,但对于短字符串应该没问题。

【讨论】:

  • 获得通用代码的更好方法是使该通用代码成为具有适当参数的函数。并在需要时调用它。
  • 很好奇,为什么是"%u-%u-%u ..." 而不是"%d-%d-%d ...?两者都接受'+''-'
  • @chux:是吗?在我的实现中他们没有。
  • unsigned u = 7; sscanf("-1", "%u", &amp;u); printf("%u\n", u); --> 4294967295 和 C 规范确实说 %u 匹配 strtoul()strtol()/strtoul() 接受 +/-
  • @chux: 好吧,我不熟悉 C 标准,但你是对的:“u -- 匹配可选带符号的十进制整数...”,我觉得这有点违反直觉。今天早上我用和你类似的测试测试它时,我得到的结果是 0,这个值仍然是我输入的魔法值,但这可能是因为那台机器不是超级最新的。无论如何:我对你的问题“为什么用%u 而不是%d”的回答是:因为它在语义上应该是无符号的,即使%d%u 在标准上看起来是一样的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多