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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14504870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:23:32  来源:igfitidea点击:

Convert std::chrono::time_point to unix timestamp

c++c++11unix-timestampchrono

提问by Daniel

How can I get an std::chrono::durationsince a fixed date? I need this to convert a std::chrono::time_pointto an unix timestamp.

我怎样才能得到std::chrono::duration一个固定日期?我需要它来将 a 转换std::chrono::time_point为 unix 时间戳。

Insert code into XXX

将代码插入 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();

I know time_pointhas a method time_since_epoch()but it's not guaranteed that this is the same as the unix epoch (00:00:00 UTC on 1 January 1970).

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

回答by bames53

A unix time stamp is defined as the number of seconds since January 1, 1970 UTC, except not counting all the seconds. This is somewhat ridiculous and one has to wonder what the point of it is, so I agree that this is a silly question.

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

Anyway, lets look at some platform documentation for time_tand time().

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

Linux:

Linux

time() returns the time as the number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).

POSIX.1 defines seconds since the Epoch using a formula that approximates the number of seconds between a specified time and the Epoch. This formula takes account of the facts that all years that are evenly divisible by 4 are leap years, but years that are evenly divisible by 100 are not leap years unless they are also evenly divisible by 400, in which case they are leap years. This value is not the same as the actual number of seconds between the time and the Epoch, because of leap seconds and because system clocks are not required to be synchronized to a standard reference. The intention is that the interpretation of seconds since the Epoch values be consistent; see POSIX.1-2008 Rationale A.4.15 for further rationale.

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

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

Windows:

窗户

The time function returns the number of seconds elapsed since midnight (00:00:00), January 1, 1970, Coordinated Universal Time (UTC), according to the system clock.

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

Mac OS X:

Mac OS X

The functions ctime(), gmtime(), and localtime() all take as an argument a time value representing the time in seconds since the Epoch (00:00:00 UTC, January 1, 1970;

The asctime(), ctime(), difftime(), gmtime(), localtime(), and mktime() functions conform to ISO/IEC 9899:1990 (ISO C90''), and conform to ISO/IEC 9945-1:1996 (POSIX.1'') provided the selected local timezone does not contain a leap-second table (see zic(8)).

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

如果ISO C90''), and conform to ISO/IEC 9945-1:1996 (所选本地时区不包含闰秒表(参见 zic(8))。

Similar documentation can be found for other systems, such as AIX, HP-UX, Solaris, etc.

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

So although not specified in C++there is an easy and widely portable way to get a Unix timestamp:

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

auto unix_timestamp = std::chrono::seconds(std::time(NULL));

And if you want a number of milliseconds since 1 Jan 1970 UTC (similarly not counting all of them) then you can do this:

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

int unix_timestamp_x_1000 = std::chrono::milliseconds(unix_timestamp).count();

Just remember that these values aren't real times, so you can't in general use unix timestamps in arithmetic. For example subtracting unix timestamps does not give you an accurate count of seconds between the times. Or if you did something like:

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

std::chrono::steady_clock::now() - unix_timestamp;

you would not get a time point actually corresponding to 1970-01-01 00:00:00+0000.

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



As Andy Prowl suggests you could do something silly like:

正如 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

lshould now represent the (wrong) number of seconds since 1 Jan 1970 UTC. As long as there are no leap seconds between the system epoch and 1 Jan 1970 (system time zone), or within an equal amount of time in the other direction from the system epoch, then any counted leap seconds should cancel out and lwill be wrong in just the way that unix timestamps are wrong.

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



Another option is to use a decent date library such as Howard Hinnant's chrono::date. (Howard Hinnant was one of the guys that worked on the C++11 <chrono>library.)

另一种选择是使用一个不错的日期库,例如Howard Hinnant 的chrono::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);

If you want to handle leap seconds Howard Hinnant also provides a librarythat includes facilities for handling them as well as for parsing time zone databases as the source for leap second data.

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

回答by Shital Shah

Long story short, here is the function I use to get Unix timestamp (seconds count since Jan 1, 1970 UTC):

长话短说,这是我用来获取 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);
}

The advantage of this function is that the default parameter value just gives you current time. However if you wanted to convert some specific time to unix timestamp than you can do so as well.

这个函数的优点是默认参数值只是给你当前时间。但是,如果您想将某个特定时间转换为 unix 时间戳,那么您也可以这样做。

回答by siamoss

what about this C++11 implementation

这个 C++11 实现怎么样

auto microsecondsUTC = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();

回答by Andy Prowl

You could use mktime()to convert the desired date encoded in a tmstructure into a local-timetime_tvalue.

您可以使用mktime()将在tm结构中编码的所需日期转换为本地时间time_t值。

If you need a UTC time, then use gmttime()to convert that time_tvalue into a UTC tmstructure, and figure out from the output you get which tmstructure yields the desired UTC time_twhen given in input to mktime().

如果你需要一个UTC时间,然后使用gmttime()该转换time_t价值为UTCtm结构,并找出从输出你得到它tm的结构得到所需的UTCtime_t在输入给时mktime()

A bit elaborate, but hopefully it will work or at least provide a hint.

有点复杂,但希望它会起作用或至少提供一个提示。