为什么我在 Powershell 和 C# 之间得到不同的结果

Why do I get different results between Powershell and C#

我有一个将日期时间转换为 DOS 格式的方法

它最初是在 C# 中,但我已将其转换为 powershell。

相同的输入会产生两个 returns 不同的结果。 我正在努力寻找原因。

Powershell 方法

Function ConvertTo-DOSDate {
    Param(
        [DateTime]$dateTime

    )

    Process {
        Try {

            [int] $ret = (($dateTime.Year - 1980) -band 0x7F);
            $ret = ($ret -shl 4) + $dateTime.Month;
            $ret = ($ret -shl 5) + $dateTime.Day;
            $ret = ($ret -shl 5) + $dateTime.Hour;
            $ret = ($ret -shl 6) + $dateTime.Minute;
            $ret = ($ret -shl 5) + ($dateTime.Second / 2); # only 5 bits for second, so we only have a granularity of 2 sec.
            return  [uint32] $ret;

        }
        Catch {

            throw "Exception: $_"
        }
    }

}

C# 方法

  public static uint DateTimeToDosTime(DateTime dateTime)
        {
            // DateTime must be Convertible to DosTime:
            //#Debug.Assert(ValidZipDate_YearMin <= dateTime.Year && dateTime.Year <= ValidZipDate_YearMax);

            int ret = ((dateTime.Year - 1980) & 0x7F);
            ret = (ret << 4) + dateTime.Month;
            ret = (ret << 5) + dateTime.Day;
            ret = (ret << 5) + dateTime.Hour;
            ret = (ret << 6) + dateTime.Minute;
            ret = (ret << 5) + (dateTime.Second / 2); // only 5 bits for second, so we only have a granularity of 2 sec.
            return (uint)ret;
        }

在 powershell 控制台中我 运行:

Add-Type -Path "C:\temp\ClassLibrary1.dll"
$date = New-Object DateTime 2019, 08, 30, 20, 56, 43 
$powershellResult = ConvertTo-DOSDate -dateTime $date 
$CSharpResult = [TomLib.ZipHelper]::DateTimeToDosTime($date)

write-host "Input Date : $date"
Write-host "Powershell: $powershellResult"
write-host "C#: $CSharpResult"

然后输出

Input Date : 08/30/2019 20:56:43
Powershell: 1327408918
C#: 1327408917

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_arithmetic_operators?view=powershell-6 说:

DIVISION AND ROUNDING When the quotient of a division operation is an integer, PowerShell rounds the value to the nearest integer. When the value is .5, it rounds to the nearest even integer.

The following example shows the effect of rounding to the nearest even integer.

Expression  Result
[int]( 5 / 2 )  2
[int]( 7 / 2 )  4

Notice how 5/2 = 2.5 gets rounded to 2. But, 7/2 = 3.5 gets rounded to 4.

当 C# 在 int space 中进行除法时,它只是删除小数部分:

5/2 -> 2, 
7/2 -> 3

在 powershell 中,您的示例时间的秒分量为 43,因此 43/2 向上舍入为 22,最接近的偶数

在 C# 中 43/2 是 21

这会在您的结果中引入一个错误,因为在 C# 表单中您正在执行 ret+21 而在 powershell 表单中您是 $ret+22