Как преобразовать временную метку нано второй эпохи в читаемый формат - PullRequest
0 голосов
/ 25 июня 2019

У меня есть длинное целое число, представляющее метку времени эпохи с точностью до наносекунды, я хотел бы преобразовать ее в удобочитаемую метку времени, например дату-чч: мм: сс

Я пытался использовать статическое приведение и непосредственно приводил это целое число к формату time_t, и намеревался использовать локальное время для его форматирования, но безуспешно.

Из документации видно, что time_ts - это 32-разрядное целое число, что означает, что оно недостаточно велико, чтобы прочитать мою метку времени. Какой лучший способ отформатировать мою метку времени в удобочитаемый формат?

#include <iostream>
#include <sstream>
#include <locale>
#include <iomanip>
#include <ctime>

int main()
{
   time_t now = time(NULL);
   long long int ts = 1561402947698860015;

   time_t t = static_cast<time_t>(ts);
   std::cout << std::asctime(std::localtime(&t))
          << t << " seconds since the Epoch\n";
   std::cout<<"done"<<std::endl;
   return 0;
}

Ответы [ 2 ]

1 голос
/ 25 июня 2019

Вариант 1

Простое приведение не будет знать, что ему нужно сместить масштабирование числа с наноса до секунд (а секунды - это почти всегда приращение, используемое time_t). Для компилятора это просто одно целое число, назначаемое другому целому числу, может быть, даже того же типа. если у вас есть время в наносекундах и вы хотите использовать time_t, вам, вероятно, потребуется разделить на 1 000 000 000, чтобы преобразовать вашу печать в секунды.

#include <iostream>
#include <sstream>
#include <locale>
#include <iomanip>
#include <ctime>

constexpr long long int nanos_to_seconds = 1000000000; // conversion factor
constexpr long long int nanos_to_milis = 1000000;

int main()
{
   time_t now = time(NULL);
   long long int ts = 1561402947698860015;

   time_t t = static_cast<time_t>(ts/nanos_to_seconds);
                                  //^ change here
   long long int milis = ts % nanos_to_seconds / nanos_to_millis; // compute milliseconds
   std::cout << std::asctime(std::localtime(&t))
             << t << "." << std::setfill('0') << std::setw(3) << millis
             << " seconds since the Epoch\n";
   std::cout<<"done"<<std::endl;
   return 0;
}

Вариант 2

Начиная с C ++ 11, C ++ имеет встроенную поддержку наносекундных временных меток в библиотеке <chrono> . Объедините это с библиотекой дат Говарда Хиннанта , и все ваши проблемы с форматированием будут решены вместе с подготовкой вашего кода для C ++ 20. Это стоит посмотреть. Это не решает вашу текущую проблему прямо из коробки, но может использоваться, чтобы заменить проблему так, чтобы это было менее раздражающим в будущем.

Примечание:

В наши дни time_t обычно составляет 64-битное число секунд. 32-битный счетчик будет запущен через 20 лет или около того, поэтому вместо того, чтобы мириться с ошибкой Y2038 в последнюю минуту, переход на гораздо большее число был начат несколько десятилетий назад.

0 голосов
/ 25 июня 2019

Ваш код будет работать, если вы разделите для преобразования в секунды (как прокомментировал user4581301):

long long int ts = 1561402947698860015 / 1000000000;

Но также вместо:

std::asctime(std::localtime(&t))

вы можете просто использоватьследующее, чтобы получить тот же результат:

ctime(&t)
...