Powershell: Add One New DateTime Parsing Format

Created on 29 Jan 2020  路  7Comments  路  Source: PowerShell/PowerShell

Yesterday I posted a suggestion that we have a new special format for Get-Date that creates the SecondsSinceEpoch (aka UnixTime) for users.

Additionally I think we should have built into the language the ability to easily parse a UnixEpoch timestamp back into a DateTime.

Various existing parsing that works today:

$aDate = [DateTime]"2020-01-28T17:32:18.4986003-06:00" #  (conversion back from the format of Format "o")
$bDate = [DateTime]"2020-01-28T17:36:39" #  (conversion back from the format of Format "s")
$cDate = [DateTime]"Tue, 28 Jan 2020 17:37:43 GMT" #  (conversion back from the format of Format "r")
$dDate = [DateTime]"2020-01-28 17:38:24Z" #  (conversion back from the format of Format "u")
$eDate = [DateTime]"7/25/2013 6:37:31 PM" 
$fDate = [DateTime]"2013-07-25 14:26:00" 
$gDate = [DateTime]"7/25/2013 14:26:00"
$hDate = [DateTime]"2013-07-25 6:37:31 PM"

But we can't currently put in $AUnixDate = [DateTime]"1374755180" and end up with a valid DateTime object (which would be of UTC kind)

A discussion by Randy James at https://stackoverflow.com/questions/17859421/parse-datetime-in-multiple-formats suggests perhaps something along these lines for processing this in another language:

public DateTime ParseRequestDate()
{
    // https://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c

    CultureInfo enUS = new CultureInfo("en-US");

    var dt = "1374755180";
    //var dt = "7/25/2013 6:37:31 PM";
    //var dt = "2013-07-25 14:26:00";

    DateTime dateValue;
    long dtLong;

    // Scenario #1
    if (long.TryParse(dt, out dtLong))
        return dtLong.FromUnixTime();

    // Scenario #2 & #3
    var formatStrings = new string[] { "MM/dd/yyyy hh:mm:ss tt", "yyyy-MM-dd hh:mm:ss" };
    if (DateTime.TryParseExact(dt, formatStrings, enUS, DateTimeStyles.None, out dateValue))
        return dateValue;

    throw new SomeException("Don't know how to parse...");
}

Area-Cmdlets-Utility Issue-Enhancement Resolution-Fixed

Most helpful comment

Using .NET methods, you parse Unix epoch time values as follows (given PowerShell's flexible type conversions, you can also use a _string_ in the following method call):

PS> [datetimeoffset]::FromUnixTimeSeconds(1374755180).UtcDateTime
Thursday, July 25, 2013 12:26:20 PM

As for making that easier:

Note that PowerShell's casts translate to looking for and invoking, as appropriate, the following behind the scenes:

  • a single-parameter constructor on the target type whose parameter is of the same type as the operand
  • with _string_ operands, a call to .Parse(<operand>[, <invariantCulture>)

  • [datetime] <string> translates to the latter, and it doesn't recognize Unix epoch time, and we shouldn't try to add magic there.

  • With a _numeric_ operand, [datetime] <num> maps onto constructor DateTime(long ticks); ticks are very fine-grained units with a starting point in the year 1 (sic); try [datetime] 0.

    • The same happens when you call Get-Date 0 (short for: Get-Date -Date 0)
    • We shouldn't try to change this logic.

Therefore, if we want to make this easier, I suggest adding a new parameter to Get-Date, along the lines of -FromUnixTime <long>, which would be mutually exclusive with -Date.

All 7 comments

Looks good for me but I'd put the code for 1 scenario in last place.

@SteveL-MSFT Please triage.

Using .NET methods, you parse Unix epoch time values as follows (given PowerShell's flexible type conversions, you can also use a _string_ in the following method call):

PS> [datetimeoffset]::FromUnixTimeSeconds(1374755180).UtcDateTime
Thursday, July 25, 2013 12:26:20 PM

As for making that easier:

Note that PowerShell's casts translate to looking for and invoking, as appropriate, the following behind the scenes:

  • a single-parameter constructor on the target type whose parameter is of the same type as the operand
  • with _string_ operands, a call to .Parse(<operand>[, <invariantCulture>)

  • [datetime] <string> translates to the latter, and it doesn't recognize Unix epoch time, and we shouldn't try to add magic there.

  • With a _numeric_ operand, [datetime] <num> maps onto constructor DateTime(long ticks); ticks are very fine-grained units with a starting point in the year 1 (sic); try [datetime] 0.

    • The same happens when you call Get-Date 0 (short for: Get-Date -Date 0)
    • We shouldn't try to change this logic.

Therefore, if we want to make this easier, I suggest adding a new parameter to Get-Date, along the lines of -FromUnixTime <long>, which would be mutually exclusive with -Date.

We shouldn't try to change this logic.

It would be a breaking change. @mklement0 Thanks! -FromUnixTime is best compromise to address the request.

@mklement0 Thank you for suggesting this. I like your idea MUCH better. I think it has the added benefit that by being part of Get-Date, its implementation will be documented in the Get-Date documentation which is where I think most people would look if trying to figure out if PowerShell can convert UnixEpoch times. +1 for -FromUnixTime

Agree with @mklement0's proposal

I believe this would be super handy! I'd be happy to take a swing at it 馃榿

:tada:This issue was addressed in #12179, which has now been successfully released as v7.1.0-preview.2.:tada:

Handy links:

Was this page helpful?
0 / 5 - 0 ratings