首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何将ISO8601解析为time_t?

如何将ISO8601解析为time_t?
EN

Stack Overflow用户
提问于 2019-06-11 00:09:58
回答 2查看 68关注 0票数 2

将ISO8601 datetimes解析为time_t的正确方法是什么?

输入字符串是ISO8601日期时间的特定变体:

1991-02-03T04:05:06.000-07:00

(我不需要担心'Z‘或隐含的本地时间变体)

我可以使用strptime()解析到几分之一秒,但是手册页提到了setlocale(),所以我担心我需要对此做些什么。Do I?还是只用于月份和日期之类的名称?

似乎没有任何方法可以跳过(或处理) strptime中的小数秒,而且我的版本似乎也不支持'%z‘(而且tm_gmtoff是非标准的),所以我不得不’手动‘解析输入的小数秒和时区偏移。很简单。

所以我假设我可以用TZ偏移量的分钟数修改从strptime获得的tm_min正确吗?

然后我们来看看mktime()。似乎强制它在UTC中运行的预期方式是:

get TZ,清除TZ,tzset()mktime(),reset TZ,tzset()

(有timegm(),但不是标准的)

我将处理很多这样的字符串,并且我不关心这个程序中的其他处理时间,所以这看起来像是很多毫无价值的开销,我能不能只在一开始就清除TZ和 tzset()

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-11 00:33:08

我可以使用strptime()解析到几分之一秒,但是手册页提到了setlocale(),所以我担心我需要做些什么。我有吗?

是的,遗憾的是;根据区域设置,%S可能会占用小数秒,并且可能会查找小数逗号而不是小数点。

就我个人而言,我会完全手工完成这项工作,使用strtokstrtol,填充struct tm的适当字段。您不必填写tm_ydaytm_wday即可使mktime正常工作。

我假设我可以用TZ偏移量的分钟数来修改我从strptime获得的tm_min。对,是这样?

这比看起来要难。根据时区偏移量的实际值,您将需要调整tm_hrtm_min (实际上,常见的情况是整型小时数,因此您将调整tm_hr而不是tm_min),如果调整将时间推到了一天的界限上,您将需要标准化小时并确定日、月和年。

您还必须确保tm_isdsttm_gmtoff为零,并且tm_zone为空。

我可以只在开始时清除TZ和tzset()一次吗?

在一个“预期方式”有效的系统上,是的。然而,“预期的方式”并不能保证工作,事实上,如果你没有timegm,我希望它不能工作。

使用timegm。如果你没有timegm,那就用get it from gnulib

票数 2
EN

Stack Overflow用户

发布于 2019-06-11 03:16:24

事实证明,写你自己的极简主义'mktime w/o时区胡言乱语‘并不是那么难。

代码语言:javascript
复制
#define divis(y,n) (((y) % (n)) == 0)
#define isLY(y) (divis((y),4) && (!divis((y),100) || divis((y),400)))
#define nLY(y)  (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)

static int      mdays[]         = {31,28,31,30,31,30,31,31,30,31,30,31};

/*
 * mktime implicitly applies the local timezone, this doesn't.
 * This also only works with valid values, no checking or normalizing happens.
 */
static time_t epoch (
        struct tm *     tm
) {
        int     years           = tm->tm_year + 1900;
        int     months          = tm->tm_mon;
        int     days            = tm->tm_mday - 1;
        int     hours           = tm->tm_hour;
        int     minutes         = tm->tm_min;
        int     seconds         = tm->tm_sec;

        if ((months > 1) && isLY(years)) ++days;
        while (months-- > 0) days += mdays[months];
        days += (365 * (years - 1970)) + nLY(years);
        return (time_t)((86400 * days) + (3600 * hours) + (60 * minutes) + seconds);
}

因此,我将把这一点与@zwol的答案中的建议结合起来,即“手动”解析字符串,而不必处理strptime()mktime()struct tm可能的特性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56529899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档