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
的值是多少吗?
我关心的事情:
- 我不想被我当地的时区误导
- 我不想被修改后的 Julian 日期定义中的 0.5 事物(下午与午夜)所困扰(尽管它应该在这里帮助我;修改后的 Julian 纪元和 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
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
嗯,
海因.
我如何编写一个 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
的值是多少吗?
我关心的事情:
- 我不想被我当地的时区误导
- 我不想被修改后的 Julian 日期定义中的 0.5 事物(下午与午夜)所困扰(尽管它应该在这里帮助我;修改后的 Julian 纪元和 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
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
所以我从
得到了3506716800auto 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
嗯, 海因.