Как преобразовать в современном С++ двойник в дату и время

Как преобразовать в современном C++ (C++11/14/17) двойник в дату и время, используя date.h, когда при экспорте рабочего листа Excel в виде файла CSV был сгенерирован дубликат?

Например, дата и время в Excel:

21/08/2017 11:54

был преобразован Excel в файл CSV как двойной:

42968.4958333333

Спасибо.

EDIT от 07.11.2019: Этот вопрос касается использования date.h библиотека. Другие вопросы, указанные как «возможные дубликаты», не требуют использования этой библиотеки (см. также комментарий ниже автора библиотеки date.h)


person stegua    schedule 01.10.2017    source источник
comment
В зависимости от того, как Excel решит преобразовать данные в двойные, было бы намного проще помочь вам, если бы вы могли это предоставить.   -  person Borgleader    schedule 01.10.2017
comment
Спасибо за ваш комментарий. Однако число, указанное в примере, является результатом преобразования Excel. Я понятия не имею, как excel преобразовать это число, иначе я бы знал ответ на свой вопрос.   -  person stegua    schedule 01.10.2017
comment
@Borgleader Я просто редактирую свой вопрос, чтобы попытаться прояснить его.   -  person stegua    schedule 01.10.2017
comment
stackoverflow.com/a/5023663/214671   -  person Matteo Italia    schedule 01.10.2017
comment
Google поможет вам найти документацию   -  person Dúthomhas    schedule 01.10.2017
comment
Если вы используете MFC/ATL, есть очень удобный класс COleDateTime у которого есть конструктор, который принимает double в этом формате.   -  person alain    schedule 02.10.2017
comment
pastebin.com/XCmUzfuM Я думаю... std::chrono все еще немного нецивилизованно по сравнению с DateTime классами в других языках, таких как Java и С# и так далее..   -  person Brandon    schedule 02.10.2017
comment
Этот вопрос не может быть дубликатом преобразования даты и времени, потому что этот вопрос спрашивает, как использовать date.h. Эта библиотека даже не существовала, когда был задан другой вопрос. Другой вопрос также не был обновлен, чтобы спросить об этой новой библиотеке.   -  person Howard Hinnant    schedule 11.07.2019


Ответы (1)


Используя date.h, это может выглядеть так:

#include "date/date.h"
#include <iostream>

std::chrono::system_clock::time_point
to_chrono_time_point(double d)
{
    using namespace std::chrono;
    using namespace date;
    using ddays = duration<double, days::period>;
    return sys_days{December/30/1899} + round<system_clock::duration>(ddays{d});
}

int
main()
{
    using date::operator<<;
    std::cout << to_chrono_time_point(42968.495833333333333333333) << '\n';
}

который выводит:

2017-08-21 11:54:00.000000

Это определение предполагает, что ваше сопоставление от 42968.4958333333 до 21/08/2017 11:54 верно. Я вижу в другом месте, что эпоха должна быть 1899-12-31, а не 1899-12-30. В любом случае, как только будет найдена правильная эпоха, именно так можно будет выполнить вычисление.

А, https://en.wikipedia.org/wiki/Leap_year_bug объясняет -одна ошибка. Авторы Excel намеренно считали 1900 год високосным в целях обратной совместимости с Lotus 1-2-3.

Этот вывод был сгенерирован в macOS, где system_clock::duration равно microseconds. Вывод будет немного отличаться на других платформах, где system_clock::duration имеет другие единицы измерения.

Примечание: в этом диапазоне точность 64-битного IEEE double грубее, чем nanoseconds, но лучше, чем microseconds (порядка половины microsecond).

person Howard Hinnant    schedule 01.10.2017
comment
Говард: еще раз спасибо за ваш ответ. Я очень ценю поддержку вашей библиотеки date.h. - person stegua; 11.07.2019