在日期中DIFF .NET错误 [英] Error in Date Diff in .net

查看:123
本文介绍了在日期中DIFF .NET错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用下面的code段

I am using the following code snippet

lxDate= #1/1/1970#
GetUnixDate = CType(DateDiff("S", lxDate, pDate), Int32)

其中PDATE被输入的日期由用户以及它在格式 MM / DD / YYYY如第12/24 /到2014年# 这检索UNIX日期correctly.However在一个特定的机器的产量是秒比所要求的日期起计。 也就是说当在previous日期转换结果的Unix时间戳。 对于如星期六2004年12月18日23时59分59秒GMT恢复时所需的结果是
孙,2004年12月19日00:00:00 GMT

where pDate is the date entered by user and its in the format mm/dd/yyyy e.g. #12/24/2014# This retrieves unix date correctly.However on one particular machine the output is one sec less than the required date. That is the unix timestamp when converted results in the previous date. For e.g Sat, 18 Dec 2004 23:59:59 GMT is retrieved when the desired result is
Sun, 19 Dec 2004 00:00:00 GMT

推荐答案

是的,这在技术上是可行的。则DateDiff()使用Math.Round(),以产生从TimeSpan.TotalSeconds的返回值。浮点运算一样,是容易受到哪些改变FPU控制字在计算机上运行的行为不端code。两个设置在控制字会导致偏离情况的一个错误就是这样,precision设置和舍入模式。

Yes, this is technically possible. DateDiff() uses Math.Round() to produce the return value from TimeSpan.TotalSeconds. Floating point math like that is vulnerable to misbehaving code that runs on the machine which alters the FPU control word. Two settings in the control word can cause an off-by-one bug like this, the precision setting and the rounding mode.

有多种方法,例如code可以感染你的程序。通常制造麻烦的打印机驱动程序,一些惠普驱动程序已知有这个bug。或外壳扩展,他们得到加载到你的搭配,比方说,一个OpenFileDialog过程。更隐蔽的方式是DirectX的,它可以改变precision设置。一个版本的Microsoft ACE数据提供的已知搞砸了舍入模式。

There are various ways such code can infect your program. The usual troublemakers are a printer driver, some Hewlett Packard drivers are known to have this bug. Or a shell extension, they get loaded into your process with, say, an OpenFileDialog. More obscure ways are DirectX, it can alter the precision setting. A version of the Microsoft ACE data provider is known to screw up the rounding mode.

到现在为止,解决这个问题的最好办法是重新映像机器。 DLL可以是pretty的很难找到,如果你没有在机器上提供一个调试器。它可能会导致其他程序非常难以诊断的方式胡作非为。 这个帖子有调试技巧,如果你有一个调试器。

By far the best way to tackle this problem is to re-image the machine. The DLL can be pretty hard to find if you don't have a debugger available on the machine. And it can cause other programs to misbehave in very hard to diagnose ways. This post has debugging tips if you do have a debugger.

但你可能只想得到错误关闭你的盘子。您可以通过避免浮点运算与此code这样做,把它放在一个模块:

But you probably just want to get the bug off your plate. You can do so by avoiding floating point math with this code, put it in a Module:

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


这说明了此问题的一个示例程序:


A sample program that demonstrates this problem:

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。然而,正是在哪里把该呼叫你有什么要搞清楚。

Which gives you another workaround, you could use SetFpuRoundingMode(RoundingMode.Near) to restore the FPU. Where exactly to put that call is however what you'd have to figure out.

这篇关于在日期中DIFF .NET错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆