将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()
?
发布于 2019-06-11 00:33:08
我可以使用
strptime()
解析到几分之一秒,但是手册页提到了setlocale()
,所以我担心我需要做些什么。我有吗?
是的,遗憾的是;根据区域设置,%S可能会占用小数秒,并且可能会查找小数逗号而不是小数点。
就我个人而言,我会完全手工完成这项工作,使用strtok
和strtol
,填充struct tm
的适当字段。您不必填写tm_yday
和tm_wday
即可使mktime
正常工作。
我假设我可以用TZ偏移量的分钟数来修改我从strptime获得的tm_min
。对,是这样?
这比看起来要难。根据时区偏移量的实际值,您将需要调整tm_hr
和tm_min
(实际上,常见的情况是整型小时数,因此您将调整tm_hr
而不是tm_min
),如果调整将时间推到了一天的界限上,您将需要标准化小时并确定日、月和年。
您还必须确保tm_isdst
和tm_gmtoff
为零,并且tm_zone
为空。
我可以只在开始时清除TZ和tzset()一次吗?
在一个“预期方式”有效的系统上,是的。然而,“预期的方式”并不能保证工作,事实上,如果你没有timegm
,我希望它不能工作。
使用timegm
。如果你没有timegm
,那就用get it from gnulib
。
发布于 2019-06-11 03:16:24
事实证明,写你自己的极简主义'mktime w/o时区胡言乱语‘并不是那么难。
#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
可能的特性。
https://stackoverflow.com/questions/56529899
复制相似问题