HowardHinnant / date

A date and time library based on the C++11/14/17 <chrono> header
Other
3.08k stars 669 forks source link

how can i make UTC date time compatible with postgres TIME from a nanosecond timestamp ? #742

Open JourneyToSilius opened 1 year ago

JourneyToSilius commented 1 year ago
    std::chrono::milliseconds milliTime = std::chrono::milliseconds(message.E);

    std::chrono::nanoseconds ns = std::chrono::duration_cast<std::chrono::nanoseconds> (milliTime);

    int64_t nanoTime = ns.count();

So I've got a nano timestamp as int64_t and I need to make a date time UTC compatible with postgres TIME format UTC

I have been trying to find answers in stack overflow but none related on how to do this specific parsing

I am trying to do this : date::sys_time<std::chrono::nanoseconds>{nanoTime};

but it does not accept the this type for conversion ...

Thanks !

HowardHinnant commented 1 year ago

Sorry, I'm not familiar with postgres. However, the input seems to be an integral number of milliseconds contained in message.E. And I'm going to guess that this number of milliseconds is a time duration since the Unix Time epoch of 1970-01-01. Is that right?

The output I'm more confused about: Is it a date/time string you're looking for? Or a count of nanoseconds since the Unix Time epoch?

HowardHinnant commented 1 year ago

date::sys_time<std::chrono::nanoseconds>{ns}; will work. The input needs to have type nanoseconds, or something implicitly convertible to nanoseconds such as:

date::sys_time<std::chrono::nanoseconds>{std::chrono::milliseconds{message.E}};
JourneyToSilius commented 1 year ago

Hi Howard and thank you for your answer !

The format in postgres I'm using is this, which is UTC time witth nanosecond precission : 2022-07-10 01:03:57.369263+0

Thanks I'm going to try this right now

JourneyToSilius commented 1 year ago

ok now it compiles, thanks ! How can I convert it to a string ?

HowardHinnant commented 1 year ago

Before I answer, clarification: You're asking for nanosecond precision, but the example you show has microsecond precision (6 places vs 9). Which should it be?

JourneyToSilius commented 1 year ago

ah yes, sorry ... this was another database example I was looking at. It's on nano, yes ! Thank you

HowardHinnant commented 1 year ago
#include "date/date.h"
#include <chrono>
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;

    int64_t input = 1657415037369263000;  // nanoseconds of Unix Time
    sys_time<nanoseconds> tp{nanoseconds{input}};
    auto str_out = format("%F %T+0", tp);
    cout << str_out << '\n';
}

Output:

2022-07-10 01:03:57.369263000+0
JourneyToSilius commented 1 year ago

thank you very much, I got it working now. Just one more thing, is there a section where I can look at all the options for time formatiing ? just in case since I will use this extensively and I might need to do other resolutions, like microseconds, miliseconds, etc

Thanks !

HowardHinnant commented 1 year ago

Yes, here are all of the formatting options: https://howardhinnant.github.io/date/date.html#to_stream_formatting

HowardHinnant commented 1 year ago

To change the resolution, truncate the time stamp passed to format using one of time_point_cast, floor, ceil, or round. E.g.:

    auto str_out = format("%F %T+0", floor<milliseconds>(tp));
JourneyToSilius commented 1 year ago

I'm studying it now. thank you for your prompt answers, I will close this now :)

JourneyToSilius commented 1 year ago

Hi Howard

I am struggling with the format on postgres, it doesn't accept the one date.h produces

I had a POC of this program in Go, which worked out of the box with TIMESTAMPZ postgres format. The Go produced string was this : 2022-08-02 16:37:20.472778873 +0000 UTC

the one date.h is producing right now is: 2022-08-02 16:37:20.472778873+0

HowardHinnant commented 1 year ago

Try:

auto str_out = format("%F %T %z %Z", tp);