File::Stat#mtime
で取得できるファイルの最終更新日時だが、この精度(桁)は実装依存らしく、公式の Ruby では秒単位でしか取得できないものの、JRuby ではミリ秒単位で取得できた。しかし公式実装でもミリ秒単位で取得したいので、Win32 API の力を借りてみることにした。
require 'Win32API' GENERIC_READ = 0x80000000 OPEN_EXISTING = 3 file = 'E:/o2on/dat/2ch.net/software/1180/1180450101.dat' create_file = Win32API.new('kernel32', 'CreateFile', 'PIIIIII', 'I') get_file_time = Win32API.new('kernel32', 'GetFileTime', 'IPPP', 'I') close_handle = Win32API.new('kernel32', 'CloseHandle', 'I', 'I') file_time_to_system_time = Win32API.new('kernel32', 'FileTimeToSystemTime', 'PP', 'I') # 構造体を返してもらう場所を確保 lp_last_write_time = "\0" * 4 * 2 # FILETIME = DWORD * 2 lp_system_time = "\0" * 2 * 8 # SYSTEMTIME = WORD * 8 h_file = create_file.call(file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0) get_file_time.call(h_file, nil, nil, lp_last_write_time) close_handle.call(h_file) file_time_to_system_time.call(lp_last_write_time, lp_system_time) year, mon, wday, day, hour, min, sec, msec = lp_system_time.unpack('S8') p Time.gm(year, mon, day, hour, min, sec, msec * 1000).to_f # => 1183297724.109 # 普通にやった場合 p File.stat(file).mtime.to_f # => 1183297724.0
こんな感じだが、速度的にはどうなんだろう。