Отметка времени VMS для POSIX time_t --- ошибка Boost.DateTime?
Как я могу написать функцию C++, которая принимает long long
значение, представляющее метку времени VMS, и возвращает соответствующий time_t
значение, при условии, что преобразование дает действительный time_t
? (Я буду анализировать двоичные данные, отправленные по сети на стандартный сервер CentOS, если это будет иметь какое-либо значение.)
Я заглянул в документ под названием "Почему среда, 17 ноября 1858 г., базовое время для VAX/VMS", но я не думаю, что смогу написать правильную реализацию без тестирования с фактическими данными, которых у меня нет рука прямо сейчас, к сожалению.
Если я не ошибаюсь, это должна быть простая арифметика в таком виде:
time_t vmsTimeToTimeT(long long v) {
return v/10'000'000 - OFFSET;
}
Может ли кто-нибудь сказать мне, какую ценность вкладывать в OFFSET
?
Вещи, которые меня беспокоят:
- Я не хочу быть укушенным моим местным часовым поясом
- Я не хочу быть укушенным 0,5 (днем против полуночи) в определении модифицированной юлианской даты (хотя это должно помочь мне здесь; модифицированная юлианская эпоха и эпоха Unix должны отличаться в 24 раза благодаря определение)
Я попытался вычислить его самостоятельно с помощью Boost.DateTime, только чтобы получить таинственное отрицательное значение...
int main() {
boost::posix_time::ptime x(
boost::gregorian::date(1858, boost::gregorian::Nov, 17),
boost::posix_time::time_duration(0, 0, 0) );
boost::posix_time::ptime y(
boost::gregorian::date(1970, boost::gregorian::Jan, 1),
boost::posix_time::time_duration(0, 0, 0) );
std::cout << (y - x).total_seconds() << std::endl;
std::cout << (y > x ? "y is after x" : "y is before x") << std::endl;
}
-788250496
у после х
Я использовал Boost 1.60 для этого:
Текущая реализация поддерживает даты в диапазоне от 1400-Jan-01 до 9999-Dec-31.
Обновить
Дерьмо, sizeof(total_seconds())
было 4, несмотря на то, что говорится в документе
Итак, я получил 3506716800 от
auto diff = y - x;
std::cout << diff.ticks() / diff.ticks_per_second() << std::endl;
что не выглядит слишком неправильно, но... кто может заверить, что это действительно правильно?
3 ответа
Вау, вы, ребята, заставляете все это казаться таким сложным с библиотеками и все такое Итак, вы прочитали 17 ноября 1858 года и обнаружили, что VMS хранит время как 100 нс "стуков" с этой даты. Правильно?
Время Unix - секунды (или микросекунды) с 1 января 1970 года. Правильно?
Таким образом, все, что вам нужно сделать, это вычесть значение смещения времени OpenVMS для 1 января 1970 года из отчетного времени деления времени OpenVMS на 10 000 000 (секунд) или 10 (микросекунд). Вам нужно найти это значение только один раз, используя тривиальную программу OpenVMS. Ниже я даже не использовал выделенную программу, просто использовал интерактивный отладчик OpenVMS, запускающий случайную исполняемую программу:
$ run tmp/debug
DBG> set rad hex
DBG> dep/date 10000 = "01-JAN-1970 00:00:00" ! Local time
DBG> examin/quad 10000
TMP\main: 007C95674C3DA5C0
DBG> examin/quad/dec 10000
TMP\main: 35067168005400000
Таким образом, вы можете использовать смещение, как в шестнадцатеричном, так и в десятичном формате, чтобы использовать его по своему усмотрению.
В простейшей форме вы предварительно делите входящее время OpenVMS на 10 000 000 и вычитаете 3506716800 (десятичное число), чтобы получить секунды эпохи. Будьте уверены, чтобы сохранить математику, в том числе вычитать к длинным-длинным целым
Хе, Хейн.
Используя эту бесплатную библиотеку с открытым исходным кодом, которая расширяет <chrono>
К календарным вычислениям я могу подтвердить вашу цифру смещения в секундах:
#include "chrono_io.h"
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
using namespace std;
seconds offset = sys_days{jan/1/1970} - sys_days{nov/17/1858};
cout << offset << '\n';
}
Выход:
3506716800s
Согласно этому: https://www.timeanddate.com/date/durationresult.html?d1=17&m1=11&y1=1858&d2=1&m2=jan&y2=1970
Вы хотите, чтобы 40587 дней, время 86400 секунд, составляло 3506716800 в качестве смещения в ваших расчетах.