Как преобразовать long в строку, не имея научной нотации - PullRequest
0 голосов
/ 04 октября 2018

У меня есть скрипт 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

Как избежать этого преобразования?

Ответы [ 3 ]

0 голосов
/ 04 октября 2018

Вы можете явно указать $currentTime переменный тип данных как [Decimal] вместо автоматически назначенного [Double].Вот так:

[Decimal]$currentTime = [math]::Round([double](get-date -uformat %s ((get-date).AddMinutes(-5).ToUniversalTime()))*1000)
0 голосов
/ 04 октября 2018

Я использую эту маленькую функцию, чтобы получить текущую дату и время как метку времени 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"
0 голосов
/ 04 октября 2018

tl; dr :

Чтобы обойти проблему с форматированием чисел, зависящим от культуры, используйте замена строки в результате 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 % выводит string представление метки времени Unix
  • и использует чувствительное к культуре форматирование для базового числа с плавающей точкой [1] , что означает, что в некоторыхв культурах вы получите строку, например '1538651788,87456' (, в качестве десятичной метки), а не '1538651788.87456' в качестве выходного.

В отличие от этого, при преобразовании PowerShell всегда используется инвариант культура, который только распознает . как десятичную метку - и игнорирует ,, который считается символом группировки тысяч.

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

Поскольку десятичная дробьМетка была проигнорирована, и есть 5 десятичных знаков, в этом случае результирующее число слишком велико в 10 000 раз (хотя учтите, что число десятичных знаков может варьироваться, поскольку завершающие нули не отображаются).

Если затем умножить это результатt с 1000, вы получите такое большое число, что PowerShell по умолчанию будет представлять его строковое представление в научном формате:

PS> [double] '1538651788,87456' * 1000
1.53865178887456E+17 # !! scientific notation.

[1] Дополнительное чтение: Get-Date -UFormat %sпроблемы в Windows PowerShell и PowerShell Core:

  • Временные метки Unix целые , поэтому Get-Date -UFormat %s не должно возвращать число с плавающей запятой для началас.Эта проблема была исправлена ​​в PowerShell Core .

  • Отметки времени Unix выражены в UTC, но Windows PowerShell возвращает правильное значение, только если вы явно передаетеUTC [datetime] экземпляр .Эта проблема была исправлена ​​в PowerShell Core .

    • Например, чтобы получить метку времени Unix текущего времени в Windows PowerShell, используя
      Get-Date -UFormat %s - not достаточно;вместо этого используйте Get-Date -UFormat %s ([datetime]::UtcNow).

Вкратце: проблема этого вопроса не возникла бы в PowerShell Core , потому что строкапредставления целых чисел не чувствительны к культуре;Кроме того, отпадает необходимость округления, равно как и необходимость преобразования входной даты в UTC, так что решение PowerShell Core упрощается до:

# PowerShell *Core* only
[double](get-date -uformat %s ((get-date).AddMinutes(-5))) * 1000
...