Как я могу написать функцию 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
?
Вещи, которые меня беспокоят:
Я попытался вычислить его самостоятельно с помощью 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;
что не выглядит слишком неправильно, но … кто может заверить, что это действительно правильно?
Вау, вы, ребята, заставляете все это казаться таким сложным с библиотеками и все такое.
Итак, вы прочитали 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 (десятичное число), чтобы получить секунды эпохи.
Будьте уверены, чтобы сохранить математику, в том числе вычитать к длинным-длинным целым
НТН,
Хайн.
Согласно этому:
https://www.timeanddate.com/date/durationresult.html?d1=17&m1 = 11&y1 = 1858&d2 = 1&м2 = январь&у2 = 1970
Вы хотите, чтобы 40587 дней, время 86400 секунд, составляло 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