C++ 之boost/date_time/posix_time高精度计时详细总结

文章目录

    • 概要
    • 时间长度类time_duration
    • 时间点ptime
    • 时间区域time_period
    • 时间迭代器
    • 实际应用1:(计算加速度)
    • 实际应用2:可以支持秒级和微秒/纳秒级计时器

概要

使用date_time库需要在编译时加上"-lboost_date_time",而且需要包含以下头文件:

处理日期的组件:#include <boost/date_time/gregorian/gregorian.hpp>

处理时间的组件:#include <boost/date_time/posix_time/posix_time.hpp>

时间长度类time_duration

date_time库使用time_duration度量时间长度。它可以表示包括时、分、秒、毫秒的时间长度。类似日期长度类date_duration有days、weeks、months、years这些常用类,time_duration也有几个子类:hours、minutes、seconds、millisec、microsec、nanosec,他们都支持流输入输出、比较操作、加减乘除运算。

    //对象的定义boost::posix_time::time_duration td(1, 10, 30, 1000); //1小时10分钟30秒1毫秒boost::posix_time::time_duration  td1(1, 60, 60, 1000); //2小时1分钟1毫秒,超出的时间会自动进位boost::posix_time::time_duration td2 = boost::posix_time::duration_from_string("1:10:30:001");  //1小时10分钟30秒1毫秒//成员函数assert(td.hours() == 1 && td.minutes() == 10 && td.seconds() == 30);assert(td.total_seconds() == 1 * 3600 + 10 * 60 + 30);//获取字符串表示cout << boost::posix_time::to_simple_string(td) << endl; //输出为 01:10:30.001000cout << boost::posix_time::to_iso_string(td) << endl; //输出为 011030.001000//运算boost::posix_time::hours h(1);boost::posix_time::minutes m(10);boost::posix_time::seconds s(30);boost::posix_time::millisec ms(1);boost::posix_time::time_duration td3 = h + m + s + ms;assert(td2 == td3);
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;int main()
{time_duration td(1,2,3,888);std::cout<<td<<std::endl;// 01:02:03.000888hours h(2);//时minutes(20);//分seconds(4);//秒millisec(999);//毫秒microsec(22);//微秒
}

时间长度可以是任意数字,超出范围的值会进位或借位:

    time_duration td(1,10086,3,888);std::cout<<td<<std::endl;// 169:06:03.000888

使用子类可以直观地赋值:

    time_duration td2 = hours(2) + minutes(30) + seconds(77);

也可以从字符串创建:

    time_duration td3 = duration_from_string("1:10:20:333");

成员函数:

#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;int main()
{time_duration td(1,10086,3,888);std::cout<<td<<std::endl;// 169:06:03.000888std::cout<<td.hours()<<std::endl;//169std::cout<<td.minutes()<<std::endl;//6std::cout<<td.seconds()<<std::endl;//3std::cout<<td.total_seconds()<<std::endl;//时间长度的总秒数       608763std::cout<<td.total_milliseconds()<<std::endl;//总毫秒数         608763000std::cout<<td.fractional_seconds()<<std::endl;//以long返回微秒数  888std::cout<<td.total_microseconds()<<std::endl;//总微秒数          608763000888std::cout<<td.total_nanoseconds()<<std::endl;//总纳秒数           608763000888000std::cout<<td.is_negative()<<std::endl;//是否负值//is_xxx() 是否特殊时间 略std::cout<<to_simple_string(td)<<std::endl;//169:06:03.000888std::cout<<to_iso_string(td)<<std::endl;//1690603.000888
}

要让精度变为纳秒级别,在导入文件之前定义宏:

#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;int main()
{time_duration td(1,10086,3,888);std::cout<<td<<std::endl;std::cout<<td.total_microseconds()<<std::endl;std::cout<<td.total_nanoseconds()<<std::endl;
}

输出:

时间点ptime

创建ptime的方法是在其构造函数传入一个date和一个time_duration,不传入time_duration的话为0点,ptime支持流输入输出、比较操作、减法运算、与date_duration、time_duration的加减运算。时间点的概念可以理解为一个日期加上一个小于24小时的时间长度。

ptime 是时间点的类,它是很轻量级的对象。

//对象的定义boost::posix_time::ptime p(boost::gregorian::date(2010, 3, 5)); //2010年3月5号0点boost::posix_time::ptime p1(boost::gregorian::date(2010, 3, 5), boost::posix_time::hours(1)); //2010年3月5号1点boost::posix_time::ptime p2 = boost::posix_time::time_from_string("2010-3-5 01:00:00");boost::posix_time::ptime p3 = boost::posix_time::from_iso_string("20100505T010000");//获取当前时间boost::posix_time::ptime p4 = boost::posix_time::second_clock::local_time(); //本地时间,秒精度cout << p4 << endl; //可以直接输出ptime,2018-Apr-11 16:23:54boost::posix_time::ptime p4 = boost::posix_time::microsec_clock::local_time(); //本地时间,微妙精度,2018-Apr-11 08:23:54.986535//boost::posix_time::ptime p4 = boost::posix_time::second_clock::universal_time(); //UTC时间,微妙精度//获取字符串表示cout << boost::posix_time::to_iso_extended_string(p) << endl; //输出为2010-03-05T00:00:00cout << boost::posix_time::to_iso_string(p) << endl; //输出为20100305T000000cout << boost::posix_time::to_simple_string(p) << endl; //输出为2010-Mar-05 00:00:00

 ptime相当于date + time_duration,所以对于它的操作可以分解为对这两个部分的操作,可以通过两个成员函数date()和time_of_day()获得日期和时间段,然后分别处理,如:

boost::posix_time::ptime p4(boost::gregorian::date(2010, 3, 20), boost::posix_time::hours(12) + boost::posix_time::minutes(30));boost::gregorian::date d = p4.date(); //获取dateboost::posix_time::time_duration td4 = p4.time_of_day(); //获取time_durationassert(d.month() == 3 && d.day() == 20);assert(td4.total_seconds() == 12 * 3600 + 30 * 60);boost::posix_time::ptime p5 = p4 + boost::posix_time::hours(3);assert(p4 < p5);assert(p5 - p4 == boost::posix_time::hours(3));p5 += boost::gregorian::months(1);boost::posix_time::ptime pTime = boost::posix_time::second_clock::local_time(); //获取本地时间 ,秒精度std::string strDate = boost::gregorian::to_iso_extended_string(pTime.date()); // 当前日期:2019-03-06std::string strTimeOfDay = boost::posix_time::to_simple_string(pTime.time_of_day()); // 当前时间:15:03:55std::string strTime = strDate + ", " + strTimeOfDay; // 当前日期和时间:2019-03-06, 15:03:55

boost::posix_time::to_tm()可以由ptime转换为tm,如果想要把tm转换为ptime,可以使用boost::gregorian::date_from_tm()得到date对象,然后再根据tm得到time_duration对象,最后通过date和time_duration创建出ptime。

boost::posix_time::to_time_t()可以由ptime转换为time_t,boost::posix_time::from_time_t()可以由time_t转换为ptime,但这两个函数是以UTC时间为标准的,使用的话还需要进行时区转换。

不同于日期迭代器,时间迭代器只有一个time_iterator,在它的构造函数中传入一个起始时间ptime和一个步长time_duration,eg:

boost::posix_time::ptime p6(boost::gregorian::date(2010, 2, 27), boost::posix_time::hours(10));boost::posix_time::time_iterator t_iter(p6, boost::posix_time::minutes(20));for (; t_iter < p6 + boost::posix_time::hours(1); ++t_iter){cout << *t_iter << endl;}//输出为://2010 - Feb - 27 10:00 : 00//2010 - Feb - 27 10 : 20 : 00//2010 - Feb - 27 10 : 40 : 00

创建对象:

#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;
int main()
{ptime p (date(2035,10,1),hours(20));std::cout<<p<<std::endl;std::cout<<time_from_string("2010-11-11 01:30:20")<<std::endl;std::cout<<from_iso_string("20101111T013020")<<std::endl;//从时钟产生当前时间ptime p1 = second_clock::local_time();//秒精度ptime p2 = microsec_clock::universal_time();//微秒精度std::cout<<p1<<" "<<p2<<std::endl;boost::posix_time::ptime p4 = boost::posix_time::microsec_clock::local_time(); //本地时间,微妙精度,2018-Apr-11 08:23:54.986535//boost::posix_time::ptime p4 = boost::posix_time::second_clock::universal_time(); //UTC时间,微妙精度//特殊时间std::cout<<ptime(not_a_date_time)<<std::endl;//无效时间点
}

输出:

由于 ptime 相当于 date time_duration,所以对它的操作可以分解为对这两个组成部分的操作:

#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;
int main()
{ptime p (date(2035,10,1),hours(20) + minutes(30) + microsec(444));date d = p.date();time_duration td = p.time_of_day();//支持比较操作和加减操作ptime p2 = p + hours(3);//转换为字符串//1、转换为YYYY-mm-DD HH:MM:SS.ffffff(微秒)格式std::cout<<to_simple_string(p)<<std::endl;//2、转换为YYYYMMDDTHHMMSS,ffffff(微秒)格式std::cout<<to_iso_string(p)<<std::endl;//3、转换为YYYY-MM-DDTHH:MM:SS,ffffff(微秒)格式std::cout<<to_iso_extended_string(p)<<std::endl;std::cout<<p<<std::endl;
}

输出:

时间区域time_period

与日期区间date_period对应,date_time库也有时间区间的概念,类time_period使用ptime作为区间的两个端点,同样是左闭右开区间,它与date_period用法基本相同。
 

#include <iostream>  
#include <boost/date_time/posix_time/posix_time.hpp>  
#include <boost/date_time/gregorian/gregorian.hpp>  
using namespace std;  
using namespace boost::posix_time;  
using namespace boost::gregorian;  int main()  
{  ptime p(date(2014,1,1),hours(12)) ;  time_period tp1(p, hours(8));               //一个8小时的区间  time_period tp2(p + hours(8), hours(1));    //1小时的区间  if (tp1.end() == tp2.begin() && tp1.is_adjacent(tp2))  cout << "两个区间相邻\n";  if (!tp1.intersects(tp2))  cout << "两个区间不相交\n";  tp1.shift(hours(1));                        //平移1小时  if (tp1.is_after(p))  cout << "tp1在中午之后\n";  if (tp1.intersects(tp2))  cout << "两个区间现在相交\n";  tp2.expand(hours(10));                      //向两端扩展10小时  if (tp2.contains(p) && tp2.contains(tp1))  cout << "tp2包含p且包含tp1\n";  return 0;  
}  输出:
两个区间相邻
两个区间不相交
tp1在中午之后
两个区间现在相交
tp2包含p且包含tp1

boost::posix_time::time_periodticks()方法用于获取时间间隔的持续时间。

在Boost库中,boost::posix_time::time_period表示一个时间间隔,它由两个时间点定义:开始时间和结束时间。ticks()方法用于获取这个时间间隔的总持续时间,单位是ticks(一个非常小的、固定的时间单位)。

使用方法

要使用ticks()方法,首先需要包含相应的头文件:

#include <boost/date_time/posix_time/posix_time.hpp>

然后,创建一个boost::posix_time::time_period对象,并调用其ticks()方法:

boost::posix_time::time_period period(start_time, end_time);
unsigned long ticks = period.ticks();

其中,start_timeend_timeboost::posix_time::ptime类型的对象,表示时间间隔的开始和结束时间。

示例代码

以下是一个简单的示例,演示如何使用ticks()方法:

#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>int main() {// 定义开始时间和结束时间boost::posix_time::ptime start_time = boost::posix_time::second_clock::local_time(); //获取本地时间,精确到秒
//boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time();//获取本地时间,微秒精度boost::posix_time::ptime end_time = start_time + boost::posix_time::seconds(10); // 10秒后结束// 创建时间间隔对象boost::posix_time::time_period period(start_time, end_time);//如果获取start_time是采用的微秒精度,则获取到ticks后,需要转化为秒,1微秒=0.000001秒,也即ticks * 0.000001// 获取时间间隔的ticks数unsigned long ticks = period.ticks();std::cout << "Ticks: " << ticks << std::endl; // 输出ticks数return 0;
}

这段代码创建了一个10秒的时间间隔,并输出其ticks数。

时间迭代器

时间迭代器类只有一个 time_iterator,它构造时传入一个起始时间点 ptime 对象和一个步长 time_duration 对象。

time_iterator 可以直接和 ptime 比较,无需使用解引用操作符。

#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;
int main()
{ptime p(date(2022,10,1),hours(10));for(time_iterator it(p,minutes(10));it < p + hours(1);++it){std::cout<<*it<<std::endl;}
}

输出:

实际应用1(计算加速度)

float ComputeVehAcc(const float &speed) {float acc;boost::posix_time::ptime time_now = boost::posix_time::microsec_clock::local_time();//获取本地时间,微秒精度if(last_time != boost::posix_time::not_a_date_time) {boost::posix_time::time_duration time_period = (time_now - last_gps_time);//时间差int tickes = time_period.ticks(); //获取时间间隔的总持续时长cycle_time = tickes * 0.000001;//此处是微秒精度,需要转化为多少秒,假设控制周期100ms;1微秒=0.000001秒acc = (speed - last_speed) / cycle_time;} else {acc = 0.0;}  last_speed = speed;last_time = time_now;return acc;}
boost::posix_time::not_a_date_time
boost::posix_time::not_a_date_time 是一个异常,它在使用 boost::posix_time 库时可能会抛出。这个异常通常表示试图创建一个无效或不合法的 ptime 或 date_time 对象。解决方法:检查输入是否合法:确保你在创建 ptime 或 date_time 对象时使用的日期和时间是有效的。时间范围:确保你没有尝试创建一个超出允许范围的时间(例如,不要创建一个年数小于1474年或大于2037年的日期)。时区处理:如果你在使用带有时区的 date_time 对象,确保你正确处理了时区转换。格式问题:如果你是从字符串解析日期和时间,确保字符串的格式与你使用的解析函数相匹配,并且字符串包含有效的日期和时间值。更新Boost库:确保你使用的Boost版本是最新的,或者至少是一个稳定的版本,因为在旧版本中可能存在已知的bug导致这个异常。异常处理:在你的代码中,正确地捕获并处理这个异常,比如通过使用 try-catch 块来处理异常情况。如果你遵循了上述建议,仍然遇到了问题,可能需要查看具体的代码和上下文,以便进一步诊断问题

实际应用2:一个可以支持秒级别和微秒 / 纳秒级别的计时器

#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;template<typename Clock = microsec_clock> //默认为微秒级别
class basic_ptimer
{
public:basic_ptimer(){restart();}~basic_ptimer(){elapsed();}void restart(){_start_time = Clock::local_time();}void elapsed() const{std::cout << Clock::local_time() - _start_time <<std::endl;}
private:ptime _start_time;
};
//typedef basic_ptimer<microsec_clock> ptimer;
//typedef basic_ptimer<second_clock>   sptimer;using ptimer = basic_ptimer<microsec_clock>;
using sptimer = basic_ptimer<second_clock>;int main()
{ptimer p;sptimer s;for(int i = 1,sum = 0;i < 100000000;++i){sum += i;}
}

输出:

参考:

1、boost:date_time库——处理时间_boost 时间 微秒-CSDN博客 

2、boost--时间处理 - 整鬼专家 - 博客园

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/465265.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小语言模型介绍与LLM的比较

小模型介绍 小语言模型&#xff08;SLM&#xff09;与大语言模型&#xff08;LLM&#xff09;相比&#xff0c;具有不同的特点和应用场景。大语言模型通常拥有大量的参数&#xff08;如 GPT-3 拥有 1750 亿个参数&#xff09;&#xff0c;能够处理复杂的自然语言任务&#xff…

Kafka 可观测性最佳实践

Kafka 概述 Kafka 是由 LinkedIn 开发一个分布式的基于发布订阅模式的消息队列&#xff0c;是一个实时数据处理系统&#xff0c;可以横向扩展。与 RabbitMQ、RockerMQ 等中间件一样拥有几大特点&#xff1a; 异步处理服务解耦流量削峰 监控 Kafka 是非常重要的&#xff0c;因…

混合式学习平台:企业培训的新选择

在当前的商业环境中&#xff0c;企业普遍采用在线直播课程进行员工培训。然而&#xff0c;在线学习常常伴随着焦虑、疲劳和效率低下等问题&#xff0c;这些都是企业在进行在线培训时需要面对和解决的挑战。本文将探讨如何通过使用白板协作工具——即时白板&#xff0c;来提高企…

内网项目,maven本地仓库离线打包,解决Cannot access central in offline mode?

背景&#xff1a; 内网项目打包&#xff0c;解决Cannot access central in offline mode? 1、修改maven配置文件&#xff1a; localRepository改为本地仓库位置 <localRepository>D:\WorkSpace\WorkSoft\maven-repository\iwhalecloud-repository\business</loca…

如何用 ChatPaper.ai 打造完美的 AI 课堂笔记系统

作为学生&#xff0c;我们都遇到过这样的困扰&#xff1a;上课时记笔记太投入就听不进讲解&#xff0c;专注听讲又担心错过重要知识点。有了AI助手&#xff0c;这个问题就可以优雅地解决了。今天跟大家分享如何用ChatPaper.ai构建个人的智能课堂笔记系统。 为什么需要AI辅助记笔…

雷池社区版 7.1.0 LTS 发布了

LTS&#xff08;Long Term Support&#xff0c;长期支持版本&#xff09;是软件开发中的一个概念&#xff0c;表示该版本将获得较长时间的支持和更新&#xff0c;通常包含稳定性、性能改进和安全修复&#xff0c;但不包含频繁的新特性更新。 作为最受欢迎的社区waf&#xff0c…

C语言心型代码解析

方法一 心型极坐标方程 爱心代码你真的理解吗 笛卡尔的心型公式&#xff1a; for (y 1.5; y > -1.5; y - 0.1) for (x -1.5; x < 1.5; x 0.05) 代码里面用了二个for循环&#xff0c;第一个代表y轴&#xff0c;第二个代表x轴 二个增加的单位不同&#xff0c;能使得…

【云原生开发】如何通过client-go来操作K8S集群

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

开源协议类型及长安链开源协议介绍

截至目前&#xff0c;我国参与国际开源社区协作的开发者数量排名全球第二并推出了众多社区活跃度较高的高质量开源项目&#xff0c;是全球开源生态的重要贡献力量&#xff0c;但在开源治理方面我国还处于发展初期&#xff0c;大部分开发者对开源的印象还限于开放代码、免费使用…

计算机网络:网络层 —— 边界网关协议 BGP

文章目录 路由选择协议动态路由协议边界网关协议 BGPBGP 的基本概念BGP-4 的四种报文 路由选择协议 因特网是全球最大的互联网&#xff0c;它所采取的路由选择协议具有以下三个主要特点&#xff1a; 自适应&#xff1a;因特网采用动态路由选择&#xff0c;能较好地适应网络状态…

Kubernetes——part9-2 kubernetes集群java项目上云部署

一、部署前准备工作 1.1 部署项目情况 1.1.1 业务部署架构 单体服务架构分布式服务架构微服务架构超微服务架构 1.1.2 项目涉及第三方服务 关系型数据库系统 MySQL缓存服务 Redis memcache协调服务 zookeeper消息中间件服务 kafka rabbitmq服务注册 服务发现 nacos 1.1.3…

基于SpringBoot的免税商品优选购物商城的设计与实现

一、项目背景 从古至今&#xff0c;通过书本获取知识信息的方式完全被互联网络信息化&#xff0c;但是免税商品优选购物商城&#xff0c;对于购物商城工作来说&#xff0c;仍然是一项非常重要的工作。尤其是免税商品优选购物商城&#xff0c;传统人工记录模式已不符合当前社会…

光伏无人机踏勘,照亮光伏未来!

光伏电站选址地分散在各地&#xff0c;想要精准获取该地的地形特点与屋顶面积等信息&#xff0c;传统的人工踏勘耗时耗力且精度无法保证&#xff0c;难以满足现代光伏项目的规模快发发展需求。光伏无人机踏勘&#xff0c;照亮光伏未来&#xff01; 在光伏无人机智能踏勘设计系统…

Angular引用控件类

说明&#xff1a; angular 在一个控件类里面&#xff0c;引入另外一个控件类&#xff0c;这样做的好处&#xff0c;就是代码分离&#xff0c;当你一个页面存在多少类似于独立的界面时&#xff0c;可以使用这种方式&#xff0c;分离代码 更好维护程序 效果图&#xff1a; step…

Android 面试题汇总

Android 面试题汇总 文章目录 Android 面试题汇总快手一面同程旅行一面快手二面虎牙二面蚂蚁一面 很多八股文的差不多&#xff0c;这里只汇总一些我不会的知识点 快手一面 tcp三次握手&#xff0c;最后一次失败&#xff0c;网络会怎么样&#xff1f; 如果第三次握手失败的时候…

SQL常见语法

select * from student; select&#xff1a;选取 from&#xff1a;来源 *&#xff1a;所有栏位 select 姓名&#xff0c;班级&#xff0c;成绩 from students; 选取特定栏位 select 姓名&#xff0c;班级&#xff0c;成绩 from students limit 5;--限制显示拦数 select 姓…

用ChatGPT提高工作效率,轻松搞定每天任务!

ChatGPT 在现代工作环境中的关键作用 随着数字化时代的到来&#xff0c;商业环境也进入了一个迅速发展的新时代&#xff0c;技术进步成为推动这一变革的核心力量。自动化和效率已不再是理想&#xff0c;而是企业保持竞争力的必备条件。在这一变化的过程中&#xff0c;人工智能…

程序员开发速查表

作为一名苦逼的程序员&#xff0c;在开发的过程中&#xff0c;我们总是在各种编程语言中来回穿梭&#xff0c;忙完后端整前端&#xff0c;还得做一部分的运维工作&#xff0c;忙的我们有时候忘记语法&#xff0c;忘记编写规则&#xff0c;甚至混淆。这时候我们就希望有一个综合…

【大数据学习 | kafka高级部分】kafka的快速读写

1. 追加写 根据以上的部分我们发现存储的方式比较有规划是对于后续查询非常便捷的&#xff0c;但是这样存储是不是会更加消耗存储性能呢&#xff1f; 其实kafka的数据存储是追加形式的&#xff0c;也就是数据在存储到文件中的时候是以追加方式拼接到文件末尾的&#xff0c;这…

Embedding模型部署及效果评测

最近大模型发展迅速&#xff0c;与之对应的向量化需求也被带动起来了&#xff0c;由此社区也衍生出很多模型&#xff0c;本文选几款&#xff0c;简单做下评测。 前置概念 为方便读者&#xff0c;先简单介绍几个概念。 概念1&#xff1a;Vector Embedding 也即向量化嵌入&am…