将ISO8601日期时间解析为time_t的正确方法是什么?
输入字符串是ISO8601日期时间的特定变体:
1991-02-03T04:05:06.000-07:00
(我不必担心'Z'或隐含的本地时间变体)
我可以使用strptime()
来解析小数秒,但是手册页中提到了setlocale()
,所以我担心我需要为此做些事情。 我可以吗?还是仅用于月份和日期名称?
似乎没有任何方法可以跳过(或处理)strptime中的小数秒,而且我的版本似乎也无论如何都不支持'%z'(并且tm_gmtoff
不是-standard),因此我无法解析“手动”输入的小数秒和时区偏移量。很容易。
所以我想我可以用strptime修改的tm_min
的TZ偏移量的分钟数。 正确吗?
然后我们来到mktime()
。似乎强制它在UTC中起作用的预期方式是:
获取TZ,清除TZ,
tzset()
,mktime()
,重置TZ,tzset()
(有一个timegm()
,但不是标准的)
我将要处理很多这样的字符串,并且我不在乎此程序中的任何其他时间,因此这似乎是很多毫无用处的开销,我可以清除TZ和{{ 1}}刚开始一次?
答案 0 :(得分:2)
我可以使用
strptime()
来解析小数秒,但是手册页中提到了setlocale()
,所以我担心我需要为此做些事情。我可以吗?
是的,很不幸;根据地区的不同,%S可能会消耗小数秒,并且可能会寻找小数点逗号而不是小数点。
我个人将完全手动完成此操作,并使用strtok
和strtol
,并填写struct tm
的适当字段。您无需填写tm_yday
和tm_wday
即可使mktime
正常工作。
我假设我可以用strptime修改的
tm_min
的TZ偏移量的分钟数。是吗?
这比看起来要难。根据时区偏移量的实际值,您将需要同时调整tm_hr
和tm_min
(实际上,通常情况是整小时数,因此您需要调整{{1 }},而不是tm_hr
),并且如果调整将时间推到一天的边界上,您将需要对小时进行归一化并确定日期,月份和年份。
还必须确保tm_min
和tm_isdst
为零,而tm_gmtoff
为NULL。
我可以一开始就清除一次TZ和tzset()吗?
在“预期方式”有效的系统上,可以。但是,不能保证“预期的方式”有效,实际上,如果您没有tm_zone
,我希望它不有效。
使用timegm
。如果您没有timegm
,则get it from gnulib
。
答案 1 :(得分:1)
结果证明,编写自己的极简主义的“不带时区废话的mktime”并不难。
let jsObj = {
"arrow-alt-circle-down": [
512,
512,
[],
"f358",
"M504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zM212 140v116h-70.9c-10.7 0-16.1 13-8.5 20.5l114.9 114.3c4.7 4.7 12.2 4.7 16.9 0l114.9-114.3c7.6-7.6 2.2-20.5-8.5-20.5H300V140c0-6.6-5.4-12-12-12h-64c-6.6 0-12 5.4-12 12z"
],
"other-fields": "preserved",
};
delete jsObj['arrow-alt-circle-down'];
console.log(jsObj);
因此,我将其与@zwol答案中的建议结合起来,以“手动”解析字符串,而不必处理#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);
}
,strptime()
和{{1} }的可能特质。