powershell 在对Invoke-Restmethod的响应进行反序列化后,禁用到UTC时区的转换

kmbjn2e3  于 2022-11-10  发布在  Shell
关注(0)|答案(2)|浏览(128)

我使用Invoke-RestMethod从rest API获取数据。响应的属性之一是日期。当使用 Postman 或其他工具获取数据时,会正确返回日期,但当我使用PowerShell(5.1.19041.906版)及其Invoke-RestMethod时,如下所示:

$response = Invoke-RestMethod -Method Get -Uri $url -Headers $requestHeaders

Date属性中的所有值都会自动转换为UTC。有什么办法可以停用这个变速箱吗?我需要API返回的原始值。

ulydmbyx

ulydmbyx1#

当获得JSON响应时,Invoke-RestMethod会自动将其解析为[pscustomobject]图形;从某种意义上说,它具有ConvertFrom-Json内置的
ConvertFrom-Json能够识别输入JSON中日期的字符串表示形式时,它会将它们转换为[datetime]示例。

Windows PowerShell(V5.1,最新最终版本)和PowerShell(Core)7.2中,您无法控制构造什么样的[datetime]示例**,这反映在它们的.Kind property上:

  • Windows PowerShell**中,需要自定义日期字符串格式(例如"\/Date(1633984531266)\/"),您不可避免地会得到Utc示例。
  • PowerShell(Core)7+中,额外识别属于ISO 8601日期-时间字符串的字符串值(变体)(例如"2021-10-11T13:27:12.3318432-04:00"),.Kind值取决于字符串值的细节
  • 如果字符串以Z结尾,表示UTC,则得到一个Utc示例。
  • 如果字符串以UTCOffset结尾,例如-04:00,则会得到Local示例(即使偏移量为00:00)
  • 否则得到Unspecified示例。

虽然Windows PowerShell不会有新的功能,但*PowerShell(Core)*还是有希望的:**GitHub issue #13598建议在ConvertFrom-Json**中增加一个-DateTimeKind参数,以便显式请求感兴趣的类型,并交替构造[datetimeoffset]示例,这是更好的选择。

解决方法

  • 注意:如果您需要访问原始字符串值,完全按照定义,下面的解决方案将不起作用。您必须检索原始JSON文本并执行您自己的解析,使用Invoke-WebRequest和响应的.Content属性,如Mathias R. Jessen所示。

以下代码片段**遍历从Invoke-RestMethod返回的[pscustomobject]图,并显式将遇到的任何[datetime]示例转换为Local示例就地(Unspecified示例被视为Local):


# Call Invoke-RestMethod to retrieve and parse a web service's JSON response.

$fromJson = Invoke-RestMethod ... 

# Convert any [datetime] instances in the object graph that aren't already

# local dates (whose .Kind value isn't already 'Local') to local ones.

& {
  # Helper script block that walks the object graph.
  $sb = {
    foreach ($el in $args[0]) { # iterate over elements (if an array)
      foreach ($prop in $el.psobject.Properties) {
        # iterate over properties
        if ($dt = $prop.Value -as [datetime]) {
          switch ($dt.Kind) {
            'Utc' { $prop.Value = $dt.ToLocalTime() }
            # Note: calling .ToLocalTime() is not an option, because it interprets
            #       an 'Unspecified' [datetime] as UTC.
            'Unspecified' { $prop.Value = [datetime]::new($dt.Ticks, 'Local') }
          }
        }
        elseif ($prop.Value -is [Array] -or $prop.Value -is [System.Management.Automation.PSCustomObject]) { 
          & $sb $prop.Value # recurse
        }
      }
    }
  }
  # Start walking.
  & $sb $args[0]
} $fromJson

# Output the transformed-in-place object graph

# that now contains only Local [datetime] instances.

$fromJson
6tqwzwtp

6tqwzwtp2#

$response = Invoke-RestMethod -Method Get -Uri $url -Headers $requestHeaders

$changeddate = $response.fields.'System.ChangedDate'

$datetime  = ([DateTime]$changeddate).ToLocalTime()

相关问题