纳秒和计时C ++

问题描述 投票:4回答:2
2018-10-01 00:06:16.700000000

我有一个带有上述时间戳记的时间序列数据文件。我需要将其从纪元转换为十亿分之一秒,然后我需要在时间戳(偏移)中添加毫,微或毫微秒。最后,对于选择记录,将其恢复为上面的格式。

我在创建时间点时遇到麻烦-以及如何表示纳秒...它可以与微米配合使用。

我能否请下面的代码片段提供帮助...,还有从纪元到十亿分之一秒的时间-我该如何回到上面的时间戳。

std::string ts("23 01 2020 20:59:59.123456789");

XXXX (ts);

void XXXXX (string timestamp)
{
     stringstream temp_ss(timestamp);

     tm temp_time_object = {};

     temp_ss >> get_time (&temp_time_object, "%Y/%m/%d %H:%M:%S");

     chrono::system_clock::time_point temp_time_point = system_clock::from_time_t(mktime(&temp_time_object));
    // chrono::high_resolution_clock::time_point temp_time_point1 = temp_time_point;

    auto  nsecs           =  stol (timestamp.substr (timestamp.find_first_of('.')+1,9));

// +++ This is where I GET stuck forming the time_point....
// I've tried this so many different ways .... 
// Is it that the system_clock cannot accept nanos? 


    temp_time_point += nanoseconds (nsecs);

     auto micro_from_epoch = duration_cast<nanoseconds> (temp_time_point.time_since_epoch()).count();

     cout << micro_from_epoch << endl;

}
c++ datetime chrono
2个回答
2
投票

我在创建时间点时遇到麻烦-以及如何表示纳秒...在微米上工作正常。

这告诉我,您的system_clock::time_point的精度比纳秒还要大(在llvm上是微秒,在Windows上是1/10微秒)。将纳秒添加到此类time_point的最简单方法是:

auto tp = temp_time_point + nanoseconds (nsecs);

这形成一个仍基于time_pointsystem_clock,但具有system_clock::durationnanoseconds的“通用类型”的精度,实际上,它们的精确度仅为nanoseconds

假定所有时间戳均为格林尼治标准时间,UTC + 0

现在问题是mktimelocal tm转换为UTC time_t。但是您想从UTC字段类型转换为UTC序列类型。

这在C ++ 20中很容易完成(我知道您还没有,请听我说:):

#include <chrono>
#include <iostream>
#include <sstream>

std::chrono::sys_time<std::chrono::nanoseconds>
XXXXX(std::string const& timestamp)
{
    using namespace std;
    using namespace std::chrono;
    istringstream temp_ss{timestamp};
    sys_time<nanoseconds> tp;
    temp_ss >> parse("%F %T", tp);
    return tp;
}

int
main()
{
    auto tp = XXXXX("2018-10-01 00:06:16.700000000");
    std::cout << tp.time_since_epoch().count() << "ns\n";
    std::string s = std::format("{:%F %T}", tp);
    std::cout << s << '\n';
}

[这将string转换为chrono::time_point<system_clock, nanoseconds>,这显然与system_clock::time_point不同,仅在于system_clock::time_point具有比nanoseconds更高的精度。

然后,format用于将time_point转换回string

输出:

1538352376700000000ns
2018-10-01 00:06:16.700000000

现在我知道,如今完全符合C ++ 20 <chrono>的情况已经很少见了(即将到来)。在到达此处之前,有一个C++20 <chrono> preview library与C ++ 11兼容。它是免费和开源的。并且需要很少的语法更改:

<chrono>

输出:

#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>

date::sys_time<std::chrono::nanoseconds>
XXXXX(std::string const& timestamp)
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;
    istringstream temp_ss{timestamp};
    sys_time<nanoseconds> tp;
    temp_ss >> parse("%F %T", tp);
    return tp;
}

int
main()
{
    using namespace date;
    auto tp = XXXXX("2018-10-01 00:06:16.700000000");
    std::cout << tp.time_since_epoch().count() << "ns\n";
    std::string s = format("%F %T", tp);
    std::cout << s << '\n';
}

1
投票

您的工作直接从文本转换为纳秒分辨率。本质上有两个密钥库:

  • [1538352376700000000ns 2018-10-01 00:06:16.700000000 由一些Google工程师提供,尽管(像许多项目一样)不是正式发行的Google产品

  • CCTZ作者:霍华德·辛南特(Howard Hinnant),他可能会在我完成打字之前在这里回答;他的库是C ++ 20中内容的基础]

我已经包装了R(通过Rcpp),并有很多示例。但是这两个存储库中也有示例,所以也许从那里开始?

因此,由于缺少更好的立即CCTZ示例,这里使用R包;您会看到输入:

date

调用的解析器函数是(并且忽略与R相关的位)

R> library(RcppCCTZ)
R> example(parseDatetime)

prsDttR> ds <- getOption("digits.secs")

prsDttR> options(digits.secs=6) # max value

prsDttR> parseDatetime("2016-12-07 10:11:12",        "%Y-%m-%d %H:%M:%S")   # full seconds
[1] "2016-12-07 10:11:12 UTC"

prsDttR> parseDatetime("2016-12-07 10:11:12.123456", "%Y-%m-%d %H:%M:%E*S") # fractional seconds
[1] "2016-12-07 10:11:12.123456 UTC"

prsDttR> parseDatetime("2016-12-07T10:11:12.123456-00:00")  ## default RFC3339 format
[1] "2016-12-07 10:11:12.123456 UTC"

prsDttR> now <- trunc(Sys.time())

prsDttR> parseDatetime(formatDatetime(now + 0:4))               # vectorised
[1] "2020-05-01 02:16:27 UTC" "2020-05-01 02:16:28 UTC"
[3] "2020-05-01 02:16:29 UTC" "2020-05-01 02:16:30 UTC"
[5] "2020-05-01 02:16:31 UTC"

prsDttR> options(digits.secs=ds)
R> 

它查看字符串的传入向量Rcpp::DatetimeVector parseDatetime(Rcpp::CharacterVector svec, std::string fmt = "%Y-%m-%dT%H:%M:%E*S%Ez", std::string tzstr = "UTC") { cctz::time_zone tz; load_time_zone(tzstr, &tz); sc::system_clock::time_point tp; cctz::time_point<cctz::sys_seconds> unix_epoch = sc::time_point_cast<cctz::sys_seconds>(sc::system_clock::from_time_t(0)); // if we wanted a 'start' timer //sc::system_clock::time_point start = sc::high_resolution_clock::now(); auto n = svec.size(); Rcpp::DatetimeVector dv(n, tzstr.c_str()); for (auto i=0; i<n; i++) { std::string txt(svec(i)); if (!cctz::parse(fmt, txt, tz, &tp)) Rcpp::stop("Parse error on %s", txt); // time since epoch, with fractional seconds added back in // only microseconds guaranteed to be present double dt = sc::duration_cast<sc::microseconds>(tp - unix_epoch).count() * 1.0e-6; // Rcpp::Rcout << "tp: " << cctz::format(fmt, tp, tz) << "\n" // << "unix epoch: " << cctz::format(fmt, unix_epoch, tz) << "\n" // << "(tp - unix.epoch).count(): " << (tp - unix_epoch).count() << "\n" // << "dt: " << dt << std::endl; dv(i) = Rcpp::Datetime(dt); } return dv; } 并进行转换。

编辑:这是另一个使用我们的svec包的示例,该包利用并使用CCTZ解析器:

nanotime

自纪元以来使用基础纳秒级的全9 + 9位精度,可与R> library(nanotime) R> as.nanotime("2020-01-29 13:12:00.000000001 America/New_York") [1] 2020-01-29T18:12:00.000000001+00:00 R> 完全互操作。

© www.soinside.com 2019 - 2024. All rights reserved.