在反序列化来自 Invoke-Restmethod 的响应后禁止转换为 UTC 时区
Disable conversion to UTC timezone after deserialization of a response from Invoke-Restmethod
我正在使用 Invoke-RestMethod 从 REST API 获取数据。响应中的属性之一是日期。当使用 Postman 或其他工具获取数据时,日期会正确返回,但当我使用 PowerShell(版本 5.1.19041.906)及其 Invoke-RestMethod 时,如下所示:
$response = Invoke-RestMethod -Method Get -Uri $url -Headers $requestHeaders
日期属性中的所有值都会自动转换为 UTC。有什么办法可以禁用这种转变吗?我需要从 API.
返回的原始值
$response = Invoke-RestMethod -Method Get -Uri $url -Headers $requestHeaders
$changeddate = $response.fields.'System.ChangedDate'
$datetime = ([DateTime]$changeddate).ToLocalTime()
Invoke-RestMethod
, when given a JSON response, automatically parses it into a [pscustomobject]
graph; in a manner of speaking, it has ConvertFrom-Json
内置。
当 ConvertFrom-Json
识别出输入 JSON 中日期的不变 字符串 表示形式时,它会将它们转换为 [datetime]
实例。
在 Windows PowerShell(v5.1,最新和最终版本)和从 PowerShell(核心)开始7.2,您无法控制 [datetime]
个实例中 种类 的构造,如它们的 .Kind
property 所示:
在Windows PowerShell中,需要自定义日期字符串格式(例如"\/Date(1633984531266)\/"
),你总是得到Utc
个实例。
在 PowerShell (Core) 7+ 中, 还识别字符串值(变体)ISO 8601 日期时间字符串 s(例如 "2021-10-11T13:27:12.3318432-04:00"
),.Kind
值取决于 字符串值的具体细节 :
- 如果字符串以
Z
结尾,表示 UTC,您将获得一个 Utc
实例。
- 如果字符串以 UTC offset 结尾,例如
-04:00
你得到一个 Local
实例(即使偏移值是 00:00
)
- 否则你会得到一个
Unspecified
实例。
虽然 Windows PowerShell 不会看到新功能,但 PowerShell(核心) 有希望:GitHub issue #13598建议在ConvertFrom-Json
中增加一个-DateTimeKind
参数,以允许显式请求兴趣的种类,并交替构造[datetimeoffset]
个实例, 哪个更可取。
解决方法:
- 注意:如果您需要访问完全按照定义的原始字符串值,则以下解决方案将不起作用。您必须使用
Invoke-WebRequest
and the response's .Content
property, as Mathias R. Jessen 注释检索原始 JSON 文本并执行您自己的解析。
以下代码段 遍历 [pscustomobject]
图,从 Invoke-RestMethod
返回并显式 转换任何 [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
我正在使用 Invoke-RestMethod 从 REST API 获取数据。响应中的属性之一是日期。当使用 Postman 或其他工具获取数据时,日期会正确返回,但当我使用 PowerShell(版本 5.1.19041.906)及其 Invoke-RestMethod 时,如下所示:
$response = Invoke-RestMethod -Method Get -Uri $url -Headers $requestHeaders
日期属性中的所有值都会自动转换为 UTC。有什么办法可以禁用这种转变吗?我需要从 API.
返回的原始值$response = Invoke-RestMethod -Method Get -Uri $url -Headers $requestHeaders
$changeddate = $response.fields.'System.ChangedDate'
$datetime = ([DateTime]$changeddate).ToLocalTime()
Invoke-RestMethod
, when given a JSON response, automatically parses it into a [pscustomobject]
graph; in a manner of speaking, it has ConvertFrom-Json
内置。
当 ConvertFrom-Json
识别出输入 JSON 中日期的不变 字符串 表示形式时,它会将它们转换为 [datetime]
实例。
在 Windows PowerShell(v5.1,最新和最终版本)和从 PowerShell(核心)开始7.2,您无法控制 [datetime]
个实例中 种类 的构造,如它们的 .Kind
property 所示:
在Windows PowerShell中,需要自定义日期字符串格式(例如
"\/Date(1633984531266)\/"
),你总是得到Utc
个实例。在 PowerShell (Core) 7+ 中, 还识别字符串值(变体)ISO 8601 日期时间字符串 s(例如
"2021-10-11T13:27:12.3318432-04:00"
),.Kind
值取决于 字符串值的具体细节 :- 如果字符串以
Z
结尾,表示 UTC,您将获得一个Utc
实例。 - 如果字符串以 UTC offset 结尾,例如
-04:00
你得到一个Local
实例(即使偏移值是00:00
) - 否则你会得到一个
Unspecified
实例。
- 如果字符串以
虽然 Windows PowerShell 不会看到新功能,但 PowerShell(核心) 有希望:GitHub issue #13598建议在ConvertFrom-Json
中增加一个-DateTimeKind
参数,以允许显式请求兴趣的种类,并交替构造[datetimeoffset]
个实例, 哪个更可取。
解决方法:
- 注意:如果您需要访问完全按照定义的原始字符串值,则以下解决方案将不起作用。您必须使用
Invoke-WebRequest
and the response's.Content
property, as Mathias R. Jessen 注释检索原始 JSON 文本并执行您自己的解析。
以下代码段 遍历 [pscustomobject]
图,从 Invoke-RestMethod
返回并显式 转换任何 [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