我需要根据 RFC 5905由以下结构表示为boost::posix_time::ptime
转换成NTP 日期邮票:转换的boost ::了posix_time ::的ptime到NTP时间戳
struct NtpDatestamp {
std::int32_t era_number;
std::uint32_t seconds_since_era_epoch;
std::uint64_t fraction_of_second;
};
RFC 5905条规定如下:
要转换系统时间以任何形式向NTP日期和时间戳的格式 要求从黄金时期秒
s
到系统0号时间确定。为了确定整数era
和timestamp
给出s
,era = s/2^(32) and timestamp = s - era * 2^(32),
它适用于正面和负面的日期。为了确定给定的时代 和时间戳
s
,s = era * 2^(32) + timestamp.
所以我尝试了以下内容:
const auto system_time = boost::posix_time::time_from_string("1899-12-31 00:00:00.000");
const boost::posix_time::ptime prime_epoch{boost::gregorian::date{1900, 1, 1}};
// Calculate the number of seconds from the prime epoch to the system time.
const boost::posix_time::time_duration time_duration{system_time - prime_epoch};
const std::int64_t s{time_duration.total_seconds()};
const std::int32_t era_number{static_cast<std::int32_t>(s/std::pow(2, 32))};
const std::uint64_t seconds_since_era_epoch{static_cast<std::uint64_t>(s - s/std::pow(2, 32) * std::pow(2, 32))};
// The fraction of a NTP Datestamp is measured in Attoseconds.
const std::uint64_t fraction_of_second{static_cast<std::uint64_t>(time_duration.total_microseconds() * 1e12)};
但是,让不正确的结果。
我完全被这个(其实很简单)的问题困扰着。
有人可以引导我进入正确的方向吗?我如何获得时代号码,时代补偿和分数 NTP日期戳boost::posix_time::ptime
?
编辑: RFC 5905中的计算不够准确,或者我误解了它们。多亏了意见,我已经改变了计算如下(此时一个完整的例子):
#include <cmath>
#include <cstdint>
#include <iostream>
#include <boost/date_time.hpp>
int main() {
const auto system_time =
boost::posix_time::time_from_string("1899-12-31 00:00:00.000");
const boost::posix_time::ptime prime_epoch{
boost::gregorian::date{1900, 1, 1}};
// Calculate the number of seconds from the prime epoch to the system time.
const boost::posix_time::time_duration time_duration{prime_epoch -
system_time};
// s is correctly determined now.
std::int64_t s{time_duration.total_seconds()};
if (prime_epoch > system_time) {
// boost::posix_time::time_duration does not take the sign into account.
s *= -1;
}
// TODO(wolters): The following calculations do not return the correct
// results, but the RFC 5905 states them
const std::int32_t era{static_cast<std::int32_t>(s/std::pow(2, 32))};
const std::uint64_t timestamp{
static_cast<std::uint64_t>(s - era * std::pow(2, 32))};
// The fraction of a NTP Datestamp is measured in Attoseconds.
// TODO(wolters): `boost::posix_time::ptime` does NOT resolve to attoseconds,
// but doesn't the target format expect the value to be specified as
// attoseconds? Doesn't the following depend on Boost compile options?
const std::uint64_t fraction{
static_cast<std::uint64_t>(time_duration.fractional_seconds())};
std::cout << "s = " << std::dec << s << '\n';
// TODO(wolters): This does still not match the expected results; taken from
// Figure 4 of https://www.ietf.org/rfc/rfc5905.txt
std::cout << "Era (expected: -1) = " << std::dec << era << '\n';
std::cout << "Timestamp (expected: 4294880896) = " << std::dec << timestamp
<< '\n';
std::cout << "Fraction (expected: 0) = " << std::dec << fraction << '\n';
}
s
现在可以正确地计算,但其他的计算是错误的。我想我完全错过了一些重要的东西......
一个问题:seconds_since_era_epoch应该计算的S - era_number * 2^32,但你计算的方式,它会永远是零。 – lrm29
第二个问题:fraction_of_second应该使用time_duration.fractional_seconds() 第三个问题:ptime无法解析为attoseconds ... – lrm29