PowerShell中Get-Date的Date属性JSON转换偏移是否为Bug?
问题分析:PowerShell双向JSON转换中Date属性的异常时区偏移
这确实是PowerShell内置JSON序列化/反序列化工具的已知逻辑缺陷,根源在于ConvertTo-Json和ConvertFrom-Json对DateTime类型的时区处理不一致,在夏令时(CEST)时段的特定时间点会触发异常偏移。
问题本质
序列化阶段(ConvertTo-Json):
Get-Date | Select-Object *输出的Date属性是当日00:00:00的本地时间(比如CEST时区下的2024-04-19T00:00:00)。ConvertTo-Json会将这个DateTime转换为UTC时间戳:CEST的00:00对应UTC的前一天22:00,生成的时间戳为\/Date(1713477600000)\/,这一步是正确的。反序列化阶段(ConvertFrom-Json):
缺陷出在这里:ConvertFrom-Json错误地将UTC时间戳直接解析为本地时间,而不是先解析为UTC再转换回本地时区。- 当在CEST时区23点后执行时,原始
Date是当日00:00(如2024-04-19T00:00:00),对应的UTC时间戳是2024-04-18T22:00:00。ConvertFrom-Json把这个UTC时间当成本地时间,最终显示为2024-04-18T22:00:00——相对于当前执行时间(23点左右),正好偏移25小时。 - 午夜后执行时,原始
Date是当日00:00(如2024-04-20T00:00:00),对应UTC的2024-04-19T22:00:00。ConvertFrom-Json将其解析为本地时间后,显示为2024-04-19T22:00:00,与原始值的偏移正好等于CEST与UTC的时差(2小时),看起来“正常”,但本质还是错误的解析逻辑。
- 当在CEST时区23点后执行时,原始
临时解决方案
方案1:避免序列化Date属性
如果不需要Date属性,直接指定需要的字段,或者将日期转换为字符串格式:
# 只选择需要的属性,跳过Date Get-Date | Select-Object DateTime, Day, Month, Year | ConvertTo-Json | ConvertFrom-Json # 或者将日期转为字符串 Get-Date | Select-Object @{Name='Date'; Expression={$_.ToString('yyyy-MM-dd')}}, * -ExcludeProperty Date | ConvertTo-Json | ConvertFrom-Json
方案2:使用第三方JSON库(Newtonsoft.Json)
Newtonsoft.Json的时区处理更准确,需要先安装模块:
Install-Module -Name Newtonsoft.Json -Force
然后执行转换:
$dateObj = Get-Date | Select-Object -Property * $json = [Newtonsoft.Json.JsonConvert]::SerializeObject($dateObj) $deserialized = [Newtonsoft.Json.JsonConvert]::DeserializeObject($json, $dateObj.GetType()) # 此时Date属性会正确显示为本地时间的当日0点 $deserialized.Date
方案3:手动修正时区偏移
如果必须使用内置命令,反序列化后手动将UTC时间转换为本地时区:
$result = Get-Date | Select-Object -Property * | ConvertTo-Json | ConvertFrom-Json # 将解析后的UTC时间转换为本地时间 $result.Date = [DateTimeOffset]$result.Date | ConvertTo-LocalTime
说明
该问题属于PowerShell内置JSON处理器的长期存在的缺陷,在PowerShell官方仓库的Issue中有相关记录,目前尚未完全修复,夏令时时段的边界场景容易触发异常。
内容的提问来源于stack exchange,提问作者Guidonis
相关产品推荐
相关产品推荐

