В свое время для алготрейдерских задач мне нужно было много оперировать датой и временем. Конечно, в С++ и Си есть библиотеки для работы с датой и временем. Но мне захотелось сделать свой велосипед, который бы мог легко и удобно превращать строковое представление времени в метку времени, менять часовой пояс, получать время UTC компьютера, преобразовывать метку времени в стандартный формат даты и времени и обратно и т.д. и т.п. Одним словом, целый спектр задач.
В итоге я сделал библиотеку
xtime (ну, громко сказано «библиотека», это всего лишь два файла
.cpp и
.hpp). Для хранения и преобразования меток времени используется тип данных
uint64 либо
double, поэтому у данной библиотеки нет
проблемы 2038 года.
Используемые типы данных:
- timestamp_t — тип длиной 64 бита для хранения метки времени.
- ftimestamp_t - тип с плавающей точкой длиной 64 бита для хранения метки времени с дробной частью секунд.
- oadate_t - тип с плавающей точкой длиной 64 бита для хранения даты автоматизации (OADate)
Что умеет библиотека, покажу на примерах.
Нужно получить время UTC на компьютере вне зависимости от текущего часового пояса? Без проблем:
#include <iostream>
#include <xtime.hpp>
uint32_t main() {
std::cout << "Hello world!" << std::endl;
// Получаем метку времени компьютера
xtime::timestamp_t t = get_timestamp();
// выводим в человекочитабельном формате
std::cout << xtime::get_str_date_time(t) << std::endl;
/* но можно сразу строку получить
* В строке время будет представлено как
* в примере (24.05.2018 00:00:00)
*/
std::string str = get_str_date_time();
/* а может нужен формат OLE Automation Date
*(Дата автоматизации OLE)
*/
std::cout << "oadate " << xtime::get_oadate() << endl;
return 0;
}
Хочется иметь стандартное представление времени (часы, минуты и пр.) в виде класса с соответствующими объектами? Без проблем:
using namespace xtime;
// Инициализируем датой 24.05.2018
DateTime iTime(24,5,2018);
// Второй вариант инициализации с указанием времени
iTime = DateTime(24,5,2018, 0, 0, 0);
// iTime = DateTime(24,5,2018);
// Третий вариант инициализации (Инициализация с указанием unix-времени в формате ISO)
// iTime = DateTime("2013-12-06T15:23:01+00:00");
// Или инициализируем Unix epoch или Unix time или POSIX time или Unix timestamp
xtime::timestamp_t unix_epoch = 1527120000;
iTime.set_timestamp(unix_epoch);
// Переменные класса DateTime
iTime.day = 24; // день
iTime.month = 5; // месяц
iTime.year = 2018 // год
iTime.hour = 0; // час
iTime.minutes = 0; // минуты
iTime.seconds = 0; // секунды
// Получить Unix epoch или Unix time или POSIX time или Unix timestamp
unix_epoch = iTime.get_timestamp();
// Вывести время и дату на экран
iTime.print();
// Получить дату и время в виде строки
std::string str = iTime.get_str_date_time(); // В строке будет 24.05.2018 00:00:00
Конечно же можно получать день недели, день года, количество дней в месяце, метку времени начала или конца дня, час, минуту от метки времени и многое другое.
К примеру,
получить день недели:
using namespace xtime;
// Получить номер дня недели
uint32_t wday = get_weekday(24,5,2018);
if(wday == SUN) std::cout << "SUN" << std::endl; // Если функция вернула 0 или Воскресенье
else if(wday == MON) std::cout << "MON" << std::endl; // Если функция вернула 1 или Понедельник
else if(wday == TUS) std::cout << "TUS" << std::endl;
else if(wday == WED) std::cout << "WED" << std::endl;
else if(wday == FRI) std::cout << "FRI" << std::endl;
else if(wday == SAT) std::cout << "SAT" << std::endl;
xtime::timestamp_t unix_epoch = 1527120000;
// Второй вариант функции для определения дня недели
wday = get_weekday(unix_epoch);
// Получить день недели через метод класса DateTime
DateTime iTime(24,5,2018);
wday = iTime.get_weekday();
Конвертировать строку в формате ISO в данные класса DateTime:using namespace xtime;
DateTime iTime;
std::string strISOformattedUTCdatetime = "2013-12-06T15:23:01+00:00";
if(convert_iso(strISOformattedUTCdatetime, iTime) == true) {
iTime.print();
}
Перевод времени CET во время GMT и обратно с учетом перехода на зимнее время
using namespace xtime;
// получаем время GMT для примера
DateTime startTime(20,3,2018);
xtime::timestamp_t startGMT = startTime.get_timestamp();
// переводим время GMT во время CET
DateTime realCET(convert_gmt_to_cet(startGMT));
realCET.print();
// переводим время CET во время GMT
DateTime realGMT(convert_cet_to_gmt(realCET.get_timestamp()));
realGMT.print();
А еще можно получить синхронизированное UTC время
#include <iostream>
#include <xtime_sync.hpp>
uint32_t main() {
std::cout << "Hello world!" << std::endl;
// класс для получения синхронизированного времени
xtime::TimeSync iTimeSync;
while(!iTimeSync.is_time_sync()) {
std::this_thread::sleep_for(std::chrono::seconds(1));
};
double last_utc = iTimeSync.get_ftimestamp();
while(true) {
double real_utc = iTimeSync.get_ftimestamp();
double pc_utc = xtime::get_ftimestamp();
if(real_utc - last_utc > 0.1) {
std::cout
<< "accuracy: "
<< iTimeSync.get_accuracy()
<< " sync utc: " << xtime::get_str_time_ms(real_utc)
<< " pc utc: " << xtime::get_str_time_ms(pc_utc) << "\r";
last_utc = real_utc;
}
};
return 0;
}
В последнем случае вам нужно будет подключать в проект библиотеку
curl.
Репозиторий с кодом
у тебя по сути еще одна библиотека для работы с датами с привязкой к C++
std, boost ::chrono
надо учится эффективно использовать чужие велосипеды, иначе легко завязнуть в своих
Андрей К, я про _быстро_ мало знаю.
целочисленные boost, std ::chrono, boost::posix_time - медленные?
есть много алго, где время взятия меток очень ощутимо для самого алго. Вот именно тут, лучше делать кастом.
кастом — это личное, свои требования, окружение, история. нет смысла обсуждать исходя из общих представлений.
Чисто для дальнейшего опыта. Quik уже работает с микросеками. Сама биржа наша уже работает с наносеками. Текущему коду есть куда стремиться. Так как tm не умеет ни микросеки, ни наносеки =).
Синхрон тоже. Проткол ntp умеет синхронить до микросек. ptp до наносек. Но наша биржа ptp никак не хочет вводить
Настоящий русский программист