将std :: chrono :: time_point转换为unix时间戳

Dan*_*iel 28 c++ unix-timestamp c++11 c++-chrono

std::chrono::duration自固定日期起如何获得?我需要这个来转换std::chrono::time_point为unix时间戳.

将代码插入XXX

auto unix_epoch_start = XXX;
auto time = std::chrono::system_clock::now();
auto delta = time - unix_epoc_start;
auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(delta).count();
Run Code Online (Sandbox Code Playgroud)

我知道time_point有一种方法,time_since_epoch()但不能保证这与unix时代(1970年1月1日00:00:00 UTC)相同.

bam*_*s53 32

unix时间戳定义为1970年1月1日UTC以来的秒数,但不计算所有秒数.这有点荒谬,我不得不怀疑它的意义,所以我同意这是一个愚蠢的问题.

无论如何,让我们看看一些平台文档time_ttime().

Linux:

time()返回自Epoch,1970-01-01 00:00:00 +0000(UTC)以来的秒数.

POSIX.1使用近似于指定时间和纪元之间的秒数的公式定义自纪元以来的秒数.这个公式考虑了这样的事实:所有可被4整除的年份都是闰年,但是可以被100整除的年份不是闰年,除非它们也可以被400整除,在这种情况下它们是闰年.由于闰秒并且系统时钟不需要与标准参考同步,因此该值与时间和Epoch之间的实际秒数不同.目的是自大纪元价值观以来对秒的解释是一致的; 有关进一步的理由,请参阅POSIX.1-2008理由A.4.15.

Windows:

time函数根据系统时钟返回自1970年1月1日午夜(00:00:00),协调世界时(UTC)以来经过的秒数.

Mac OS X:

函数ctime(),gmtime()和localtime()都将一个时间值作为参数,该时间值表示自Epoch(1970年1月1日00:00:00 UTC)以来的秒数.

asctime(),ctime(),difftime(),gmtime(),localtime()和mktime()函数符合ISO/IEC 9899:1990(ISO C90''), and conform to ISO/IEC 9945-1:1996 (POSIX.1''),前提是所选的本地时区不包含闰秒表(见zic(8)).

可以在其他系统中找到类似的文档,例如AIX,HP-UX,Solaris等.

因此,虽然没有在C++中指定,但是有一种简单且可广泛移植的方式来获取Unix时间戳:

auto unix_timestamp = std::chrono::seconds(std::time(NULL));
Run Code Online (Sandbox Code Playgroud)

如果你想要自1970年1月1日UTC以来的数毫秒(同样不计算所有这些),那么你可以这样做:

int unix_timestamp_x_1000 = std::chrono::milliseconds(unix_timestamp).count();
Run Code Online (Sandbox Code Playgroud)

请记住,这些值不是实际值,因此您通常不能在算术中使用unix时间戳.例如,减去unix时间戳并不能准确计算时间之间的秒数.或者如果你做了类似的事情:

std::chrono::steady_clock::now() - unix_timestamp;
Run Code Online (Sandbox Code Playgroud)

你不会得到实际对应于1970-01-01 00:00:00 + 0000的时间点.


正如Andy Prowl建议你可以做一些愚蠢的事情:

// 1 Jan 1970 (no time zone)
std::tm c = { 0, 0, 0, 1, 0, 70, 0, 0, -1};

// treat it as 1 Jan 1970 (your system's time zone) and get the
// number of seconds since your system's epoch (leap seconds may
// or may not be included)
std::time_t l = std::mktime(&c);

// get a calender time for that time_point in UTC. When interpreted
// as UTC this represents the same calendar date and time as the
// original, but if we change the timezone to the system TZ then it
// represents a time offset from the original calendar time by as
// much as UTC differs from the local timezone.
std::tm m = *std::gmtime(&l);

// Treat the new calendar time as offset time in the local TZ. Get
// the number of seconds since the system epoch (again, leap seconds
// may or may not be counted).
std::time_t n = std::mktime(&m);

l -= (n-l); // subtract the difference
Run Code Online (Sandbox Code Playgroud)

l现在应该代表1970年1月1日UTC以来的(错误)秒数.只要系统时期和1970年1月1日(系统时区)之间没有闰秒,或者在系统时期的另一个方向上的相同时间内,那么任何计算的闰秒都应该取消并且l将是错误的就像unix时间戳错误一样.


另一种选择是使用像Howard Hinnantchrono::date这样的体面日期库.(Howard Hinnant是参与C++ 11 <chrono>库的人之一.)

auto now = system_clock::now();
sys_days today = time_point_cast<days>(now);
system_clock::time_point this_morning = today;

sys_days unix_epoch = day(1)/jan/1970;
days days_since_epoch = today - unix_epoch;

auto s = now - this_morning;

auto tz_offset = hours(0);
int unix_timestamp = (days_since_epoch + s + tz_offset) / seconds(1);
Run Code Online (Sandbox Code Playgroud)

如果你想处理闰秒,Howard Hinnant还提供了一个库,其中包括处理它们的工具以及解析时区数据库作为闰秒数据的来源.

  • 它看起来并不像Howard Hinnant的日期类是专门提出的,但似乎委员会正在考虑标准化某种日期格式.见[link](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3344.pdf). (2认同)

Shi*_*hah 7

简而言之,这是我用来获取Unix时间戳的函数(自UTC时间1970年1月1日起的秒数):

static uint64_t getUnixTimeStamp(const std::time_t* t = nullptr)
{
    //if specific time is not passed then get current time
    std::time_t st = t == nullptr ? std::time(nullptr) : *t;
    auto secs = static_cast<std::chrono::seconds>(st).count();
    return static_cast<uint64_t>(secs);
}
Run Code Online (Sandbox Code Playgroud)

此功能的优点是默认参数值只为您提供当前时间.但是,如果您想将某个特定时间转换为unix时间戳,那么也可以将其转换为unix时间戳.


小智 5

这个C ++ 11实现如何

auto microsecondsUTC = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
Run Code Online (Sandbox Code Playgroud)

  • 优秀的解决方案 - 我喜欢将其除以 1000000.0 以获得双精度秒数。据我估计,在 2112 年 9 月 17 日之前,在双精度尾数中给出 2^52 位精度,这将具有微秒分辨率。 (2认同)