Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >c++11:使用HowardHinnant/date.h解析ISO8601格式字符串,并解决时区问题

c++11:使用HowardHinnant/date.h解析ISO8601格式字符串,并解决时区问题

作者头像
10km
发布于 2021-09-26 03:30:52
发布于 2021-09-26 03:30:52
1.2K00
代码可运行
举报
文章被收录于专栏:10km的专栏10km的专栏
运行总次数:0
代码可运行

C++11提供了std::get_time函数用于解析时间格式字符串,解析成功后将时间保存在std::tm结构中。

但是对于ISO8601标准中有毫秒精度的字符串比如('2014-11-12T19:12:14.505+0800')是不支持的。

如何解析这种有毫秒精度的时间字符串呢?

HowardHinnant/date

通过stakoverflow上的这个贴子:

《how do I parse an iso 8601 date (with optional milliseconds) to a struct tm in C++?》 https://stackoverflow.com/questions/26895428/how-do-i-parse-an-iso-8601-date-with-optional-milliseconds-to-a-struct-tm-in-c

我知道github上的开源代码HowardHinnant/date提供了这种支持.核心代码只有一个date.h头文件。include进来就可以使用。

下面是从贴子中抄来的使用HowardHinnant/date对ISO8601标准时间字符串解析的示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include "date.h"
#include <iostream>
#include <sstream>

date::sys_time<std::chrono::milliseconds>
parse8601(std::istream&& is)
{
    std::string save;
    is >> save;
    std::istringstream in{save};
    date::sys_time<std::chrono::milliseconds> tp;
    in >> date::parse("%FT%TZ", tp);
    if (in.fail())
    {
        in.clear();
        in.exceptions(std::ios::failbit);
        in.str(save);
        in >> date::parse("%FT%T%Ez", tp);
    }
    return tp;
}

int
main()
{
    using namespace date;
    using namespace std;
    // 这里输出显示为UTC时间
    cout << parse8601(istringstream{"2014-11-12T19:12:14.505Z"}) << '\n';
    cout << parse8601(istringstream{"2014-11-12T12:12:14.505-5:00"}) << '\n';
}

注意事项

  1. 要注意的是如果字符串中没有指定时区,HowardHinnant/date在解析时会自动解析成UTC时间,而不是本地时间。这与std::get_time是不一样的。
  2. 第二个问题是如果字符串中没有日期,只有时间(如12:12:14),HowardHinnant/date不能正确解析,所以建议是要判断日期格式,如果日期字符串没有只有时间,还是用std::get_time来解析.

时区问题

对于第一个问题其实HowardHinnant/date也提供了解决方案。进一步阅读HowardHinnant/date的源码,发现date::parse函数有好几个重载函数。上面的示例中只是用了参数最少最简单的一个,下面date::parse函数这个有4个参数的版本,后面两个参数都是用于时区设置的,如果正确指定了时区参数,解析出来的时间就是当前时区的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <class Parsable, class CharT, class Traits, class Alloc>
inline
auto
parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp,
      std::basic_string<CharT, Traits, Alloc>& abbrev, std::chrono::minutes& offset)
  • abbrev 指定提供时区名字缩写,如CST–中国标准时间(但这个参数似乎无效,我没有深究)
  • offset 相对GMT时间以分钟为单位时区偏移,比如北京时间东八区就是8x60=480。

这个第二个参数就是指定当前时区与GMT时间的偏移.默认这个参数为0,如果指定了该参数,则转换后的时间是以当前时区计算的时间。

所以上面的例子代码做如下修改,就可以支持将未指定时区的字符串解析为本地时间.说明参见代码中的中文注释。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 增加一个时区偏移参数 offset
static date::sys_time<std::chrono::milliseconds>
parse8601(std::istream&& is,int offset = 0/** 时区偏移 */)
{
    std::string save;
    is >> save;
    std::istringstream in{save};
    date::sys_time<std::chrono::milliseconds> tp;
    // 将 offset 传递给data:parse
    in >> date::parse("%FT%TZ", tp,std::string(), std::chrono::minutes(offset));
    if (in.fail())
    {
        in.clear();
        in.exceptions(std::ios::failbit);
        in.str(save);
        in >> date::parse("%FT%T%Ez", tp);
    }
    return tp;
}

int
main()
{
    using namespace date;
    using namespace std;
    // 这里输出显示为UTC时间
    cout << parse8601(istringstream{"2014-11-12T19:12:14.505Z"}) << '\n';
    cout << parse8601(istringstream{"2014-11-12T12:12:14.505-5:00"}) << '\n';
    /** 
     * 下面这个字符串没有指定时区,我们希望它解析为当前时间,
     * 所以offset使用北京时间(+08:00)的时区偏移
     */
    cout << parse8601(istringstream{"2014-11-12T12:12:14.505"},480) << '\n';
}

上面的例子中480仅对+08:00时区有效,如何自动获取当前时区的偏移呢?

参见我的上一篇博客:

《c,c++:获取当前时区偏移》

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/09/23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
地球时间和 C++ 时间库
GMT 是一个 时区,也指一种 时制。很久以前,科学家通过天文观察,将一个太阳日定义为 86400 秒,以英国 Greenwich 天文台白天平均太阳最高点作为正午 12:00,这样一个相对长度 + 一个绝对时刻,就定义了一套绝对时间体系,也就是 GMT 体系,同时 Greenwich 所在的时区也作为 GMT+0 时区。自1924年2月5日开始,Greenwich 天文台负责每隔一小时向全世界发放调时信息。再后来又从 GMT 升级到了 UT1,本质不变,还是基于天体测量。
JIFF
2019/09/10
3.4K0
地球时间和 C++ 时间库
一起Polyfill系列:让Date识别ISO 8601日期时间格式
一、什么是ISO 8601日期时间格式   ISO 8601是国际标准化组织制定的日期时间表示规范,全称是《数据存储和交换形式·信息交换·日期和时间的表示方法》。   示例:   1. 2014-12-12T00:00:00.000Z   2. 2014-12-12T00:00:00.000+08   3. 2014-12-12T00:00:00.000+0800   4. 2014-12-12T00:00:00.000+08:00   5. 2004-W17-3   6. 0001-165 详细说明请参考
^_^肥仔John
2018/01/18
1.7K0
了解一下ISO 8601是什么
上周的组内分享,有朋友介绍一个工具包生成的日期是UTC,需要转成北京时,另外还带了Z,很是不解,组长介绍说这是ISO 8601的日期格式标准。
bisal
2021/09/06
7.7K0
了解一下ISO 8601是什么
java如何将字符串转化为日期_java如何将字符串转为日期「建议收藏」
date.setlong currentTime = date.getTime();
全栈程序员站长
2022/11/16
5.3K0
ISO8601时间字符串到时间戳处理
作者:matrix 被围观: 8,903 次 发布时间:2019-06-21 分类:Python 兼容并蓄 | 无评论 »
HHTjim 部落格
2022/09/26
1.7K0
java iso8601 PT1M,iso8601
public static String getISO8601TimestampFromDateStr(String timestamp){
全栈程序员站长
2022/11/02
14.2K0
使用Python将时间或者时间间隔转为ISO 8601格式
Python自带的datetime库提供了将datetime转为ISO 8610格式的函数,但是对于时间间隔(inteval)并没有提供转换的函数,下面我们动手写一个。 对于时间间隔,ISO 8601的表示形式如下:
卡尔曼和玻尔兹曼谁曼
2019/01/22
2.2K0
使用Python将时间或者时间间隔转为ISO 8601格式
js格式化iso 8601格式的日期为其他格式-处理默认golang time类型格式问题
ISO 8601 格式的时间表示法,常用于表示世界范围内的时间和日期。ISO 8601 格式使用连字符 "-" 分隔日期和时间部分,并以字母 "T" 分隔日期和时间部分,其中 "T" 后面跟着时间部分。在这个时间表示中,"2023-03-09" 表示日期部分,"23:43:43+08:00" 表示时间部分和时区偏移量。其中,"+08:00" 表示相对于 UTC 时间偏移了 8 个小时,也就是北京时间。
唯一Chat
2023/03/10
1.8K0
详细介绍下C/C++时间相关的那些函数
chrono是一个关于时间的库,起源于boost,现在是C++的标准,话说现在的C++标准好多都是源于boost,要进标准的特性似乎都会先在boost试验一番。
C语言与CPP编程
2020/12/02
7420
详细介绍下C/C++时间相关的那些函数
iso815中文版_国际标准日期时间格式
严格的来说,这个标题可能不太正确,因为我首先度娘了一下,ISO8601时间格式标准应该类似于:2016-01-18T23:41:00-08:00,而UTC时间格式差不多类似
全栈程序员站长
2022/11/17
9630
Go各时间字符串的解析
format 的使用对象是一个 time.Time 对象,可以使用官方或者自己定义的布局进行格式化的输出,如:
caoayu
2020/09/23
1.5K0
时间序列 | 字符串和日期的相互转换
在数据处理过程中,难免会遇到日期格式,特别是从外部读取数据到jupyter或其他python编译器中,用于数据处理分析时。若读取excel文档时还能保留原本日期时间格式,但有时却差强人意,读取后为字符串格式,尤其是以csv格式存储的数据。此时就需要用到字符串转日期格式。
数据STUDIO
2021/06/24
7.5K0
Javascript中的Date.now() 方法与Date.UTC() 方法 ,Date.parse() 方法
Date.parse() 方法解析一个表示某个日期的字符串,并返回从1970-1-1 00:00:00 UTC 到该日期对象(该日期对象的UTC时间)的毫秒数,如果该字符串无法识别,或者一些情况下,包含了不合法的日期数值(如:2015-02-31),则返回值为NaN。
acoolgiser
2019/01/17
2K0
4.3 C++ Boost 日期时间操作库
Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量、可移植、高效的C应用程序。Boost库可以作为标准C库的后备,通常被称为准标准库,是C标准化进程的重要开发引擎之一。使用Boost库可以加速C应用程序的开发过程,提高代码质量和性能,并且可以适用于多种不同的系统平台和编译器。Boost库已被广泛应用于许多不同领域的C++应用程序开发中,如网络应用程序、图像处理、数值计算、多线程应用程序和文件系统处理等。
王瑞MVP
2023/08/18
5030
SO8601型字符串日期转Date
使用org.apache.log4j.helpers.ISO8601DateFormat;包 SO8601型字符串日期转成常用日期方法
MaybeHC
2024/04/23
1330
SpringBoot报错JSON parse error: Cannot deserialize value of type java.util.Date fr
最近对外部PHP提供一个查单接口,PHP传入的日期格式为:Y-m-d H:i:s ,如2023-12-28 09:50:59,SpringBoot中使用Date类型接收,接收失败,报错JSON parse error: Cannot deserialize value of type java.util.Date from String "2023-12-21 00:00:00": not a valid representation
高久峰
2023/12/28
9860
Java8中时间API
java.time.Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。
鱼找水需要时间
2023/04/28
9130
博采众长穿梭时空|Maya库使用笔记
用time、datetime等内置库处理时区需要挺多的代码,而且写法很不优雅,Maya是一个不错的第三方时间库,在pytz、pendulum等库基础上增强了对时区的处理。
蛰虫始航
2020/12/30
1.5K0
博采众长穿梭时空|Maya库使用笔记
C++之字符串
C语言中不提供字符串类型,因此所谓的字符串不过是一组以’\0’结尾的字符序列。 C语言中通常以char型的数组来存储字符串,如下例:
用户7886150
2021/02/16
6940
前端中的时间
这涉及到时间字符串格式的两个标准。前者4/29/2019是RFC2822格式,后者是ISO 8601格式。
LIYI
2019/09/02
2.1K0
相关推荐
地球时间和 C++ 时间库
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验