4

I have a function from a library i'm using that requires a double as a parameter. It needs to be passed an offset of type nanoseconds plus the sytem_clock::now(). I have this code so far:

system_clock::time_point now = std::chrono::system_clock::now(); 
    auto timepointoffset = (now + desiredOffset);

How can I make this a double?

Edit: So I need to add that the problem is that I need to do it without a risk of losing data. I have this code:

    system_clock::time_point now = std::chrono::system_clock::now(); 
    auto timepointoffset =  std::chrono::time_point_cast<std::chrono::nanoseconds>(now + desiredOffset);
    double value = timepointoffset.time_since_epoch().count();

The problem is that the compiler says that there is a possible loss of data.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
ecain
  • 1,282
  • 5
  • 23
  • 54

5 Answers5

10

This program:

#include <chrono>
#include <cmath>
#include <iostream>

int
main()
{
    using namespace std::chrono;
    auto tp = system_clock::now() + 0ns;
    double t1 = tp.time_since_epoch().count();
    double t2 = std::nextafter(t1, INFINITY);
    std::cout << t2-t1 << '\n';
}

currently outputs:

256

This means that currently a double can not exactly represent the number of nanoseconds since 1970-01-01 00:00:00 UTC. A double can represent a unit equal to 256ns (about a quarter of a microsecond).

This has been true since 2006-07-14 23:58:24.606847232. Before then (for a while), a double could represent with a precision of 128ns.

At 2043-01-25 23:56:49.213694464 UTC a double will start being able to represent a precision of only 512ns.

A double can store a system_clock::time_point with nanosecond precision only in the approximate range of 1969-09-18 18:00:01 to 1970-04-15 05:59:59.

This analysis of course assumes an IEEE 64 bit double.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
2

The time_point template has a member function time_point::time_since_epoch that returns the time since epoch as a duration object. duration is a template type and the exact duration type returned by the function is the same as the Duration template parameter of the time_point. The type of time_point returned by system_clock::now() on the other hand is implementation defined.

You want the time in a specific representation. To achieve that, you must have the duration of the desired type. In this case, you want std::duration<double, std::ratio<1>>. To get the duration returned by time_since_epoch in correct type, you can cast it using std::chrono::duration_cast. When you have the duration of the correct representation, you can use the count member function of duration to get the value in the desired representation.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thanks for the answer, I believe I did as you said, but I am still getting a warning that there is a possible loss of data. Am I doing it incorrectly? – ecain Nov 18 '15 at 19:05
  • @Elijah maybe you are, or maybe there is something else wrong with your code. The exact warning message and the line that it points to should reveal what's wrong. – eerorika Nov 18 '15 at 22:41
1
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(
  std::chrono::system_clock::now().time_since_epoch()).count() << std::endl;

appears to be the correct way to get a long: http://en.cppreference.com/w/cpp/chrono/time_point/time_since_epoch which you can then convert to double.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
0

You can cast timepointoffset to std::time_t and then cast it to double:

std::time_t offsetTimet = std::chrono::system_clock::to_time_t(timepointoffset);
double offsetDouble = static_cast<double>(offsetTimet);

Be aware that while std::time_t is normally an integer type, there is no guarantee.

Community
  • 1
  • 1
user2891462
  • 3,033
  • 2
  • 32
  • 60
0

So I need to add that the problem is that I need to do it without a risk of losing data. I have this code:

There is no way to do this in general. When you convert from an integer type to a floating point type, you will typically lose precision. Using floating point, the bits are split into a mantissa and an exponent. Since an integer has no bits allocated for an exponent, there are generally fewer bits of precision to represent the value.

For example, converting from int64_t to double. An int64_t has 1 sign bit, and 63 value bits. A double has 1 sign bit, 11 exponent bits, and 52 mantissa bits. So converting from int64_t (63) to double (52), you can lose up to 11 bits of information.

Jason
  • 3,777
  • 14
  • 27