Отметка времени 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 в качестве смещения в ваших расчетах.

Другие вопросы по тегам