如何在没有科学记数法的情况下将 long 转换为字符串
How to convert a long to a string without having the scientific notation
我有一个 Powershell 脚本可以获取当前时间并将其转换为 Unix 时间戳。我想使用这个值作为字符串参数来发出 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 机器上它工作正常但在其他一些机器上(不同的区域设置?),我得到了用科学记数法转换的当前时间。例如
http://something?unmodifiedSince=1.53835531189786E+17
如何避免这种转换?
更新:
- 在 Windows PowerShell 5.1 和 PowerShell(核心)7+ (.NET Framework 4.6+) 现在可以使用 更简单的解决方案 ,使用
System.DateTimeOffset.ToUnixTimeSeconds
:
[datetimeoffset]::UtcNow.AddMinutes(-5).ToUnixTimeSeconds()
tl;dr:
要解决文化特定数字格式的问题,避免[double]
转换 和 使用 [double]::Parse()
,默认情况下以 culture-sensitive 方式解析:
[Math]::Round(
[double]::Parse(
(Get-Date -Uformat %s ((Get-Date).ToUniversalTime().AddMinutes(-5)))
) * 1000,
0,
'AwayFromZero'
)
AwayFromZero
中点舍入策略确保 .5
第二个值 总是 舍入,而默认 ToEven
策略会在某些情况下舍入 ,即每当数字的整数部分恰好是偶数时。
确实,您的问题源于以下事实:
Get-Date -UFormat %
输出 Unix 时间戳 的 字符串 表示
- 并对基础浮点数使用文化敏感格式[1],这意味着在某些文化中你将得到一个字符串,例如
'1538651788,87456'
(,
作为小数点)而不是 '1538651788.87456'
作为输出。
相比之下,PowerShell 的转换始终使用 不变 文化,仅 将 .
识别为小数点 - 并且忽略 ,
,它被认为是千位分组字符。
PS> [double] '1538651788,87456'
153865178887456 # !! , was IGNORED
由于忽略了小数点并且有 5 位小数,因此在本例中结果数字太大了 10,000 倍(但请注意,小数位数可能会有所不同,因为尾随零不是显示)。
如果您随后将该结果乘以 1000,您会得到一个非常大的数字,以至于 PowerShell 将其字符串表示默认为您所体验过的科学格式:
PS> [double] '1538651788,87456' * 1000
1.53865178887456E+17 # !! scientific notation.
[1] 可选阅读:Get-Date -UFormat %s
Windows PowerShell 与 PowerShell Core[= 中的问题106=] (v6+):
Unix 时间戳是 整数 ,因此 Get-Date -UFormat %s
不应该 return 以浮点数开头。此问题已在 PowerShell Core.
中得到纠正
Unix 时间戳以 UTC 表示,但 Windows PowerShell 只有 return 如果您显式传递 UTC [datetime]
才是正确的值实例。此问题已在 PowerShell Core (v6+) 中得到纠正。
- 例如,要在 Windows PowerShell 中获取当前时间的 Unix 时间戳,使用
Get-Date -UFormat %s
不够;请改用 Get-Date -UFormat %s ([datetime]::UtcNow)
。
简而言之:这个问题的 问题不会出现在 PowerShell Core 中,因为 整数的字符串表示 对文化不敏感;此外,不需要四舍五入,也不需要将输入日期转换为 UTC,因此 PowerShell Core 解决方案可以简化为:
# PowerShell *Core* only
1000 * (Get-Date -UFormat %s ((Get-Date).AddMinutes(-5)))
注意:从技术上讲,这 return 是一个 [double]
实例,但没有小数位;如果明确需要整数类型,请使用 [long] (...)
。
您可以将 $currentTime
变量数据类型显式指定为 [Decimal]
而不是自动分配 [Double]
。像这样:
[Decimal]$currentTime = [math]::Round([double](get-date -uformat %s ((get-date).AddMinutes(-5).ToUniversalTime()))*1000)
我使用这个小函数来获取当前日期和时间作为 Unix 时间戳。
它 returns 是一个 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"
我有一个 Powershell 脚本可以获取当前时间并将其转换为 Unix 时间戳。我想使用这个值作为字符串参数来发出 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 机器上它工作正常但在其他一些机器上(不同的区域设置?),我得到了用科学记数法转换的当前时间。例如
http://something?unmodifiedSince=1.53835531189786E+17
如何避免这种转换?
更新:
- 在 Windows PowerShell 5.1 和 PowerShell(核心)7+ (.NET Framework 4.6+) 现在可以使用 更简单的解决方案 ,使用
System.DateTimeOffset.ToUnixTimeSeconds
:
[datetimeoffset]::UtcNow.AddMinutes(-5).ToUnixTimeSeconds()
tl;dr:
要解决文化特定数字格式的问题,避免[double]
转换 和 使用 [double]::Parse()
,默认情况下以 culture-sensitive 方式解析:
[Math]::Round(
[double]::Parse(
(Get-Date -Uformat %s ((Get-Date).ToUniversalTime().AddMinutes(-5)))
) * 1000,
0,
'AwayFromZero'
)
AwayFromZero
中点舍入策略确保 .5
第二个值 总是 舍入,而默认 ToEven
策略会在某些情况下舍入 ,即每当数字的整数部分恰好是偶数时。
确实,您的问题源于以下事实:
Get-Date -UFormat %
输出 Unix 时间戳 的 字符串 表示
- 并对基础浮点数使用文化敏感格式[1],这意味着在某些文化中你将得到一个字符串,例如
'1538651788,87456'
(,
作为小数点)而不是'1538651788.87456'
作为输出。
相比之下,PowerShell 的转换始终使用 不变 文化,仅 将 .
识别为小数点 - 并且忽略 ,
,它被认为是千位分组字符。
PS> [double] '1538651788,87456'
153865178887456 # !! , was IGNORED
由于忽略了小数点并且有 5 位小数,因此在本例中结果数字太大了 10,000 倍(但请注意,小数位数可能会有所不同,因为尾随零不是显示)。
如果您随后将该结果乘以 1000,您会得到一个非常大的数字,以至于 PowerShell 将其字符串表示默认为您所体验过的科学格式:
PS> [double] '1538651788,87456' * 1000
1.53865178887456E+17 # !! scientific notation.
[1] 可选阅读:Get-Date -UFormat %s
Windows PowerShell 与 PowerShell Core[= 中的问题106=] (v6+):
Unix 时间戳是 整数 ,因此
中得到纠正Get-Date -UFormat %s
不应该 return 以浮点数开头。此问题已在 PowerShell Core.Unix 时间戳以 UTC 表示,但 Windows PowerShell 只有 return 如果您显式传递 UTC
[datetime]
才是正确的值实例。此问题已在 PowerShell Core (v6+) 中得到纠正。- 例如,要在 Windows PowerShell 中获取当前时间的 Unix 时间戳,使用
Get-Date -UFormat %s
不够;请改用Get-Date -UFormat %s ([datetime]::UtcNow)
。
- 例如,要在 Windows PowerShell 中获取当前时间的 Unix 时间戳,使用
简而言之:这个问题的 问题不会出现在 PowerShell Core 中,因为 整数的字符串表示 对文化不敏感;此外,不需要四舍五入,也不需要将输入日期转换为 UTC,因此 PowerShell Core 解决方案可以简化为:
# PowerShell *Core* only
1000 * (Get-Date -UFormat %s ((Get-Date).AddMinutes(-5)))
注意:从技术上讲,这 return 是一个 [double]
实例,但没有小数位;如果明确需要整数类型,请使用 [long] (...)
。
您可以将 $currentTime
变量数据类型显式指定为 [Decimal]
而不是自动分配 [Double]
。像这样:
[Decimal]$currentTime = [math]::Round([double](get-date -uformat %s ((get-date).AddMinutes(-5).ToUniversalTime()))*1000)
我使用这个小函数来获取当前日期和时间作为 Unix 时间戳。 它 returns 是一个 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"