如何在不使用科学记数法的情况下将long转换为字符串

时间:2018-10-04 14:42:49

标签: powershell unix-timestamp

我有一个Powershell脚本,它可以获取当前时间并将其转换为Unix Timestamp。我想将此值用作字符串参数来发出HTTP请求:

$currentTime = [math]::Round([double](get-date -uformat %s ((get-date).AddMinutes(-5).ToUniversalTime()))*1000)

Invoke-RestMethod -Method Delete -Uri "http://something?unmodifiedSince=$currentTime"

在某些Windows机器上,它可以正常工作,但在其他(不同的Region设置?)上,我将当前时间转换为科学计数法。例如

http://something?unmodifiedSince=1.53835531189786E+17

如何避免这种转换?

3 个答案:

答案 0 :(得分:1)

tl;博士

使用区域性特定的数字格式解决此问题,请在Get-Date -UFormat结果上使用字符串替换以确保小数点分隔符为. ,这是[double]强制转换所要求的:

[math]::Round([double] (
  (get-date -uformat %s ((get-date).AddMinutes(-5).ToUniversalTime())) -replace
    '[^\d]', '.') * 1000
 )

-replace '[^\d]', '.'替换非数字字符。与.,以及唯一的非数字字符。在Get-Date -UFormat %s的输出中,是区域性特定的小数点。


实际上,您的问题源于以下事实:

  • Get-Date -UFormat %输出Unix时间戳的 string 表示形式
  • 并对基础浮点数 [1] 使用 culture-sensitive 格式,这意味着在某些文化中,您将获得诸如{{ 1}}('1538651788,87456'作为小数点)而不是,作为输出。

相比之下,PowerShell的强制转换始终使用不变文化,其中'1538651788.87456'识别为小数点-并忽略.,这被认为是上千个分组的字符。

,

因为忽略了小数点标记并且有5个小数位,所以在这种情况下,结果数太大了10,000倍(尽管请注意,由于不显示尾随零,所以小数位数可能会有所不同)

如果将结果乘以1000,则会得到一个很大的数字,因此PowerShell会将其字符串表示形式默认为您经历过的科学格式:

PS> [double] '1538651788,87456'
153865178887456  # !! , was IGNORED

[1]可选阅读:Windows PowerShell与PowerShell Core中的PS> [double] '1538651788,87456' * 1000 1.53865178887456E+17 # !! scientific notation. 问题:

  • Unix时间戳是 integers ,因此Get-Date -UFormat %s不应以浮点数开头。此问题已在PowerShell Core 中得到纠正。

  • Unix时间戳以UTC表示,但是 Windows PowerShell仅在您显式传递UTC Get-Date -UFormat %s实例时才返回正确的值。在PowerShell Core 中,此问题已得到纠正。

    • 例如,使用以下命令在Windows PowerShell中获取当前时间的Unix时间戳:
      [datetime] 还不够;改用Get-Date -UFormat %s

简而言之:在PowerShell Core 中不会出现此问题的问题,因为 integers 的字符串表示形式不区分文化;此外,舍入的需求消失了,将输入日期转换为UTC的需求也消失了,因此PowerShell Core解决方案简化为:

Get-Date -UFormat %s ([datetime]::UtcNow)

答案 1 :(得分:1)

我使用这个小函数来获取当前的日期和时间,作为Unix时间戳。 它返回一个int64,因此您可以毫不费力地将其添加到url中:

function Get-CurrentUnixTimeStamp {
    [DateTime]$epoch = New-Object System.DateTime 1970, 1, 1, 0, 0, 0, 0, Utc
    [TimeSpan]$diff  = (Get-Date).ToUniversalTime() - $epoch
    return [int64][Math]::Floor($diff.TotalSeconds)
}

$currentTime = Get-CurrentUnixTimeStamp
Invoke-RestMethod  -Method Delete -Uri "http://something?unmodifiedSince=$currentTime"

答案 2 :(得分:-1)

您可以将$currentTime变量数据类型显式表示为[Decimal],而不是自动分配的[Double]。像这样:

[Decimal]$currentTime = [math]::Round([double](get-date -uformat %s ((get-date).AddMinutes(-5).ToUniversalTime()))*1000)