将std :: chrono :: time_point转换为unix时间戳 [英] Convert std::chrono::time_point to unix timestamp

查看:2341
本文介绍了将std :: chrono :: time_point转换为unix时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自定义日期后,如何获得 std :: chrono :: duration ?我需要这个将 std :: chrono :: time_point 转换为unix时间戳。



将代码插入XXX

  auto unix_epoch_start = 
auto time = std :: chrono :: system_clock :: now();
auto delta = time - unix_epoc_start;
auto timestamp = std :: chrono :: duration_cast< std :: chrono :: milliseconds>(delta).count();

我知道 time_point c $ c> time_since_epoch()但不能保证这与unix纪元(1970年1月1日00:00:00 UTC)相同。



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



Linux


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



POSIX。 1使用近似于指定时间和时元之间的秒数的公式定义自纪元以来的秒。这个公式考虑到所有年份可以被4整除的年份是闰年,但是可以被100均分的年份不是闰年,除非他们也可以被400均分,在这种情况下他们是闰年。此值与时间和Epoch之间的实际秒数不同,因为闰秒和系统时钟不需要与标准参考同步。意图是对秒的解释自从Epoch值是一致的;有关进一步的理由,请参见POSIX.1-2008理论A.4.15。


Windows


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


< blockquote>

Mac OS X


函数ctime(),gmtime()和localtime取作为参数
a表示自纪元以来以秒为单位的时间的时间值(1970年1月1日的UTC时间00:00:00
;




函数符合ISO / IEC 9899:1990( ISO C90'')asctime(),ctime(),difftime(),gmtime(),localtime()和mktime ,并且符合
ISO / IEC 9945-1:1996(
POSIX.1),只要所选的本地时区
不包含闰秒表(参见zic (8))。


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

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

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

如果你想要从1970年1月1日UTC以来的几毫秒(同样不包括所有)那么你可以这样做:

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

请记住,这些值不是实际时间,因此一般不能使用unix时间戳算术。例如,减去unix时间戳不会提供时间之间的精确秒数。或者,如果你做了类似的操作:

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

你不会得到一个实际对应于1970-01-01 00:00:00+ 0000。






由于Andy Prowl建议您可以做一些愚蠢的事情:

  // 1970年1月1日(无时区)
std :: tm c = {0,0,0,1,0,70,0, -1};

//将其视为1970年1月1日(系统时区),并获得
//自系统时代起的秒数(闰秒可能为
//或不包括)
std :: time_t l = std :: mktime(& c);

//获取time_point的UTC时间。当将
//解释为UTC时,这表示与
//原语相同的日历日期和时间,但是如果我们将时区更改为系统TZ,则
//表示时间偏移从原来的日历时间by
//很像UTC与本地时区不同。
std :: tm m = * std :: gmtime(& l);

//将新日历时间视为本地TZ中的偏移时间。获取
//从系统时代起的秒数(再次,闰秒
//可能会被计数或可能不被计数)。
std :: time_t n = std :: mktime(& m);

l - =(n-l); // subtract the difference

l 表示自1970年1月1日UTC以来的(错误)秒数。只要在系统历元和1970年1月1日(系统时区)之间没有闰秒,或者在从系统历元开始的另一个方向上的等量时间内,则任何计数的闰秒都应该取消,并且<$ c






$ c> l

另一种选择是使用体面的日期库,例如 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 =今天 - unix_epoch;

auto s = now - this_morning;

auto tz_offset = hours(0);
int unix_timestamp =(days_since_epoch + s + tz_offset)/ seconds(1);

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


How can I get an std::chrono::duration since a fixed date? I need this to convert a std::chrono::time_point to an unix timestamp.

Insert code into 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_point has 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).

解决方案

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.

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

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.

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.

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)).

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

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

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:

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:

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

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


As Andy Prowl suggests you could do something silly like:

// 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

l should 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 l will be wrong in just the way that unix timestamps are wrong.


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.)

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 library that includes facilities for handling them as well as for parsing time zone databases as the source for leap second data.

这篇关于将std :: chrono :: time_point转换为unix时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆