转换的std ::时辰:: time_point到UNIX时间戳(Convert std::chro

2019-07-18 16:23发布

我怎样才能得到一个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();

我知道time_point有一个方法time_since_epoch()但它不能保证,这是一样的Unix纪元(00:00:00 UTC 1970年1月1日)。

Answer 1:

自1970年1月1日UTC一个Unix时间戳被定义为的秒数,除了不计算所有秒。 这有点荒谬,人们想知道它的用意是什么,所以我认为这是一个愚蠢的问题。

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

Linux的 :

时间()返回时间的秒从epoch 1970-01-01 00:00:00 0000(UTC)的数量,。

POSIX.1使用近似的指定的时间和时元之间的秒数的公式限定,因为时代秒。 这个公式考虑的事实是能被4整除的所有年份是闰年,但年是整除由100不闰年,除非他们也被400整除,在这种情况下,他们是闰年。 此值是不相同的时间和时元之间的实际秒数,因为闰秒和由于不需要系统时钟同步到一个标准的参考。 其目的是,由于时代价值几秒钟的解释是一致的; 看到POSIX.1-2008原理A.4.15进一步的理由。

视窗 :

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

Mac OS X的 :

的功能的ctime(),gmtime的(),和本地时间()都以作为一个参数代表由于历元(00:00:00 UTC 1970年1月1以秒计的时间的时间值;

的asctime(),的ctime(),difftime(),gmtime的(),本地时间()和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));

如果你想自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。


安迪警车建议你可以做喜欢的事,傻:

// 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现在应该代表自1970年1月1日UTC秒的(错误的)数量。 只要有系统历元和1970年1月1日(系统时区)之间没有闰秒,或在从系统划时代另一个方向等量的时间内,那么任何计数闰秒应抵消和l将错在只知道unix时间戳是错误的方式。


另一种选择是使用一个体面的最新的图书馆,如霍华德Hinnant(欣南特)的chrono::date 。 (霍华德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);

如果你想处理闰秒霍华德Hinnant(欣南特)还提供了一个库 ,其中包括处理它们,以及用于分析时区数据库作为源闰秒的数据服务。



Answer 2:

长话短说,下面是我用得到Unix时间戳(自1970年1月1日UTC秒计)的函数:

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);
}

此功能的优点是,默认参数值只是给你当前时间。 但是,如果你想一些特定的时间转换为unix时间戳比你可以这样做很好。



Answer 3:

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

如果你需要一个UTC时间,然后使用gmttime()将其转换time_t值转换为UTC tm结构,并从你的输出,计算出tm结构得到所需的UTC time_t输入给予时mktime()

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



Answer 4:

你看这个C ++ 11的实现

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


文章来源: Convert std::chrono::time_point to unix timestamp