Skip to content

Add a -DateKind parameter to ConvertFrom-Json to control how System.DateTime / System.DateTimeOffset values are constructed #13598

@mklement0

Description

@mklement0

Follow-up from #13592:

Summary of the new feature/enhancement

Introduce a new -DateKind parameter as an enumeration value as follows:

ConvertFrom-Json -DateKind { Local | Utc | Unspecified | Offset | None }

The goal is to parse timestamps in the input JSON as [datetime] / [datetimeoffset] instances of the given kind - irrespective of the specific formatting of those timestamps.

  • Local / Utc / Unspecified should create [datetime] instances with the given .Kind value.

    • A timestamp without time-zone information (UTC offset or Z suffix) should be assumed to be Local (a pitfall is that on calling .ToLocalTime() on something that was parsed as Unspecified, it is assumed to be a UTC value - [datetime]::new(<unspecified-datetime>.Ticks, 'Local') is the solution).
    • If Unspecified is requested, any UTC offset / Z suffix should be ignored.
  • Offset should create a [datetimeoffset] instance instead, which preserves the exact UTC offset as specified or implied in the input.

    • A timestamp without time-zone information (UTC offset or Z suffix) should be assumed to be a caller-local timestamp.
  • None should not create a date a [datetime] / [datetimeoffset] at all and instead pass the original string values through.

Note that on serializing, with ConvertTo-Json, both Utc and Local [datetime] instances serialize with the appropriate UTC offset (e.g., "2020-09-08T16:24:21.577822-04:00"), whereas Unspecified serializes without an offset (e.g., "2020-09-08T16:24:21.577822").

Motivation:

Since v6, the Json.NET-based ConvertTo-Json automatically deserializes strings that contain an "o"-formatted (roundtrip format) date/time string (e.g., "2020-09-07T09:44:13.769Z") or a prefix of it that at least includes everything up to the seconds part (e.g., "2020-09-07T09:44:13:) as [datetime] instances.

However, the resulting [datetime] instances' .Kind property (Local, Utc, or Unspecified) is determined by the specifics of the string value as follows:

  • Unspecified, if there is no time-zone information in the input string.
  • Utc, if the time-zone information is a trailing Z
  • Local, if the time-zone information is given as a trailing UTC offset (e.g., +02:00), in which case the offset is properly converted to the caller-local equivalent.

Note that the new System.Text.Json API that is being considered as the future underpinning of the *-Json cmdlets - see #11198 - exhibits the same behavior.

There are two problems with this behavior:

  • A Utc instance gives no indication that it is a UTC timestamp in its default output formatting (applies both to PowerShell's formatting and .ToString() - verify with [datetime]::UtcNow and [datetime]::UtcNow.ToString()).

  • Specific UTC offsets in the input are lost, because they are translated to a caller-local Local instance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    In-PRIndicates that a PR is out for the issueIssue-Enhancementthe issue is more of a feature request than a bugUp-for-GrabsUp-for-grabs issues are not high priorities, and may be opportunities for external contributorsWG-Cmdlets-Utilitycmdlets in the Microsoft.PowerShell.Utility module

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions