找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

地球时间和 C++ 时间库

admin 2019-9-9 09:05 100人围观 C++相关

基本知识

GMT (Greenwich Mean Time)


GMT 是一个 时区,也指一种 时制。很久以前,科学家通过天文观察,将一个太阳日定义为 86400 秒,以英国 Greenwich 天文台白天平均太阳最高点作为正午 12:00,这样一个相对长度 + 一个绝对时刻,就定义了一套绝对时间体系,也就是 GMT 体系,同时 Greenwich 所在的时区也作为 GMT+0 时区。自1924年2月5日开始,Greenwich 天文台负责每隔一小时向全世界发放调时信息。再后来又从 GMT 升级到了 UT1,本质不变,还是基于天体测量。

UTC (Coordinated Universal Time)


UTC 时间体系是基于 铯(caesium)-133 原子钟。原子从某高能阶跃迁到某低能阶时,会释放频率非常稳定的电磁波,例如 铯-133 原子在基态的两个超精细能级之间跃迁时,会释放频率为 9192631770 Hz 的电磁波,即该电磁波 1 秒中有 9192631770 个周期。那么反过来,可定义该电磁波经过 9192631770 个周期所用的时间为 1 秒。然后以某个 GMT 时间为起点,每计数该电磁波的 9192631770 个周期为 1 秒,这种时间体系就是 UTC 时间体系。

Leap Second (闰秒)


据上,可知 UTC 刚引入的时候和 GMT 时间是同步的。但是地球的自转并不是匀速不变的(地震,地壳运动等),且整体趋势呈缓慢减速(Tidal Acceleration 效应),而原子钟计量的时间是匀速增加的。为了使 UTC 时间和 GMT 时间误差不超过 0.9 秒,需要每隔一段时间(半年或一年或多年)把 UTC 时间减去 1 秒(不减这 1 秒的话,累计起来,过两万年,UTC 的表已经中午 12 点了,太阳才刚升起来,UT1 的表是早上 6 点)。被减去的这 1 秒叫做 Leap Second (闰秒)。有了闰秒,UTC 才和 earth rotation 保持同步。

Timezone (时区)

时区这个概念人尽皆知,无需多言。
大概在本初子午线(Prime Meridian)左右 7.5 度范围内为 0 时区,UK 和 Greenwich 位于这个时区内,即 GMT+0 时区。

这个时区在 UTC 中被称为 Zulu Timezone,简记 Z。


GPS (Global Positioning System)


GPS 时间也基于原子钟,但它没有 Leap second,不和地球自转保持同步。GPS 时间 是相对于 UTC 时间的某一时刻开始计时的,该时刻称为 GPS 时间的 epoch (UTC时间1980年1月6日00:00:00)。GPS 时间和 UTC 时间的每一秒开始时间被同步在 25ns 的误差内(消除相对论误差和设备误差等)。到现在(20190830)为止,GPS 时间已经超前 UTC 时间 18 秒。意味着从 1980年1月6日 到今日,UTC 已经调整过 18 个闰秒。

TAI (International Atomic Time) 时间也是基于原子钟计时,也没有 Leap Second。TAI 时间的 Epoch 是 1958/01/01 00:00:00 UTC+0。从该 Epoch 开始截止今天(2019/09/05), UTC 已经调整过 37 个闰秒,因此 TAI 现在超前 UTC 37 秒。

Daylight Saving Time (夏令时)


为了充分利用白天时间,某些地区实行夏令时。以美国为例:

  • 每年3月的第二个周日凌晨2点,时钟从2点拨到3点,时制记为 PST (Pacific Standard Time)。

  • 每年11月的第一个周日凌晨2点,时钟从2点拨到1点,时制记为 PDT (Pacific Daylight Time)。

  • 例如 2019-03-10 01:59:59 PST 的下一秒是 2019-03-10 03:00:00 PDT

ISO Time Format


ISO 8601 规定的时间格式:(由 date 和 time 两部分组成)

  • simple format:

    • 20090106 130101.123456789

    • 20090106T130101,123456789Z

    • 小数点后面的是纳秒。Z表示 Zulu 时区

  • extended format:

    • 2009-01-06 13:01:01.123456789

    • 2009-01-06T13:01:01,123456789+08

    • 结尾+08表示东八区

  • truncated form:

    • 090106

    • 09-01-06

  • 时区标志:

    • Z is the zone designator for the zero UTC offset, ie. Zulu time zone

    • 其他时区用±[hh][:][mm]来表示,例如+08:00, +0800, or simply +08 (省略分钟)

  • Week表示法:2009-W01(第一周)-1(Monday)

    • 并且,ISO 第一周 W01被定义为:该周至少有四天是在该年中。

Posix Time


  • Posix Time(Unix Time/Unix TimeStamp等),指从1970-01-01 00:00:00 UTC(这个时刻称为 Posix Time Epoch) 开始所经过的秒数(减去闰秒,和UTC时间基本一致)。根据表示的精确度的不同,Unix时间戳有秒级(time_t)、毫秒级(timeval)、纳秒级(timespec)等。

  • Unix和UTC不完全一致,UTC规范的闰秒表示为 2016-12-31 23:59:60 UTC,而 Unix time 会重复两个 23:59:59 时刻。并且,两个 UTC 时刻之差的时间会计入闰秒,而两个 Posix time 之间的时间差是不考虑闰秒的。

  • 老版本 Linux 是以 32bit signed int 存储 unix time 的,因此最多支持到 2038-01-19 03:14:07 UTC,下一秒变成 1901-12-13 20:45:52 UTC。因此也称为 Year 2038 problem。因此老版本请尽快升级。

  • 新版本 Linux 中日期和时间一般用 struct timespec 表示,它包含两个成员:tv_sec(从1970年开始的秒数,整数) 和 tv_nsec(纳秒部分)

编程接口

1. 汇编级别的计时


举一个例子:Intel CPU 指令 rdtsc (read Time Stamp Counter):

  • It counts the number of CPU cycles since reset(last reboot)。换言之 rdtsc 的 epoch 一般是最近一次开机时间

  • 跨平台性差

  • 不同核不一定值相同;如果一个 thread 被 migrate 到不同核,计数可能发生倒退。

  • 有人说由于CPU指令乱序,该指令的执行可能发生在前面的指令之前,因此计时不准确

  • 也有人说 rdtsc 计时器的时钟可能会不稳定(CPU clock)

    • 实测(CentOS7.2 x64,该服务器已开机运行接近两年):

    • 用 std::chrono::steady_clock 测得的经过时间为 1年12个月08天 15:54:26

    • 用 rdtsc + /proc/cpuinfo 中显示的 CPU 频率来计算:1年12个月08天 16:16:31

    • 用 rdtsc + 实时测量的 CPU HZ 来计算:1年12个月08天 15:57:25

2. linux 系统函数

/usr/include/time.h
/usr/include/linux/time.h
/usr/include/sys/time.h
/usr/include/bits/time.h

  • struct timeval

    structtimeval {
    time_t tv_sec;
    suseconds_t tv_usec;
    }

  • int gettimeofday(timeval* tv, timezone*)

    • 这是一个 Linux syscall

    • 返回自 Posix Time Epoch 的 seconds + microseconds

    • tz is obsolete and should normally be specified as NULL

    • 返回值:0 表示正常

  • struct timespec

    structtimezone {
    int tz_minuteswest;
    int tz_dsttime; /* type of dst correction */
    }

  • int clock_gettime(clockid clk_id, timespec*)

    • 这是用一个 Linux syscall

    • 返回指定 clock_id 下,"now" 距离其 epoch 的时间 (seconds + nanoseconds)。clk_id 取值:

    • CLOCK_REALTIME:返回距离 Posix time epoch 的时间。实测(CentOS7.2 x64) chrono::system_clock::now() 调用了它

    • CLOCK_MONOTONIC:返回距离最近一次开机的时间。不计入系统 suspend 时间。实测(CentOS7.2 x64) chrono::steady_clock::now() 调用了它

    • 返回值:0 表示正常

3. ctime

#include <ctime>
  • std::clock_t

    • 相关函数:clock_t clock() 返回本进程启动的时间。

    • 进程 sleep 时该 clock 暂停计时。

  • std::time_t

    • 精确到秒。

    • it is an integral value representing the number of seconds elapsed since 1970-01-01 00:00:00 UTC.

  • std::time_t time(std::time_t* tloc) "posix"

    • returns the time as the number of seconds since the Posix Time Epoch 1970-01-01 00:00:00 +0000 (UTC)

  • std::tm* localtime(std::time_t*) "local"

    • 根据 local timezone,把标量时间转换成一个 tm*

  • std::tm* gmtime(std::time_t*) "posix"

    • timezone 用 GMT+0(也就是UTC+0),把标量时间转换成一个 tm*

  • char* ctime(std::time_t*) "local" 【整段加灰】

    • 基于 local timezone,把标量时间转换成时间字符串

    • ctime(t) 相当于 asctime(localtime(t))

  • std::tm
struct tm {
int tm_sec; /* Seconds (0-60) */
int tm_min; /* Minutes (0-59) */
int tm_hour; /* Hours (0-23) */
int tm_mday; /* Day of the month (1-31) */ "只有mday是从1开始"
int tm_mon; /* Month (0-11) */ "呵呵"
int tm_year; /* Year - 1900 */ "years since 1900, 例如100表示2000年"
int tm_wday; /* Day of the week (0-6, Sunday = 0) */
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
int tm_isdst; /* Daylight saving time */ "0 表示 no Daylight Saving Time"
};

  • std::time_t std::mktime(std::tm*) "local"

    • tm* 是 localtime 时间点。转换结果是 posix timestamp。转换过程加上了 local time zone offset

  • char* std::asctime(std::tm*)

    • 把 tm* 转化成一个字符串时间

  • size_t std::strftime(buf, len, format, std::tm*)

    • 根据 format 把 tm* 转换成一个 char*

  • std::put_time(tm*, format)

    • cout << std::put_time(std::localtime(&now), "%F %T");

  • std 不支持 Linux strptime (char*tm*),用 std::get_time 代替。

4. std::chrono

#include <chrono>
  • std::ratio 在 chrono 库中表示秒、分、时等单位

  • std::nano 即 std::ratio<1,1000000000>,在 chrono 中表示纳秒单位

  • std::micro 即 std::ratio<1,1000000>,在 chrono 中表示微秒单位

  • std::milli 即 std::ratio<1,1000>,在 chrono 中表示毫秒单位

  • 模板二参默认是1,ratio<60> 即 ratio<60, 1>,在 chrono 中表示1分钟

  • chrono::days (C++20) 相当于 duration<int, ratio<86400>>;

  • chrono::hours 相当于 duration<int, ratio<3600>>;

  • chrono::minutes 相当于 duration<int, ratio<60>>;

  • chrono::seconds 相当于 duration<long, ratio<1>>

  • chrono::milliseconds 相当于 duration<long, std::milli>;

  • chrono::microseconds 相当于 duration<long, std::micro>;

  • chrono::nanoseconds 相当于 duration<long, std::nano>;

chrono literals (C++14起支持)


  • using namespace std::chrono_literals;

  • 感受一下这种方便的语法:

  • auto x = 1h; 相当于 auto x = chrono::hours(1);

  • auto x = 1min; 相当于 auto x = chrono::minutes(1);

  • auto x = 1s; 相当于 auto x = chrono::seconds(1);

  • auto x = 1ms; 相当于 auto x = chrono::milliseconds(1);

  • auto x = 1us; 相当于 auto x = chrono::microseconds(1);

  • auto x = 1ns; 相当于 auto x = chrono::nanoseconds(1);

duration


duration 代表时间的长度,例如 duration(1) 表示 1 秒。

  • duration 是一个模板类,支持 integer 或 float 类型的时间长度,需要明确指定该类型,即 duration<int>(1) 表示 1 秒,或者 duration<double>(1.2) 表示 1.2 秒。

  • duration 还能代表 分钟,需要指定模板的第二个参数:duration<int, ratio<60>>(1) 表示 1 分钟。其中 ratio<60> 表示时间单位是 60 秒,也就是 1 分钟。

  • duration::rep:即模板一参,是时间长度的类型 (例如 int, long, double 等,未提供默认类型)。要求是有符号数,从而可以表示 epoch 前的数。

  • duration::period:即模板二参,是时间的单位,默认是 std::ratio<1>,表示单位是秒。

  • count() 返回 period 的个数,返回值类型为 rep,如果 rep 是 double,则 count() 返回小数

  • duration_cast
    (duration1) 从一种duration1转换为另一种duration2:

    • auto x = duration_cast<seconds>(2800ms); 得到 2s。损失精度,需明确做 duration_cast

    • auto x = duration_cast<seconds>(-2800ms); 得到 -2s。"duration_cast" round towards 0

time_point


A time_point object expresses a point in time relative to a clock's epoch. Typical epochs include 1970-01-01 00:00:00(for system_clock) and the instant when the computer booted up(for steady_clock).

  • time_point::clock:时刻对应的时钟。可以是 system_clock, steady_clock, high_resolution_clock。不同的 Clock 即不同的 epoch。

  • time_point::duration:指定计时的单位(period)和类型(rep),一般是 秒(ratio<1>) 和 integer(long)。

  • time_since_epoch():

    • 返回该 time_point对象 距离其 epoch 的时间长度,类型是 duration。

  • time_point_cast
    (duration1) 从一种duration1转换为另一种duration2:

    • time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch()))

  • 重载了运算符 +, -, ++, --, >, <, == 等来方便 time_point 和 duration 的自然语义运算

    • 只有两个 time_point 的 Clock 相同,才可以做差来求得 duration。

system_clock


system_clock measures Posix Time (i.e., time since UTC 1970-01-01 00:00:00, not counting leap seconds).

  • system_clock::duration:system_clock keeps track of the time elapsed since its epoch,duration 给出了 elapsed time 的计数单位(period)和计数数值类型(rep)。

  • system_clock::period:即 duration::period

    • 规范竟然说默认是 seconds,但实测:Windows x64是ratio<1, 10'000'000>,即100ns;CentOS7.2 x64 是ratio<1, 1000'000'000>,即 nanoseconds。

  • system_clock::rep:即 duration::rep

    • 规范没说默认是什么类型,在实测(in both Windows7 x64 and CentOS7.2 x64)是 int64_t

  • system_clock::time_point:即 time_point<system_clock>,简洁记法。

  • now():Get current time, 返回值类型为 system_clock::time_point

  • to_time_t():Convert from time_point to std::time_t

  • from_time_t():Convert from std::time_t to time_point

  • 从 C++20 开始支持 cout << time_point,易于调试

  • 结合 <thread>:std::this_thread::sleep_for(std::chrono::duration)

  • 结合 <thread>:std::this_thread::sleep_until(std::chrono::time_point)

steady_clock


Class std::chrono::steady_clock represents a monotonic(单调递增) clock. The time points of this clock cannot decrease as physical time moves forward and the time between ticks of this clock is constant. This clock is not related to wall clock time (for example, it can be time since last reboot), and is most suitable for measuring intervals.

  • steady_clock::duration:steady_clock 一般实现为 记录距离最近一次开机经过的时间(duration),或者说 steady_clock 的 epoch 是最近一次开机的时刻。duration 给出了 elapsed time 的计数单位(period)和计数数值类型(rep)。

  • steady_clock::period:即 duration::period

    • 规范竟然说默认是 seconds,但实测:Windows x64 和 CentOS7.2 都是ratio<1,1000'000'000>,即 nanoseconds。

  • steady_clock::rep:即 duration::rep

    • 规范没说默认是什么类型,在实测(in both Windows7 x64 and CentOS7.2 x64)是 int64_t

  • is_steady(): always true。注意 system_clock 一定不是 steady 的:because the "system clock" can be adjusted. Such an adjustment may cause a call to now() to return a value earlier than that returned by a prior call to now(). 因此 system_clock 不适合用于非常严格地 measure time interval。

high_resolution_clock


high_resolution_clock is the clock with the shortest tick period. It may be a synonym for system_clock or steady_clock. 即二者谁的精度高就选谁,实测:

  • Windows 7 x64:high_resolution_clock = steady_clock

  • Linux CentOS 7.2 x64:high_resolution_clock = system_clock

5. Boost DateTime

#include <boost/date_time.hpp>

Boost date_time 库主要由3个部分组成:

  • boost::gregorian 表示年月日

  • boost::posix_time 结合 gregorian::date,表示年月日时分秒

  • boost::local_time 结合在 posix_time 基础上加上时区,可以表示任意 UTC 时间

  • 格式化输入/输出:boost::locale, facet, cin.imbue

boost::gregorian


今年是2019年,是指公历(或称为阳历,新历,西历,基督历),也称为 Gregorian Calendar(格里历)。其 epoch 也就是 公元元年,也就是 1 AD。(往前一年是 1 BC)

using namespace boost::gregorian;

  • gregorian::date d{2014, 1, 23};

    • 踩坑:d.day_number() 返回的不是自从 公元元年1月1日 的天数,而是距离 公元前4713年1月1日(上下五千年?) 的天数,也就是说 boost::gregorian::date 的 epoch 是 公元前4713年1月1日,而且这个时间点是 Julian Calendar(儒略历) 的 epoch。而且 year 的有效取值范围是 1400 到 10000。(所以这个 date 是不是应该叫做 julian::date 更合理一点?)

  • date day_clock::local_day() -> 获得 posix now 并转成 local date

  • date day_clock::universal_day() -> 获得 posix now 并转成 unix date

  • gregorian::date_duration dd{4}; 等同于 days dd{4};

    • typedef date_duration days;

    • date1 - date2 得到 date_duration

boost::posix_time


using namespace boost::posix_time;

  • time_duration td{12, 0, 0} a time_duration object of 12:00:00

    • 另外也有 hours{h}, minutes{m}, seconds{s}, nanoseconds{ns} 都是 time_duration。

    • td 的成员有 td.hours(), minutes(), seconds(), total_seconds(), fractional_seconds()

  • ptime{date, time_duration}

    • ptime 由 date + time_duration 组成。

    • ptime.date() 返回其中的 date object

    • ptime.time_of_day() 返回其中的 time_duration object

  • ptime second_clock::local_time() -> 获得 posix now 并转成 local date + local time_duration

  • ptime second_clock::universal_time() -> 获得 posix now 并转成 utc date + utc time_duration

boost::local_time


using namespace boost::local_time;

  • time_zone_ptr tz{new posix_time_zone{"GMT+8"}}; 表示时区

    • time_zone_ptr 是一个 shared_ptr

  • local_date_time dt{ptime, tz}

    • ptime 代表一个 utc 时刻结构

    • 其实跟"local"无关!可能称为"zoned_ptime"更合适点,即一个 utc time + 一个 timezone

举例


  • 从 second_clock::universal_time() 得到总秒数
办法1. ptime -> tm -> time_t
auto now = second_clock::local_time();
auto _tm = to_tm(now);
auto _time_t = mktime(&_tm);
办法2. ptime -> time_duration -> total_seconds()
(second_clock::universal_time() - ptime{{1970,1,1},{0,0,0}}).total_seconds()

  • 得到 Linux 文件的时间 timespec (精确到纳秒),转化成 ptime
lstat("file", &sb);
ptime t{date{1970,1,1}, seconds{sb.st_mtim.tv_sec} + nanoseconds{sb.st_mtim.tv_nsec}};

  • 和<ctime>相互转换的函数:
tm to_tm(date/ptime/time_duration/local_date_time)
date date_from_tm(tm);
ptime ptime_from_tm(tm)
ptime from_time_t(time_t)
std的tm和time_t都不能指定具体时区,因此无法转local_date_time
Linux的tm有扩展成员:.tm_gmtoff = +28800秒, .tm_zone = "HKT"

  • local_date_time 用法:
ptime pt{date{2002,01,20}, time_duration{12,0,0}};
// os<<put_time/strftime %Z%z 在 Linux 得到 "CST+0800"
// os<<put_time/strftime %Z%z 在 Windows 得到 "China Standard Time+0800"
strftime(tz_str, 256, "%z", &_tm); tz_str[strlen(tz_str)-2]='\0';
time_zone_ptr tz{new posix_time_zone{tz_str}};
local_date_time dt{pt, tz};
// boost/date_time 不支持 current_zone

6. C++20 date (HowardHinnant/date)

// github HowardHinnant/date
#include <date/date.h>
#include <date/tz.h>
using namespace date;

date 和 time 支持


  • date 级别:year_month_day 是年月日 field type class,是结构体,记录 3 个数(年/月/日);

  • time 级别:time_of_day 时分秒 field type class。同时记录了 mode (默认0代表24时制)

  • sys_time 是 serial-based type,是一个标量,记录从 epoch 开始的(纳?)秒数。

year_month_day


  • 简单款:auto ymd = 2019_y/sep/1;

  • 2019_y/mar/sun[2] 表示 March 的第二个 Sunday

  • 复杂款:year_month_day ymd{year(2019), month(9), day(1)};

sys_time


就是 system_clock 中的某个 time_point,简称 sys_time

  • sys_time<D>等价于 time_point<system_clock, D>

    • 在 date 级别,sys_days 即 sys_time


    • 在 time 级别,sys_seconds 即 sys_time

  • year_month_day 可以自动转换成 sys_days:

  • sys_days x = 1970_y/jan/1;

  • 转换成 time_point 后可以参与 time_point 的时间运算 (例如+,-,>,<等)

  • floor<D>(参数是 duration 或者 time_point); 类似 duration_cast/time_point_cast<D>(xxx),只是后者的舍入方向是 towards epoch 的;而 floor 是 towards 负无穷的。

  • C++20 开始,system_clock 被明确定义为 Posix time clock,不论在 Linux 还是 Windows。在C++20之前有些混乱,Windows曾尝试定义 system_clock 的 epoch 为 1601-01-01 00:00:00

时区支持


  时区支持须结合 IANA 发布的时区数据库 tzdata.tar.gz 协同工作。

time_zone


  • timezone tz = locate_zone("America/Los_Angeles");

  • UTC+0 zone 可以用 locate_zone("UTC") 或 locate_zone("Etc/UTC") 表示。

  • auto tz = current_zone();

local_time


local_time 比较特殊,虽然它是一个 time_point,但未指定 clock,不包含时区信息

  • local_days 即 local_time<days>,即 Duration = days

zoned_time


zoned_time = local_time + timezone 结构体。

  • make_zoned 构造一个 zoned_time。

  • 例如系统是HK时区,下面两个 zoned_time 相等:

  • make_zoned("Asia/Hong_Kong", local_days{2019_y/sep/1} + 16h);

  • make_zoned(current_zone(), sys_days{2019_y/sep/1} + 8h);

  • 这是因为当地时间 16:00 HKT 相当于 posix time 8:00 UTC

Leap Second 支持


  在上述所有的 lib 中,只有这个 lib 支持 leap second。

由于 Leap Second 的存在,从 posix time 2015/07/01 23:59:59 到 2015/07/02 00:00:00 对应物理世界的 2 秒钟。

  • 对于 posix clocks(sys_clock),23:59:59 这一个时间被数了两次。

  • 对于 utc clocks(utc_clock),时间经过了 23:59:59 -> 23:59:60 -> 00:00:00 三个时刻。

  • posix time_point 的计时标量只增加了 1

  • utc time_point 的计时标量增加了 2

utc_time


utc_time是 Clock = utc_clock 的 time_point,即 time_point<utc_clock, D>,其中 D 可以是任意 std::duration Type
auto t0 = to_utc_time(sys_days{2015_y/jul/1) - 200ms);
auto t1 = to_utc_time(sys_days{2015_y/jul/1) + 200ms);
可验证:t1 - t0 == 1400ms;

  • utc_time 适用于严格计时场合

  • leap second 信息来源于 IANA 的数据库。一般 leap second 会在实施前半年公布,按理 IANA 会在更新的数据库中预先增加此信息,从而在程序运行过程中,可以实时检测出发生了闰秒事件,从而准确的计时。

其他 clock


本 Lib 还支持 tai_clock, gps_clock

可以用 to_gps_time(某 time_point) 进行转换。

Formatting


  • "%F %T" 其中 %F=%Y-%m-%d(2014-01-23),%T=%H:%M:%S(14:55:02)

  • "%Y%m%d %H%M%S"

  • "%z" 得到时区offset字符串 "+0800"

  • "%Z" 得到时区abbrv字符串 "HKT"

  • 下面记 TIME = local_time/zoned_time/sys_time

  • cout << TIME

  • cout << format(fmtstr, TIME);

  • cout << format(locale, fmtstr, time)

  • istringstream("1970-01-01 05:00:00 GMT +08") >> parse("%F %T %Z %z", TIME, zone_str, tz_offset);

存在的问题


  • Linux 需要存在目录 ~/Downloads,最好预先解压 tzdata2019b.tar.gz 到 ~/Downloads/tzdata

  • Windows 需要存在目录 %USERPROFILE%/Downloads,且解压 tzdata2019b.tar.gz 到 %USERPROFILE%/Downloads/tzdata,并且下载 windowsZones.xml 到 %USERPROFILE%/Downloads/tzdata。

  • 目前没有 utc_days 定义,utc_time
    似乎不支持从 ymd 构造

  • istringstream("1999-01-01 05:00:00 +0800") >> parse("%F %T %z", ltp, offset) 支持有问题

  • istringstream("05:00:00 +0800") >> parse("%T %z", ltp) 支持有问题

  • istringstream("05:00:00") >> parse("%T", chrono::seconds) 支持有问题

  • zoned_time.get_sys_time(); VS2015无法编译

  • cout << sys_time; VS2015无法编译

  • locate_zone(string) 不支持 "GMT+8" 或者 "UTC+8" 或者 "CST" 这种标识。北京时间只能用 locate_zone("Asia/Shanghai") 这种冗长的形式表示。

  • 这个库还比较新,会有一些问题。欢迎去其github页面(howardhinnant date)提 bug。

Summary


建议使用 std::chrono + HowardHinnant/date,其内在逻辑通顺,语义比较自然。

References


Standing on the shoulders of giants:

  • Jeff Garland: author of boost::chrono, boost::date_time

  • Howard Hinnant: https://howardhinnant.github.io/

Acknowledgements


  • 感谢白博士在GPS时间章节的补充

----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:Toddler的笔记,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

yafeilinux和他的朋友们微信公众号二维码

微信公众号

专注于Qt嵌入式Linux开发等。扫一扫立即关注。

Qt开源社区官方QQ群二维码

QQ交流群

欢迎加入QQ群大家庭,一起讨论学习!

我有话说......