I've appended a version that you might find more useful.
# Take a decoded quadword that's got a VMS time in it and convert it t +o epoch # seconds. VMS dates are a 63 bit count of units since Nov 17, 1858. ( +Units # are 100ns long), while unix dates are in seconds since Jan 1, 1970. +FWIW, # there are 3,506,716,800 seconds between VMS' base date and Unix/Perl +'s # base date. # # First parameter is a scalar with the integer value of the low 32 # bits, second parameter is the integer value with the high 32 # bits. You'd call it like: # # $time = quad_to_epoch(423828480, 9926120); # sub quad_to_epoch() { my ($low_long, $high_long, $VMS_based_time, $Unix_based_time); $low_long = int shift(@_); $high_long = int shift(@_); # VMS' time has lots of extra bits we don't care about. There are 10 +^7 # ticks per second, so we can toss all the sub-second bits. 10^7 == # 1000000 == 0x989680 == 100110001001011010000000. The low seven bit +s # are all zero, so we can shift everything to the right 7 bits then # divide by 78125. # # We play these games because of precision. A VMS date has 63 bits, +but # an integer only has 32. OTOH, a double has 53 bits. Which means if + we # shift the individual pieces by 7, we only have 3 bits we could los +e, # and only if one of the top three bits of the VMS date are ones. Th +is # won't happen until well after the year 3000, so I expect we're saf +e # for a while. # # First we shift the low longword right 7 bits and mask off the top +7 # (in case we sign extended) $low_long = ($low_long >> 7) & 0x01ffffff; # Find the low seven bits of our high longword and tack them on to t +he # top of our low word. As a result of these games, $low_long gets # morphed from an IV to an NV. The shift's 24 with a multiply by 2 # (instead of a shift by 25) to avoid shifting into the sign bit $low_long = $low_long + ((($high_long & 127) << 24) * 2); # Shift the high word down by seven bits (the ones we saved). No # masking's needed, as we know we can't sign extend. (VMS absolute # times are guaranteed to have the high bit clear) $high_long >>= 7; # Put 'em together $VMS_based_time = int((($high_long * 4294967296) + $low_long) / 7812 +5); $Unix_based_time = $VMS_based_time - 3_506_716_800; return $Unix_based_time; }
In reply to Re: Re: Re: Re: Unpack for VMS binary files
by Elian
in thread Unpack for VMS binary files
by maderman
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |