我正在使用以下代码段
lxDate= #1/1/1970#
GetUnixDate = CType(DateDiff("S", lxDate, pDate), Int32)
其中pDate是用户输入的日期及其格式
mm / dd / yyyy例如第12/24/2014年#
这会正确检索unix日期。但是在一台特定的机器上,输出比所需日期少一秒。
这是转换结果在上一个日期时的unix时间戳。
例如,星期六,2004年12月18日23:59:59当期望结果为
时,检索GMT
太阳,2004年12月19日00:00:00 GMT
答案 0 :(得分:2)
是的,这在技术上是可行的。 DateDiff()使用Math.Round()从TimeSpan.TotalSeconds生成返回值。像这样的浮点数学容易受到在改变FPU控制字的机器上运行的行为不端的代码的攻击。控制字中的两个设置可能导致像这样的一个错误,精度设置和舍入模式。
此类代码可以通过各种方式感染您的程序。通常的麻烦制造者是打印机驱动程序,一些Hewlett Packard驱动程序已知有此错误。或者是一个shell扩展,它们会被加载到你的进程中,比如一个OpenFileDialog。更晦涩的方式是DirectX,它可以改变精度设置。众所周知,Microsoft ACE数据提供程序的一个版本会搞砸舍入模式。
到目前为止,解决此问题的最佳方法是重新成像机器。如果您没有在计算机上安装调试器,则很难找到DLL。并且它可能导致其他程序以非常难以诊断的方式行为不端。如果你有调试器,This post会有调试提示。
但是你可能只是想把你的盘子弄掉。您可以通过使用此代码避免浮点数学运算来实现,将其放在模块中:
Public Function UnixTimestamp(ByVal dt As DateTime) As Integer
Dim span = dt.ToUniversalTime() - New DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
Return CInt(span.Ticks \ 10000000)
End Function
演示此问题的示例程序:
Imports System.Runtime.InteropServices
Module Module1
Sub Main()
SetFpuRoundingMode(RoundingMode.Down) '' or Chop
Dim lxDate = #1/1/1970#
Dim pDate = #12/24/2014#
Dim unix = CType(DateDiff("S", lxDate, pDate), Int32)
System.Diagnostics.Debug.Assert(unix = 1419379200)
End Sub
Enum RoundingMode
Near
Down
Up
Chop
End Enum
Sub SetFpuRoundingMode(mode As RoundingMode)
_controlfp(mode << 8, &H300)
End Sub
<DllImport("msvcrt.dll", CallingConvention:=CallingConvention.Cdecl)> _
Friend Function _controlfp(bits As Integer, mask As Integer) As Integer
End Function
End Module
这为您提供了另一种解决方法,您可以使用SetFpuRoundingMode(RoundingMode.Near)来恢复FPU。然而,确切地说那个电话就是你必须要弄清楚的。