I need to convert a boost::posix_time::ptime into a NTP Datestamp according to
RFC 5905 represented by the following structure:
struct NtpDatestamp {
std::int32_t era_number;
std::uint32_t seconds_since_era_epoch;
std::uint64_t fraction_of_second;
};
RFC 5905 states the following:
To convert system time in any format to NTP date and timestamp formats
requires that the number of seconds s from the prime epoch to the system
time be determined. To determine the integer era and timestamp given s,
era = s / 2^(32) and timestamp = s - era * 2^(32),
which works for positive and negative dates. To determine s given the era
and timestamp,
s = era * 2^(32) + timestamp.
Therefore I've tried the following:
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)};
But that gives incorrect results.
I am completely stumped with this (actually simple) problem at the moment.
Can someone guide me into the correct direction? How can I obtain the era number, era offset and fraction of a NTP datestamp from a boost::posix_time::ptime?
Edit: Either the calculations in RFC 5905 are not accurate enough or I do misinterpret them. Thanks to the comments I've changed the calculation to the following (this time a complete example):
#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 is calculated correctly now, but the other calculations are wrong. I think I do miss something important completely...
It seems that I've figured out the missing pieces by myself. I've implemented the following algorithm in a reusable class ntp::Datestamp and unit tested it with the reference dates of RFC 5905. All tests finally are green. Here is the solution:
#include <cmath>
#include <cstdint>
#include <ctime>
#include <iostream>
#include <boost/date_time.hpp>
static std::time_t to_time(const boost::posix_time::ptime& time) {
static const boost::posix_time::ptime epoch_time{
boost::gregorian::date{1970, 1, 1}};
const boost::posix_time::time_duration diff{time - epoch_time};
return (diff.ticks() / diff.ticks_per_second());
}
int main() {
const auto system_time =
boost::posix_time::time_from_string("1899-12-31 00:00:00.123");
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.
std::time_t s{to_time(system_time) - to_time(prime_epoch)};
const std::int32_t era{static_cast<std::int32_t>(std::floor(s / std::pow(2, 32)))};
const std::uint32_t timestamp{
static_cast<std::uint32_t>(s - era * std::pow(2, 32))};
const std::uint64_t fraction{static_cast<std::uint64_t>(
system_time.time_of_day().fractional_seconds())};
std::cout << "s = " << std::dec << s << '\n';
std::cout << "Era (expected: -1) = " << std::dec << era << '\n';
std::cout << "Timestamp (expected: 4294880896) = " << std::dec << timestamp
<< '\n';
std::cout << "Fraction (expected: 123000) = " << std::dec << fraction << '\n';
}
Related
I have a very naive struct representing date time which I would like to perform arithmetic on:
struct MyDateTime
{
MyDateTime(int year, int month, int day, uint64_t nanos);
int year;
int month;
int day;
uint64_t nanosSinceMidnight;
};
I'd like to be able to add/subtract MyDateTime from another MyDateTime.
My idea was to make my struct a wrapper and use Boost internally.
I looked at Boost Posix Time:
https://www.boost.org/doc/libs/1_55_0/doc/html/date_time/examples.html#date_time.examples.time_math
But this seems to only be doing time math (not accounting for the date component).
I looked at Boost Gregorian Date but I couldn't see any time argument in the constructors.
What is the simplest way to use Boost, so I can perform datetime arithmetic?
As you may have realized by now, dates cannot be added.
Dates and timestamps are mathematically akin to tensors, in that their difference type is in a different domain.
When you commented that time_duration doesn't include a date, you still had a point though.
Because the time_duration might be the time-domain difference type (the difference type ptime) but we need an analog for the date-part of ptime, which is boost::gregorian::date.
Boost Gregorian dates are basically blessed tuples of (yyyy,mm,dd).So a natural difference type would just be a signed integral number of days. And that's exactly* what boost::gregorian::date_duration is:
boost::gregorian::date_duration x = date{} - date{};
boost::posix_time::time_duration y = ptime{} - ptime{};
Because that type is implemented in the Gregorian module you will get correct differences, even with special cases like leap days and other anomalies: https://www.calendar.com/blog/gregorian-calendar-facts/
So, you could in fact use that type as a difference type, just for the ymd part.
Simplify
The good news is, you don't have to bother: boost::posix_time::ptime encapsulates a full boost::gregorian::date, hence when you get a boost::posix_time::time_duration from subtracting ptimes, you will already get the number of days ciphered in:
#include <boost/date_time.hpp>
int main() {
auto now = boost::posix_time::microsec_clock::local_time();
auto later = now + boost::posix_time::hours(3);
auto tomorrow = later + boost::gregorian::days(1);
auto ereweek = later - boost::gregorian::weeks(1);
std::cout << later << " is " << (later - now) << " later than " << now
<< std::endl;
std::cout << tomorrow << " is " << (tomorrow - later) << " later than " << later
<< std::endl;
std::cout << ereweek << " is " << (ereweek - now) << " later than " << now
<< std::endl;
}
Starting from the current time we add 3 hours, 1 day and then subtract a week. It prints: Live On Coliru:
2021-Mar-28 01:50:45.095670 is 03:00:00 later than 2021-Mar-27 22:50:45.095670
2021-Mar-29 01:50:45.095670 is 24:00:00 later than 2021-Mar-28 01:50:45.095670
2021-Mar-21 01:50:45.095670 is -165:00:00 later than 2021-Mar-27 22:50:45.095670
Note that 24h is 1 day, and -165h is (7*24 - 3) hours ago.
There's loads of smarts in the Gregorian calendar module:
std::cout << date{2021, 2, 1} - date{2020, 2, 1} << std::endl; // 366
std::cout << date{2020, 2, 1} - date{2019, 2, 1} << std::endl; // 365
Taking into account leap days. But also knowing the varying lengths of a calendar month in context:
auto term = boost::gregorian::months(1);
for (date origin : {date{2021, 2, 17}, date{2021, 3, 17}}) {
std::cout << ((origin + term) - origin) << std::endl;
};
Prints 28 and 31 respectively.
Applying It To Your Type
I'd suggest keeping with the library difference type, as clearly you had not previously given it any thought that you needed one. By simply creating some interconversions you can have your cake and eat it too:
struct MyDateTime {
MyDateTime(int year = 1970, int month = 1, int day = 1, uint64_t nanos = 0)
: year(year),
month(month),
day(day),
nanosSinceMidnight(nanos) {}
operator ptime() const {
return {date(year, month, day),
microseconds(nanosSinceMidnight / 1'000)};
}
explicit MyDateTime(ptime const& from)
: year(from.date().year()),
month(from.date().month()),
day(from.date().day()),
nanosSinceMidnight(from.time_of_day().total_milliseconds() * 1'000) {}
private:
int year;
int month;
int day;
uint64_t nanosSinceMidnight;
};
Now, I would question the usefulness of keeping your MyDateTime type, but I realize legacy code exists, and sometimes you require a longer time period while moving away from it.
Nanoseconds
Nanosecond precision is not enabled by default. You need to [opt in to use that](https://www.boost.org/doc/libs/1_58_0/doc/html/date_time/details.html#boost-common-heading-doc-spacer:~:text=To%20use%20the%20alternate%20resolution%20(96,the%20variable%20BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG%20must%20be%20defined).
In the sample below I do.
Be careful that al the translation units in your project use the define, or you will cause ODR violations.
Live Demo
Adding some convenience operator<< as well:
Live On Coliru
#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
#include <boost/date_time.hpp>
#include <vector>
using boost::posix_time::ptime;
using boost::gregorian::date;
using boost::posix_time::nanoseconds;
struct MyDateTime {
MyDateTime(MyDateTime const&) = default;
MyDateTime& operator=(MyDateTime const&) = default;
MyDateTime(int year = 1970, int month = 1, int day = 1, uint64_t nanos = 0)
: year(year),
month(month),
day(day),
nanosSinceMidnight(nanos) {}
operator ptime() const {
return {date(year, month, day), nanoseconds(nanosSinceMidnight)};
}
/*explicit*/ MyDateTime(ptime const& from)
: year(from.date().year()),
month(from.date().month()),
day(from.date().day()),
nanosSinceMidnight(from.time_of_day().total_nanoseconds()) {}
private:
friend std::ostream& operator<<(std::ostream& os, MyDateTime const& dt) {
auto save = os.rdstate();
os << std::dec << std::setfill('0') << std::setw(4) << dt.year << "/"
<< std::setw(2) << dt.month << "/" << std::setw(2) << dt.day << " +"
<< dt.nanosSinceMidnight;
os.setstate(save);
return os;
}
int year;
int month;
int day;
uint64_t nanosSinceMidnight;
};
int main() {
namespace g = boost::gregorian;
namespace p = boost::posix_time;
using p::time_duration;
std::vector<time_duration> terms{p::seconds(30), p::hours(-168),
p::minutes(-15),
p::nanoseconds(60'000'000'000 * 60 * 24)};
for (auto mydt : {MyDateTime{2021, 2, 17}, MyDateTime{2021, 3, 17}}) {
std::cout << "---- Origin: " << mydt << "\n";
for (time_duration term : terms) {
mydt = ptime(mydt) + term;
std::cout << "Result: " << mydt << "\n";
}
};
}
Prints
---- Origin: 2021/02/17 +0
Result: 2021/02/17 +30000000000
Result: 2021/02/10 +30000000000
Result: 2021/02/09 +85530000000000
Result: 2021/02/10 +85530000000000
---- Origin: 2021/03/17 +0
Result: 2021/03/17 +30000000000
Result: 2021/03/10 +30000000000
Result: 2021/03/09 +85530000000000
Result: 2021/03/10 +85530000000000
Converting from UUID timestamp to seconds since EPOCH seems quite easy based on the specs, also based on Cassandra's C++ driver source code based on its struct definition.
However, when I try to do it, I always get the wrong value. I'm doing something wrong and I'm unable to figure out what it's.
For that, I used sample UUID values provided from here and here.
All one has to do is take the first uint64_t from the UUID raw data, mask its first four MSb, subtract a difference and divide by a number.
Here's my minimum complete example:
#include <boost/date_time.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <cstdint>
#include <iostream>
uint64_t TimestampFromUUID(const boost::uuids::uuid& uuid) {
static constexpr const int UUID_SIZE = 16;
static_assert(sizeof(uuid) == UUID_SIZE, "Invalid size of uuid");
static constexpr const int MS_FROM_100NS_FACTOR = 10000;
static constexpr const uint64_t OFFSET_FROM_15_10_1582_TO_EPOCH = 122192928000000000;
struct two64s {
uint64_t n1;
uint64_t n2;
} contents;
std::memcpy(&contents, uuid.data, UUID_SIZE);
// contents.n1 = __builtin_bswap64(contents.n1);
uint64_t timestamp = contents.n1 & UINT64_C(0x0FFFFFFFFFFFFFFF);
return (timestamp - OFFSET_FROM_15_10_1582_TO_EPOCH) / MS_FROM_100NS_FACTOR;
}
int main() {
std::cout << "Time now: " << (boost::posix_time::second_clock::universal_time() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_milliseconds() << std::endl;
auto gen = boost::uuids::string_generator();
std::cout << "UUID: " << gen("49cbda60-961b-11e8-9854-134d5b3f9cf8") << std::endl;
std::cout << "Time from UUID: " << TimestampFromUUID(gen("49cbda60-961b-11e8-9854-134d5b3f9cf8")) << std::endl;
std::cout << "UUID: " << gen("58e0a7d7-eebc-11d8-9669-0800200c9a66") << std::endl;
std::cout << "Time from UUID: " << TimestampFromUUID(gen("58e0a7d7-eebc-11d8-9669-0800200c9a66")) << std::endl;
return 0;
}
The output of this program is:
Time now: 1571735685000
UUID: 49cbda60-961b-11e8-9854-134d5b3f9cf8
Time from UUID: 45908323159150
UUID: 58e0a7d7-eebc-11d8-9669-0800200c9a66
Time from UUID: 45926063291384
You can play with this source code here.
Why are my results not even close to current timestamp? What am I doing wrong?
I think it would be easier to understand by processing the UUID as a string and using string manipulation to extract the timestamp information, which is then converted to a numerical value. The trick is the way timestamp information is stored in the UUID. From the specification:
The formal definition of the UUID string representation is
provided by the following ABNF [7]:
UUID = time-low "-" time-mid "-"
time-high-and-version "-"
clock-seq-and-reserved
clock-seq-low "-" node
time-low = 4hexOctet
time-mid = 2hexOctet
time-high-and-version = 2hexOctet
clock-seq-and-reserved = hexOctet
clock-seq-low = hexOctet
node = 6hexOctet
hexOctet = hexDigit hexDigit
hexDigit =
"0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
"a" / "b" / "c" / "d" / "e" / "f" /
"A" / "B" / "C" / "D" / "E" / "F"
The following is an example of the string representation of a UUID
as a URN:
urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6
i.e. the first part of the UUID (before '-') is the time-low, the second the time-mid and the third is the time-high-version, with the first character being the UUID version. So we need to split the UUID and recombine these timestamp parts to create the full timestamp string like this: {time-high minus-version}{time-mid}{time-low}
Here's the modified piece of code. I have taken this nice javascript example as a reference: https://stackoverflow.com/a/26915856/3694234
#include <boost/date_time.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <cstdint>
#include <iostream>
uint64_t TimestampFromUUID(const boost::uuids::uuid& uuid) {
static constexpr const int UUID_SIZE = 16;
static_assert(sizeof(uuid) == UUID_SIZE, "Invalid size of uuid");
static constexpr const int MS_FROM_100NS_FACTOR = 10000;
static constexpr const uint64_t OFFSET_FROM_15_10_1582_TO_EPOCH = 122192928000000000;
/* convert uuid to string for manipulation */
std::string uuid_str = boost::uuids::to_string(uuid);
/* store uuid parts in a vector */
std::vector<std::string> uuid_parts;
/* split uuid with '-' as delimiter */
boost::split(uuid_parts, uuid_str, [](char c){return c == '-';});
/* first part of uuid is time-low
second part is time-mid
third part is time high with most significant 4 bits as uuid version
*/
std::string uuid_timestamp = uuid_parts[2].substr(1) + uuid_parts[1] + uuid_parts[0];
std::cout << std::endl << "UUID Timestamp : " << uuid_timestamp << std::endl;
uint64_t timestamp = std::stoul(uuid_timestamp, nullptr, 16);
return (timestamp - OFFSET_FROM_15_10_1582_TO_EPOCH) / MS_FROM_100NS_FACTOR;
}
int main() {
std::cout << "Time now: " << (boost::posix_time::second_clock::universal_time() - boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_milliseconds() << std::endl;
auto gen = boost::uuids::string_generator();
std::cout << "UUID: " << gen("49cbda60-961b-11e8-9854-134d5b3f9cf8") << std::endl;
std::cout << "Time from UUID: " << TimestampFromUUID(gen("49cbda60-961b-11e8-9854-134d5b3f9cf8")) << std::endl;
std::cout << "UUID: " << gen("58e0a7d7-eebc-11d8-9669-0800200c9a66") << std::endl;
std::cout << "Time from UUID: " << TimestampFromUUID(gen("58e0a7d7-eebc-11d8-9669-0800200c9a66")) << std::endl;
return 0;
}
Output
Time now: 1571838175000
UUID: 49cbda60-961b-11e8-9854-134d5b3f9cf8
Time from UUID:
UUID Timestamp : 1e8961b49cbda60
1533190458118
UUID: 58e0a7d7-eebc-11d8-9669-0800200c9a66
Time from UUID:
UUID Timestamp : 1d8eebc58e0a7d7
1092575371981
IMHO you were not doing it properly all along. Reading the documentation you provided I tried to regenerate the timestamp from UUID. Here's my code to do it:
uint64_t TimestampFromUUID(const boost::uuids::uuid& uuid) {
static constexpr const int UUID_SIZE = 16;
static_assert(sizeof(uuid) == UUID_SIZE, "Invalid size of uuid");
static constexpr const int MS_FROM_100NS_FACTOR = 10000;
static constexpr const uint64_t OFFSET_FROM_15_10_1582_TO_EPOCH = 122192928000000000;
uint64_t timestamp = uuid.data[3] + (uuid.data[2] << 8) + (uuid.data[1] << 16) + (uuid.data[0] << 24);
timestamp += ((uint64_t)uuid.data[4] << 40) + ((uint64_t)uuid.data[5] << 32);
timestamp += ((uint64_t)uuid.data[7] << 48) + ((uint64_t)(uuid.data[6] & 0x0F) << 56);
return (timestamp - OFFSET_FROM_15_10_1582_TO_EPOCH) / MS_FROM_100NS_FACTOR;
}
I have following C code:
uint64_t combine(uint32_t const sec, uint32_t const usec){
return (uint64_t) sec << 32 | usec;
};
uint64_t now3(){
struct timeval tv;
gettimeofday(&tv, NULL);
return combine((uint32_t) tv.tv_sec, (uint32_t) tv.tv_usec);
}
What this do it combine 32 bit timestamp, and 32 bit "something", probably micro/nanoseconds into single 64 bit integer.
I have really hard time to rewrite it with C++11 chrono.
This is what I did so far, but I think this is wrong way to do it.
auto tse = std::chrono::system_clock::now().time_since_epoch();
auto dur = std::chrono::duration_cast<std::chrono::nanoseconds>( tse ).count();
uint64_t time = static_cast<uint64_t>( dur );
Important note - I only care about first 32 bit to be "valid" timestamp.
Second 32 bit "part" can be anything - nano or microseconds - everything is good as long as two sequential calls of this function give me different second "part".
i want seconds in one int, milliseconds in another.
Here is code to do that:
#include <chrono>
#include <iostream>
int
main()
{
auto now = std::chrono::system_clock::now().time_since_epoch();
std::cout << now.count() << '\n';
auto s = std::chrono::duration_cast<std::chrono::seconds>(now);
now -= s;
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now);
int si = s.count();
int msi = ms.count();
std::cout << si << '\n';
std::cout << msi << '\n';
}
This just output for me:
1447109182307707
1447109182
307
The C++11 chrono types use only one number to represent a time since a given Epoch, unlike the timeval (or timespec) structure which uses two numbers to precisely represent a time. So with C++11 chrono you don't need the combine() method.
The content of the timestamp returned by now() depends on the clock you use; there are tree clocks, described in http://en.cppreference.com/w/cpp/chrono :
system_clock wall clock time from the system-wide realtime clock
steady_clock monotonic clock that will never be adjusted
high_resolution_clock the clock with the shortest tick period available
If you want successive timestamps to be always different, use the steady clock:
auto t1 = std::chrono::steady_clock::now();
...
auto t2 = std::chrono::steady_clock::now();
assert (t2 > t1);
Edit: answer to comment
#include <iostream>
#include <chrono>
#include <cstdint>
int main()
{
typedef std::chrono::duration< uint32_t, std::ratio<1> > s32_t;
typedef std::chrono::duration< uint32_t, std::milli > ms32_t;
s32_t first_part;
ms32_t second_part;
auto t1 = std::chrono::nanoseconds( 2500000000 ); // 2.5 secs
first_part = std::chrono::duration_cast<s32_t>(t1);
second_part = std::chrono::duration_cast<ms32_t>(t1-first_part);
std::cout << "first part = " << first_part.count() << " s\n"
<< "seconds part = " << second_part.count() << " ms" << std::endl;
auto t2 = std::chrono::nanoseconds( 2800000000 ); // 2.8 secs
first_part = std::chrono::duration_cast<s32_t>(t2);
second_part = std::chrono::duration_cast<ms32_t>(t2-first_part);
std::cout << "first part = " << first_part.count() << " s\n"
<< "seconds part = " << second_part.count() << " ms" << std::endl;
}
Output:
first part = 2 s
seconds part = 500 ms
first part = 2 s
seconds part = 800 ms
I'm looking for a concise solution to output a boost::posix_time::time_duration with a precision of milliseconds: There should be exactly 3 fractional-second digits. The default format produces 6 fractional digits (or none, if they are all 0):
#include <boost/date_time.hpp>
#include <iostream>
int main()
{
// Define some duration in milliseconds:
int64_t start_msecs((((40 * 60) + 3) * 60 + 2) * 1000 + 1);
// The same as time_duration:
boost::posix_time::time_duration start_time =
boost::posix_time::milliseconds(start_msecs);
// No suitable format (for MP4Box chapter starts): ////////////////////
std::cout << "Wrong format: "
<< std::setprecision(3) // <-- No effect!?
<< start_time << std::endl;
// Output: "Wrong format: 40:03:02.001000"
// Required format : 40:03:02.001
return 0;
}
Using facets and some work arounds, I can get the required output. But that solution only disables the parts of the date-time library I can't get configured to my needs and replaces them with a low level implementation:
#include <boost/date_time.hpp>
#include <iostream>
int main()
{
// Define some duration in milliseconds:
int64_t start_msecs((((40 * 60) + 3) * 60 + 2) * 1000 + 1);
// The same as time_duration:
boost::posix_time::time_duration start_time =
boost::posix_time::milliseconds(start_msecs);
// Define output format without fractional seconds:
boost::posix_time::time_facet *output_facet =
new boost::posix_time::time_facet();
output_facet->time_duration_format("%O:%M:%S");
// Imbue cout with format for duration output:
std::cout.imbue(std::locale(std::locale::classic(), output_facet));
// Only the milliseconds:
int64_t msecs_only = start_msecs % 1000;
// Render duration with exactly 3 fractional-second digits: ///////////
std::cout << "Working: "
<< start_time << "."
<< std::setw(3) << std::right << std::setfill('0')
<< msecs_only << std::endl;
// Output: "Working: 40:03:02.001"
return 0;
}
What would be the recommended way to achieve the required output?
I am using boost::posix_time::ptime to measure my simulation run-time and for something else.
assuimg
boost::posix_time::ptime start, stop;
boost::posix_time::time_duration diff;
start = boost::posix_time::microsec_clock::local_time();
sleep(5);
stop = boost::posix_time::microsec_clock::local_time();
diff = stop - stop;
now
std::cout << to_simple_string( diff ) << std::endl;
return the time in hh:mm:ss.ssssss format and i would like to have the time as well in ss.sssssss.
for doing this, i tried
boost::posix_time::time_duration::sec_type x = diff.total_seconds();
but that gave me the answer in format of ss and seconds() returns Returns normalized number of seconds (0..60).
My question how could i get my simulation time in seconds of the format ss.ssssss?
EDIT
i was able to do:
std::cout << diff.total_seconds() << "." << diff.fractional_seconds() << std::endl;
is there something elegant that could plot ss.sssssss?
total_seconds() returns a long value which is not normalized to 0..60s.
So just do this:
namespace bpt = boost::posix_time;
int main(int , char** )
{
bpt::ptime start, stop;
start = bpt::microsec_clock::local_time();
sleep(62);
stop = bpt::microsec_clock::local_time();
bpt::time_duration dur = stop - start;
long milliseconds = dur.total_milliseconds();
std::cout << milliseconds << std::endl; // 62000
// format output with boost::format
boost::format output("%.2f");
output % (milliseconds/1000.0);
std::cout << output << std::endl; // 62.00
}
// whatever time you have (here 1second)
boost::posix_time::ptime pt = boost::posix_time::from_time_t( 1 );
// subtract 0 == cast to duration
boost::posix_time::time_duration dur = pt - boost::posix_time::from_time_t(0);
// result in ms
uint64_t ms = dur.total_milliseconds();
// result in usec
uint64_t us = dur.total_microseconds();
// result in sec
uint64_t s = dur.total_seconds();
std::cout << "s = " << s << ", ms = " << ms << ", us = " << us << std::endl;
s = 1, ms = 1000, us = 1000000
The most straight-forward way I see is something like this output, the rest of the time computations along the lines of nabulke's post:
#include <iomanip>
double dseconds = dur.total_milliseconds() / 1000. ;
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3);
std::cout << dseconds << std::endl;
You want to express time in terms of a floating point number, so it's probably best to actually use one and apply the standard stream formatting manipulators.