简体   繁体   中英

Trying to convert postgres time stamp string to c++ time stamp

I have PostgreSQL timestamp string:

  • 2020-07-06 09:30:00.646533

I'm trying to convert it to timeval struct, I tried using this answer , but I'm getting this output:

  • Thu Jan 1 00:33:40 1970

This is my code:

#include <iostream>
int main()
{
  std::string ss("2020-07-06 09:30:00.646533");
  auto t  = atoll(ss.c_str());
  time_t time = atoi(ss.c_str());
  std::cout << asctime(gmtime(&time));
  return 0;
}

When running with debugger, I see that this line

  • auto t = atoll(ss.c_str());

isn't working/set time with values.

How can i fix it?

atoll and atoi simply parse integers of various sizes from a string. They aren't great functions to use in general as they have no way of indicating that they have failed to parse the string. std::stoi and friends are the better functions to use. However in this case we don't have a number we have a date string so std::stoi won't work either (but it can at least tell you it didn't work).

c++20 comes with much better date support, until then Howard Hinnant's date library provides the same functionality:

#include "date.h"
#include <iostream>
#include <sstream>
#include <chrono>

int main()
{
    std::stringstream ss("2020-07-06 09:30:00.646533");
    // convert string to date time
    std::chrono::system_clock::time_point time;
    ss >> date::parse("%F %T", time);
    if (!ss) {
        std::cout << "invalid date\n";
        return 1;
    }
    // get the amount of time since the epoch, assumes std::chrono::system_clock uses the same epoch as timeval
    auto sinceEpoch = time.time_since_epoch();
    // get the whole number of seconds
    auto seconds = date::floor<std::chrono::seconds>(sinceEpoch);
    // get the remaining microseconds
    auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(sinceEpoch - seconds);
    std::cout << seconds.count() << ", " << microseconds.count() << "\n";
    return 0;
}

If you must re-invent the wheel you can do it using the pre c++20 standard library:

#include <iostream>
#include <sstream>
#include <chrono>
#include <iomanip>

int main()
{
    std::stringstream ss("2020-07-06 09:30:00.646533");
    std::tm tm;
    // convert string to date time
    std::chrono::system_clock::time_point time;
    double fraction;
    ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S") >> fraction;
    if (!ss) {
        std::cout << "invalid date\n";
        return 1;
    }
    time_t seconds = mktime(&tm);
    int64_t microseconds = fraction * 1'000'000;
    std::cout << seconds << ", " << microseconds << "\n";
    return 0;
}

Note that the microseconds should really be parsed as an integer not a double but you have to be careful to handle strings with different numbers of digits after the decimal point and with leading zeros.

you can use like this:

#include<ctime>
#include<iotream>
int main()
{
  std::string ss = "2020-07-06 09:30:00.646533";
  auto i = ss.find_first_of('.');
  std::string line(ss.begin()+(i+1),ss.end());
  std::tm tm = {};
  tm.tm_isdst = -1; // <- to set not to use day lghite saveing.
  strptime(ss.c_str(), "%F %H:%M:%S", &tm); //<-enter the data to tm
  start.tv_sec = mktime(&tm); //<-convert tm to time_t
  start.tv_usec = stoi(line); // <- set the usec from the stirng
  //IF you want the other why around

  strftime(tmbuf, sizeof tmbuf, " %F %H:%M:%S", localtime(&start.tv_sec));
  snprintf(buf, sizeof buf, "%s.%06ld", tmbuf, start.tv_usec);
  std::cout << tmbuf;  

  return 0;
}

output:

  • 2020-07-06 09:30:00.646533

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM