11917640 Member Ответов: 3

Операции с датой в миллисекундах


Мне нужен способ управлять датой, включая миллисекунды: получить текущую дату и время, добавить к ней заданное количество миллисекунд. Первая часть завершена.
Версия C++ до C++14.
Спасибо.

Обновление: некоторая предыстория. У меня есть файл с отметкой времени в начале и количеством записей, каждая из которых содержит количество миллисекунд от этого начального времени:

2108 6 21 15 14 56 588
1000 message
5577 message
10000 message
...

Итак, мне нужно напечатать каждое сообщение с его полным временем. Поскольку у меня уже есть преобразование time_point в timestamp, мне действительно нужно противоположное преобразование, которое выглядит немного сложным.

Что я уже пробовал:

#include <chrono>
#include <ctime>

struct timestamp
{
    int year;    // 0-based 
    int month;   // [1-12]
    int day;     // [1-31]
    int hour;    // [0-23]
    int minute;  // [0-59]
    int sec;     // [0-59]
    int ms;      // [0-999]
};

// Done
timestamp get_local_date()
{
    timestamp t;

    auto now = std::chrono::system_clock::now();
    auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
    auto fraction = now - seconds;
    auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(fraction);

    time_t tnow = std::chrono::system_clock::to_time_t(now);
    tm* ptm = localtime(&tnow);

    t.year = ptm->tm_year + 1990;
    t.month = ptm->tm_mon + 1;
    t.day = ptm->tm_mday;
    t.hour = ptm->tm_hour;
    t.minute = ptm->tm_min;
    t.sec = ptm->tm_sec;
    t.ms = static_cast<int>(milliseconds.count());

    return t;
}

// ??
timestamp add(const timestamp& t, int ms)
{
    // compute new normalized timestamp by adding given ms count to t
}

3 Ответов

Рейтинг:
24

Jochen Arndt

Для упрощения вычислений я бы использовал структуру, которая содержит не отдельные поля, а одно или два значения.

Если вы хотите поддерживать только Windows, вы можете использовать Структура FILETIME (Windows)[^].

В качестве альтернативы и для общей поддержки ОС используйте временная структура (Windows)[^]. Здесь просто добавьте члены и когда добавление tv_usecs переполнение (>= 1E6), инкремент tv_sec и вычесть из 1E6 tv_usec.

Для обеих структур существуют функции преобразования в другие форматы времени, так что вы можете получить доступ к отдельным полям даты и времени. Преимущество timeval структура заключается в том, что у вас есть прямой доступ к полю доли секунды, когда преобразованный формат его не поддерживает.

[РЕДАКТИРОВАТЬ]
Если вы все еще хотите использовать свою структуру, напишите функции преобразования в одну из вышеупомянутых структур и используйте их для выполнения вычисления.

Обратите также внимание, что ваша структура очень похожа на Структура SYSTEMTIME (Windows)[^]. Если вы используете это, то существуют существующие функции преобразования в и из FILETIME.
[/РЕДАКТИРОВАТЬ]

[EDIT2]
Непроверенные примеры с нуля:

timeval add(const timeval& tv, int ms)
{
    timeval tv_res = { ms / 1000, 1000 * (ms % 1000)};
    tv_res.tv_sec += tv.tv_sec;
    tv_res.tv_usec += tv.tv_usec;
    if (tv_res.tv_usec >= 1000000)
    {
        tv_res.tv_sec++;
        tv_res.tv_usec -= 1000000;
    }
    return tv_res;
}

timestamp add(const timestamp& t, int ms)
{
    return TimeValToTimeStamp(add(TimeStampToTimeVal(t), ms));
}
Все, что вам сейчас нужно, - это функции преобразования (TimeValToTimeStamp() , оставленные в качестве упражнения):
timeval TimeStampToTimeVal(const timestamp& t)
{
    struct tm tmt = { 0 };
    tmt.tm_year = t.year;
    tmt.tm_mon = t.month;
    tmt.tm_mday = t.day;
    tmt.tm_hour = t.hour;
    tmt.tm_min = t.minute;
    tmt.tm_sec = t.sec;
    timeval tv;
    tv.sec = (long)mktime(&tmt);
    tv.usec = t.ms * 1000;
    return tv;
}
[/EDIT2]


11917640 Member

mktime был функцией, которую я искал. Это позволяет вернуться от человекочитаемой временной метки обратно к компьютерному времени. Спасибо за эту подсказку.

Рейтинг:
2

KarstenK

Чем вам это нужно Функции времени с высоким разрешением для окон. Обратите внимание на такие детали, как разрешение, тип данных и их размер.


Рейтинг:
1

CPallini

Я бы

  • Выбросьте это get_local_date функция.
  • Делать time_point_to_timestamp функция.
  • Делать timestamp_to_timepoint функция.
  • Реализуйте добавление с помощью вышеперечисленных функций и time_point::operator+=.


11917640 Member

Именно, timestamp_to_timepoint-это моя настоящая проблема.