Powershell: Add timezone/offset related parameters to the Get-Date command

Created on 30 Jul 2020  路  6Comments  路  Source: PowerShell/PowerShell

Summary of the new feature/enhancement

I propose to add parameters to the Get-Date command that allows specifying the time difference of the value to be output.

For example:

Get-Date [-Date <DateTime | DateTimeOffset>] [-TimeZone <TimeZoneInfo>] ...
Get-Date [-Date <DateTime | DateTimeOffset>] [-Offset <TimeSpan>] ...

If these parameters are specified, the value to be output will be DateTimeOffset.

Date

Extend this parameter to accept DateTimeOffset.

TimeZone

Specify the time zone of the output.
This parameter can take the TimeZoneInfo object as well as its ID.
And it accepts UTC and Local as special values.

For example:

Get-Date -TimeZone (Get-TimeZone)
Get-Date -Date '2020-08-01T10:00:00-07:00' -TimeZone 'Asia/Tokyo'
Get-Date -TimeZone UTC

Offset

Specifies the offset of time from UTC of the value to be output.

For example:

Get-Date -Offset ([TimeSpan]::FromHours(-8))
Get-Date -Offset '-8:00'

Usecase examples

The following example shows how to convert the time expressed in the US local time to time in Japan.

Get-Date -Date '2020-08-01 10:00' -TimeZone 'America/Los_Angels' | Get-Date -TimeZone 'Asia/Tokyo' -Format f
Sunday, August 2, 2020 2:00 PM

Related proposals

11731 suggests adding -AsLocal parameter. The -AsLocal switch is equivalent to -TimeZone Local.

The -TimeZone parameter covers the functionality of the -AsUTC, -AsLocal, and -AsKind parameters, and more widely.

I believe that using DateTimeOffset is preferable to using DateTime and DateTimeKind.

Proposed technical implementation details

Type of the -Date parameter

The -Date parameter must accept DateTime, DateTimeOffset and Int64.
Since there is no existing type that satisfies these requirements, we need to change the type of the -Date parameter to a custom type such as the following.

public readonly struct DateInput
{
    public DateInput(DateTime dateTime) {}

    public DateInput(DateTimeOffset dateTimeOffset) {}

    public DateInput(long tick) {}
}

Converting time zone ID to TimeZoneInfo object

TimeZoneInfo cannot be implicitly converted from a string representing its ID.
We can create a custom type for the -TimeZone parameter as described above, or create an attribute derived from the ArgentTransformationAttribute and assign it to -TimeZone parameter.

Considerations

Platform dependence of time zone ID

The TimeZoneInfo.FindSystemTimeZoneById method supports different time zone ID formats, depending on the platform.
For example, 'Pacific Standard Time' on Windows, 'America/Los_Angeles' on Linux.

We need to consider whether the parameter -TimeZone should be platform-independent and should be able to take the same value.
By using a library like TimeZoneConverter, we can make it platform-independent.

Abbreviations for time zone

For example, a format like '10:00 AM PDT' is used to describe the start time of a webinar or system maintenance.
Abbreviations for time zones such as 'PDT' are widely used, but are not specified in official specifications such as ISO 8601 and are ambiguous.
I think it would be useful if the -TimeZone parameter could accept such abbreviations, but should we support this?

Removing an -AsUTC parameter

Consider removing the -AsUTC parameter because its functionality is superseded by -TimeZone UTC.
This parameter was added in the 7.1 preview release and is not yet generally available.

Default format for DateTimeOffset

Currently, the default output for DateTimeOffset is in the following format:

DateTime      : 7/29/2020 10:31:25 PM
UtcDateTime   : 7/30/2020 5:31:25 AM
LocalDateTime : 7/29/2020 10:31:25 PM
Date          : 7/29/2020 12:00:00 AM
Day           : 29
DayOfWeek     : Wednesday
DayOfYear     : 211
Hour          : 22
Millisecond   : 54
Minute        : 31
Month         : 7
Offset        : -07:00:00
Second        : 25
Ticks         : 637316586850545851
UtcTicks      : 637316838850545851
TimeOfDay     : 22:31:25.0545851
Year          : 2020

Output in the following format, like DateTime, will be easier to read.

Wednesday, July 29, 2020 10:31:25 PM (UTC -07:00)
Area-Cmdlets-Utility Issue-Enhancement

Most helpful comment

Good point, @vexx32; just to provide some conceptual background on conversions between [datetime] and [datetimeoffset] we need to be mindful of:

Get-Date -Date 1 currently outputs an Unspecified [datetime] instance, whereas [datetimeoffset] has no equivalent representation (all instances represent concrete, unambiguous points in time).

Converting an Unspecified [datetime] to a [datetimeoffset] effectively turns it into a _local_ date (that is the local time zone's then-current UTC offset is used).

Converting a [datetimeoffset] instance back to [datetime] (via the .Date or .DateTime properties) invariably returns an Unspecified [datetime] instance, irrespective of the instance's specific offset.

See also the musings on whether we should for conceptual simplicity eliminate Unspecified output altogether (technically, a breaking change): https://github.com/PowerShell/PowerShell/issues/11731#issuecomment-659279816

All 6 comments

The Get-Date cmdlet is already too complex. Maybe better to consider new Get-DateTimeOffset cmdlet?

We can't have one parameter accepting two different types. We _can_ have the parameter accept just DateTimeOffset, which from memory DateTime will convert to cleanly, but it would be somewhat confusing.

Personally if we can come up with a more intuitive name than Get-DateTimeOffset for the cmdlet (IMO that type name is _very_ unintuitive at best, it describes the implementation more than the usage/purpose) then I'm for a new cmdlet. Otherwise, Get-Date is the natural choice for it, but potentially in completely separate parameter sets.

"The Get-Date cmdlet is already too complex." - says who? What is lacking is some decent examples of how to use the blasted thing. I spent a week wrestling with [TimeZoneInfo]::GetSystemTimeZones() (which is different between Windows and Linux!) and figuring out DST shifts - this suggestion above would look to meet a very real need and Get-Date is the obvious cmdlet to address it.

We _can_ have the parameter accept just DateTimeOffset

DateTime has a constructor that takes only one long, while DateTimeOffset does not.
So changing the type of the -Date parameter to DateTimeOffset makes calls like Get-Date -Date 1 impossible. This is a breaking change.

Not necessarily. We can implement a transformation attribute to bridge the gap there if needed. But yeah, that's definitely something to keep in mind, thanks! 馃挅

Good point, @vexx32; just to provide some conceptual background on conversions between [datetime] and [datetimeoffset] we need to be mindful of:

Get-Date -Date 1 currently outputs an Unspecified [datetime] instance, whereas [datetimeoffset] has no equivalent representation (all instances represent concrete, unambiguous points in time).

Converting an Unspecified [datetime] to a [datetimeoffset] effectively turns it into a _local_ date (that is the local time zone's then-current UTC offset is used).

Converting a [datetimeoffset] instance back to [datetime] (via the .Date or .DateTime properties) invariably returns an Unspecified [datetime] instance, irrespective of the instance's specific offset.

See also the musings on whether we should for conceptual simplicity eliminate Unspecified output altogether (technically, a breaking change): https://github.com/PowerShell/PowerShell/issues/11731#issuecomment-659279816

Was this page helpful?
0 / 5 - 0 ratings