glwtta has asked for the wisdom of the Perl Monks concerning the following question:
Hello Monks,
Do any perl date modules handle Microsoft timestamps properly? The format for them is, I believe, the number of 100 nanosecond chunks since midnight Jan 1 1601.
I don't know enough about time handling (including various leap units) to trust my own conversion.
What's the proper way to handle one of these?
Thanks
Re: converting microsoft timestamps
by BrowserUk (Patriarch) on Jun 18, 2004 at 18:11 UTC
|
Assuming from your description that you are talking about FILETIME structs, you could do it like this.
#! perl -slw
use strict;
use Win32API::File qw[ FdGetOsFHandle ];
use Win32::API::Prototype;
ApiLink(
'kernel32',
'BOOL FileTimeToSystemTime(
LPFILETIME lpFileTime,
LPSYSTEMTIME lpSystemTime
)'
) or die $^E;
ApiLink(
'kernel32',
'BOOL GetFileTime(
HANDLE hFile,
LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime,
LPFILETIME lpLastWriteTime
)'
) or die $^E;
## Get an OSfilehandle for the curent script
my $osfh = FdGetOsFHandle( fileno( DATA ) ) or die $!;
## 3 x quadword buffers for the FILETIME structs
my( $ctime, $atime, $wtime ) = ( chr(0) x 8 ) x 3;
## Get them
GetFileTime( $osfh, $ctime, $atime, $wtime ) or die $^E;
## 8 word buffer for the SYSTEMTIME struct
my $systime = chr( 0 ) x 16;
for( $ctime, $atime, $wtime ) {
##Convert the FILETIMEs to SYTEMTIMEs
FileTimeToSystemTime( $_, $systime ) or die $^E;
printf "Year: %4d Month: %2d DOW: %1d Day: %2d Hour: %2d Minutes:
+%2d Seconds: %2d Milliseconds: %3d\n",
unpack 'v8', $systime;
}
__DATA__
P:\test>368002
Year: 2004 Month: 6 DOW: 5 Day: 18 Hour: 17 Minutes: 47 Seconds: 5 M
+illiseconds: 283
Year: 2004 Month: 6 DOW: 5 Day: 18 Hour: 18 Minutes: 7 Seconds: 38 M
+illiseconds: 689
Year: 2004 Month: 6 DOW: 5 Day: 18 Hour: 18 Minutes: 7 Seconds: 37 M
+illiseconds: 1
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
| [reply] [d/l] |
|
That seems reasonable, except I am on UNIX, Win32 APIs really don't help much. Any pure perl solutions?Thanks
| [reply] |
|
#! perl -slw
use strict;
use Win32API::File qw[ FdGetOsFHandle ];
use Win32::API::Prototype;
ApiLink(
'kernel32',
'BOOL GetFileTime(
HANDLE hFile,
LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime,
LPFILETIME lpLastWriteTime
)'
) or die $^E;
my $osfh = FdGetOsFHandle( fileno( DATA ) ) or die $!;
my( $ctime, $atime, $wtime ) = ( chr(0) x 8 ) x 3;
GetFileTime( $osfh, $ctime, $atime, $wtime ) or die $^E;
## Ignore the stuf above,
## it's just a way of getting some FILETIMEs for testing.
sub msFiletimeToUnix{
my ( $lo, $hi ) = unpack 'V2', $_[ 0 ];
my $nanosecs = $hi * 2**32 + $lo;
return int( ($nanosecs - 116444736010000000) / 1E7 );
}
for( $ctime, $atime, $wtime ) {
print scalar localtime( msFiletimeToUnix( $_ ) );
}
__DATA__
P:\test>368002
Fri Jun 18 18:47:04 2004
Fri Jun 18 20:10:35 2004
Fri Jun 18 20:10:33 2004
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
| [reply] [d/l] |
Re: converting microsoft timestamps
by waswas-fng (Curate) on Jun 18, 2004 at 17:48 UTC
|
When you say "Microsoft timestamps" what are you referring to? they use many different formats in different applications and API's for example MS SQL Server uses one whereas IE cookies use another. Please be more specific.
| [reply] |
|
It's the one I described - apparently it's a FILETIME struct (as BrowserUk points out), the specific place I am getting them is ActiveDirectory fields for various account control functions.
| [reply] |
Re: converting microsoft timestamps
by jmcnamara (Monsignor) on Jun 18, 2004 at 23:09 UTC
|
Here is a method to decode the timestamp from a previous node:
#!/usr/bin/perl -wl
use strict;
use Date::Calc 'Add_Delta_DHMS';
my $vt_filetime = '126697423010137600';
# Disregard the 100 nanosecond units (but you could save them for
+later)
$vt_filetime = substr($vt_filetime, 0, 11);
my $days = int( $vt_filetime / (24*60*60) );
my $hours = int( ($vt_filetime % (24*60*60)) / (60*60) );
my $mins = int( ($vt_filetime % (60*60)) / 60 );
my $secs = $vt_filetime % 60 ;
my @date = Add_Delta_DHMS(1601, 1, 1, 0, 0, 0, $days, $hours, $min
+s, $secs);
# Format @date as you wish
print "@date";
__END__
Prints:
2002 6 28 12 51 41
--
John.
| [reply] [d/l] |
Re: converting microsoft timestamps
by rir (Vicar) on Jun 18, 2004 at 18:34 UTC
|
| [reply] [d/l] [select] |
|
|