VMS 时间戳 POSIX time_t --- Boost.DateTime 错误?

VMS timestamp to POSIX time_t --- Boost.DateTime bug?

我如何编写一个 C++ 函数,该函数采用 long long 值表示 VMS 时间戳和 returns 相应的 time_t 值,假设转换产生有效的 time_t? (如果有任何不同,我将解析通过网络在商品 CentOS 服务器上发送的二进制数据。)

我查看了标题为 "Why Is Wednesday November 17, 1858 The Base Time For 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
y is after x

我用了Boost 1.60:

The current implementation supports dates in the range 1400-Jan-01 to 9999-Dec-31.

更新

废话,sizeof(total_seconds()) 是 4,尽管 what the document says

所以我从

得到了3506716800
auto diff = y - x;
std::cout << diff.ticks() / diff.ticks_per_second() << std::endl;

看起来并没有错,但是...谁能保证这是真的?

据此: https://www.timeanddate.com/date/durationresult.html?d1=17&m1=11&y1=1858&d2=1&m2=jan&y2=1970

您需要 40587 天,乘以 86400 秒,使 3506716800 作为计算中的偏移量。

使用这个 free open-source library<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

哇,你们让图书馆和其他一切看起来都那么困难。 因此,您在 1858 年 11 月 17 日阅读并发现 VMS 从该日期起将时间存储为 100nS 'clunks'。对吗?

Unix 时间是自 1970 年 1 月 1 日以来的秒(或微秒)。对吗?

因此,您需要做的就是从报告的 OpenVMS 时间中减去 1970 年 1 月 1 日的 OpenVMS 时间值 'offset' 除以 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(十进制)以获得 Epoch 秒。 一定要保留数学,包括减去 long-long int's

嗯, 海因.