How can I write a C++ function which takes a long long value representing a VMS timestamp and returns the corresponding time_t value, assuming the conversion yields a valid time_t? (I'll be parsing binary data sent over network on a commodity CentOS server, if that makes any differences.)
I've had a look into a document titled "Why Is Wednesday November 17, 1858 The Base Time For VAX/VMS" but I don't think I can write a correct implementation without testing with actual data which I don't have at hand right now, unfortunately.
If I'm not mistaken, it should be a simple arithmetic in this form:
time_t vmsTimeToTimeT(long long v) {
return v/10'000'000 - OFFSET;
}
Could somebody tell me what value to put into OFFSET ?
Things I'm concerned about:
- I don't want to be bitten by my local timezone
- I don't want to be bitten by the 0.5 thing (afternoon vs midnight) in the definition of modified Julian date (though it should be helping me here; modified Julian epoch and Unix Epoch should differ by a multiple of 24 hours thanks to the definition)
I tried to compute it by myself with the help from Boost.DateTime, only to get a mysterious negative value...
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
I used Boost 1.60 for it:
The current implementation supports dates in the range 1400-Jan-01 to 9999-Dec-31.
Update
Crap, sizeof(total_seconds()) was 4, dispite what the document says
So I got 3506716800 from
auto diff = y - x;
std::cout << diff.ticks() / diff.ticks_per_second() << std::endl;
which doesn't look too wrong but... who can assure this is really correct?
Wow, you guys make it all appear to be so difficult with libraries and all. So you read up on November-17 1858 and found out that VMS stores the time as 100nS 'clunks' since that date. Right?
Unix times are Seconds (or microseconds) since 1-jan-1970. Right?
So all you need to do is to subtract the OpenVMS time value 'offset' for 1-jan-1970 from the reported OpenVMS times ad divide by 10,000,000 (seconds) or 10 (microseconds). You only need to find that value once using a trivial OpenVMS program. Below I did not even use a dedicated program, just used the OpenVMS interactive debugger running a random executable program:
So there is you offset, both in HEX and DECIMAL to use as you see fit.
In the simplest form you pre-divide the incoming OpenVMS time by 10,000,000 and subtract 3506716800 (decimal) to get Epoch seconds. Be sure to keep the math, including the subtract to long-long int's
hth, Hein.