[英]Nanoseconds & Chrono C++
2018-10-01 00:06:16.700000000
我有一個帶有上述時間戳的時間序列數據文件。 我需要將其轉換為從紀元開始的納秒,然后我需要將毫秒、微米或納秒添加到時間戳(移位)。 最后,對於 select 記錄,將其恢復為上述格式。
我在創建時間點時遇到問題 - 以及如何表示納秒......它適用於微秒。
我可以請求一些關於下面的代碼片段的幫助......而且一旦我從紀元獲得納秒 - 我如何 go 回到像上面那樣的時間戳。
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;
}
我在創建時間點時遇到問題 - 以及如何表示納秒......它適用於微秒。
這告訴我您的system_clock::time_point
的精度比納秒更粗(在 llvm 上是微秒,在 Windows 上是 1/10 微秒)。 將納秒添加到此類time_point
的最簡單方法是:
auto tp = temp_time_point + nanoseconds (nsecs);
這個time_point
是一個仍基於system_clock
的 time_point,但具有system_clock::duration
和nanoseconds
的“通用類型”的精度,實際上,這只是nanoseconds
。
假設所有時間戳都是 GMT、UTC + 0
現在的問題是mktime
從本地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
。
Output:
1538352376700000000ns
2018-10-01 00:06:16.700000000
現在我知道現在完全符合 C++20 <chrono>
的東西很少見(它即將到來)。 在它出現之前,有一個與 C++11 兼容的C++20 <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';
}
Output:
1538352376700000000ns
2018-10-01 00:06:16.700000000
您可以將文本直接轉換為納秒級分辨率。 基本上有兩個關鍵庫:
我已經為 R (通過 Rcpp)包裝了兩者,並且有很多例子。 但是這兩個倉庫中也有例子,所以也許從那里開始?
因此,由於缺乏更好的直接 CCTZ 示例,這里是使用 R package 的示例; 你看到輸入:
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>
調用的解析器 function 是(並忽略 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
並轉換每個字符串。
編輯:這是使用我們的nanotime package 的另一個示例,它利用並使用 CCTZ 解析器:
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>
自紀元以來使用底層納秒的完整 9 + 9 位精度,可與std::chrono
完全互操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.