Rog*_*est 12 .net vb.net datetime vba
我正在开发一个程序来记录文件中的日期元数据,例如创建时间,上次修改时间等.该程序的旧版本是用VBA编写的,并且执行如下操作:
Public Function GetFileLastAccessTime(ByVal FilePath As String) As Date
Dim fso As New Scripting.FileSystemObject
Dim f As Scripting.File
Set f = fso.GetFile(FilePath)
GetFileLastAccessTime = f.DateLastAccessed
End Function
Run Code Online (Sandbox Code Playgroud)
有问题的文件的输出:
?getfilelastaccesstime("SomePath")
7/30/2010 2:16:07 PM
Run Code Online (Sandbox Code Playgroud)
这是我从Windows Exploder中的文件属性获得的值.幸福.
我将此功能移植到VB.Net应用程序.新代码:
Public Function GetLastAccessTime(ByVal FilePath As String) As Date
Return IO.File.GetLastAccessTime(FilePath)
End Function
Run Code Online (Sandbox Code Playgroud)
简单本身.输出:
?GetLastAccessTime("SomePath")
#7/30/2010 3:16:07 PM#
Run Code Online (Sandbox Code Playgroud)
一小时后.
这两个函数都在同一台机器上运行,检查同一个文件.我也尝试使用具有相同结果的IO.FileInfo类.我已经检查了数千个文件,它们一小时都关闭了.创建时间和上次修改时间的其他日期属性也会减少一个小时.
救命!
我忘了在原帖中提到,计算机的时区是CST,夏令时目前没有生效.
我在Windows 7 64位和Windows XP 32位上重现了这个问题.
谢谢.
1/6/2011更新:
感谢所有建议尝试使用适当的时区偏移从UTC计算所需日期的人.在这个时候,我决定不值得这样做的风险.对于这个特定的业务需求,更好地说日期值不是您所期望的那样,因为这就是API的工作方式.如果我试图"修复"这个,那么我拥有它,而我宁愿不.
只是为了踢,我尝试通过互操作使用好的旧Scripting.FileSystemObject.它提供了与Windows资源管理器一致的预期结果,与System.IO相比,性能损失约为5倍.如果事实证明我必须得到与Windows资源管理器相匹配的日期,我会咬紧牙关并走这条路.
我尝试的另一个实验是通过C#直接转到kernel32中的GetFileTime API函数:
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetFileTime(
IntPtr hFile,
ref FILETIME lpCreationTime,
ref FILETIME lpLastAccessTime,
ref FILETIME lpLastWriteTime
);
Run Code Online (Sandbox Code Playgroud)
这导致了System.IO完全相同的行为,从Windows资源管理器中消失了一个小时的时间.
再次感谢大家.
我可以在 XP/Win2k3/Vista 上使用 .NET 4.0 和 2.0/3.5 重现这个。
问题是 DST 与现在处于不同的状态,并且 .NET 处理这种差异的方式与 Explorer 和Scripting.FileSystemObject
.
(当 DST 与压缩文件时不同时,从 zip 文件中提取文件时,您会看到类似的问题。)
通过 Reflector,.NET 与非 .NET 代码路径不同的原因是IO.File
(和IO.FileInfo
) 中的所有三个本地日期戳都实现为获取 Utc 日期戳并应用.ToLocalTime
,它根据 DST 是否在本地发生来确定要添加的偏移量UTC 时间的时区。
我还检查了,通过将日期更改为去年的 7 月 1 日,创建一个文件并在返回当前日期(3 月 16 日)时查看时间戳(我在南澳大利亚,所以我们现在处于夏令时,并没有7月1日),和Windows(大概FileSystemObject
)代替添加DST NOW所以时间实际显示的变化。
所以,总而言之,.NET 更正确。
但是,如果您想要不正确但与资源管理器相同的日期,请使用:
Public Function GetLastAccessTime(ByVal FilePath As String) As Date
Return IO.File.GetLastAccessTimeUtc(FilePath) _
.Add(TimeZone.CurrentTimeZone.GetUtcOffset(Now))
End Function
Run Code Online (Sandbox Code Playgroud)
这已经在Raymond Chen 的博客上讨论过(这里的总结是:.NET 直觉上是正确的,但并不总是可逆的,而 Win32 是严格正确且可逆的)。
归档时间: |
|
查看次数: |
2288 次 |
最近记录: |