8

#PSTip Converting a String to a System.DateTime object

In a perfect world all date and time data available are represented by System.DateTime objects. In the real world we are usually not that lucky. You get lot of obscurely formatted dates that you have to convert yourself. The .NET Framework offers a special method just for that, TryParseExact(). Calling the method is not particularly easy so I’ve created a short function to make it easier to work with:

function Convert-DateString ([String]$Date, [String[]]$Format)
{
	$result = New-Object DateTime

	$convertible = [DateTime]::TryParseExact(
		$Date,
		$Format,
		[System.Globalization.CultureInfo]::InvariantCulture,
		[System.Globalization.DateTimeStyles]::None,
		[ref]$result)

	if ($convertible) { $result }
}

Let’s call it with a date string in an uncommon format and see how the function handles different date and time separators:

Convert-DateString -Date '12/10\2013 13:26-34' -Format 'dd/MM\\yyyy HH:mm-ss'
Saturday, October 12, 2013 1:26:34 PM

The function successfully converts the date and returns a DateTime object. If the operation was not successful nothing would have been returned.
Also notice the Format parameter accepts array of strings, allowing you to specify more than one format of the input.

Convert-DateString -Date '12:26:34' -Format 'HH:mm:ss','HH-mm-ss'
Convert-DateString -Date '12-26-34' -Format 'HH:mm:ss','HH-mm-ss'

Thursday, July 4, 2013 12:26:34 PM

Thursday, July 4, 2013 12:26:34 PM

The string is converted successfully, and because only time was provided, today’s date is used to complete the other date parts of the object.

Building a format string.

Providing correct string to the Format parameter is essential for successfully using the function. Let’s have a quick look on how to create one yourself: The string uses the following characters “d”, “f”, “F”, “g”, “h”, “H”, “K”, “m”, “M”, “s”, “t”, “y”, “z” to define type, position and format of the input values. The type of the input value (day, month, minute etc.) is defined by choosing the correct letter to represent the value (day d, month M, minute m etc.), case matters here. The position is defined by placing the character on the correct place in the string. The format is defined by how many times the character is repeated (d to represent 1-31, dd for 01-31, dddd for Monday).

Convert-DateString -Date 'Thursday, July 4, 2013 12:26:34 PM' `
-Format 'dddd, MMMM d, yyyy hh:mm:ss tt'

Thursday, July 4, 2013 12:26:34 PM

If your string contains any of the listed characters or the backslash (“\”) character you have to escape it by preceding it with a backslash:

Convert-DateString -Date “d: 01\01\2013” -Format '\d: dd\\MM\\yyyy'
Tuesday, January 1, 2013 12:00:00 AM

The complete reference to creating custom date and time format strings, as well as many examples may be found here.

Filed in: Columns, Tips and Tricks Tags: , , ,

8 Responses to "#PSTip Converting a String to a System.DateTime object"

  1. Shasta7 says:

    Very good information! Your hyperlink to the reference material, however, points to the Czech version.

  2. Curtis L. Smith says:

    There’s an easier way, pending your date/time string isn’t in some crazy format. You can pipe your date string into the Get-Date commandlet, and it will parse you string for you and output a DateTime object.

    PS C:> “Tuesday 9/17/2013” | Get-Date | FL

    DisplayHint : DateTime
    Date : 9/17/2013 12:00:00 AM
    Day : 17
    DayOfWeek : Tuesday
    DayOfYear : 260
    Hour : 0
    Kind : Unspecified
    Millisecond : 0
    Minute : 0
    Month : 9
    Second : 0
    Ticks : 635149728000000000
    TimeOfDay : 00:00:00
    Year : 2013
    DateTime : Tuesday, September 17, 2013 12:00:00 AM

    PS C:> “9-17-2013” | Get-Date | FL

    DisplayHint : DateTime
    Date : 9/17/2013 12:00:00 AM
    Day : 17
    DayOfWeek : Tuesday
    DayOfYear : 260
    Hour : 0
    Kind : Unspecified
    Millisecond : 0
    Minute : 0
    Month : 9
    Second : 0
    Ticks : 635149728000000000
    TimeOfDay : 00:00:00
    Year : 2013
    DateTime : Tuesday, September 17, 2013 12:00:00 AM

    PS C:> “9-17-2013 8:23:1” | Get-Date | FL

    DisplayHint : DateTime
    Date : 9/17/2013 12:00:00 AM
    Day : 17
    DayOfWeek : Tuesday
    DayOfYear : 260
    Hour : 8
    Kind : Unspecified
    Millisecond : 0
    Minute : 23
    Month : 9
    Second : 1
    Ticks : 635150029810000000
    TimeOfDay : 08:23:01
    Year : 2013
    DateTime : Tuesday, September 17, 2013 8:23:01 AM

  3. Mark Renton says:

    Your call to TryParseExact can be simplified somewhat!

    The InvariantCulture can be specified by $null, and the enumerated type value None can be passed the String ‘None’ (it’ll be converted when it is typecast).
    Here’s an example with a 6-digit time:

    ps> $dt=New-Object DateTime
    ps> $r=[DateTime]::TryParseExact(‘123456′,’HHmmss’,$null,’None’,[ref]$dt)
    ps> $r
    True
    ps> $dt
    Thursday, June 11, 2015 12:34:56 PM

    Also, (Get-Date)|gm reveals the existence of a method named GetDateTimeFormats(), which shows the given date formatted in many styles known to [DateTime]. Date-and-or-time strings which look like those strings can often be parsed either by passing them to Get-Date or simply typecasting them to [DateTime].
    ps> (Get-Date).GetDateTimeFormats().Length # How many of these formats are there?
    133

    ps> [DateTime]’1999-12-31T23:59:59′ # File-style DateTime

    Friday, December 31, 1999 11:59:59 PM

    Or you can use the following method to see the allowed keywords for the styles:
    ps> [Enum]::getNames(‘System.Globalization.DateTimeStyles’)
    None
    AllowLeadingWhite
    AllowTrailingWhite
    AllowInnerWhite
    AllowWhiteSpaces
    NoCurrentDateDefault
    AdjustToUniversal
    AssumeLocal
    AssumeUniversal
    RoundtripKind

    Which lets you guess you can use values like:
    ps> [System.Globalization.DateTimeStyles]’AllowLeadingWhite,AllowTrailingWhite’

    Which are described at https://msdn.microsoft.com/en-us/library/91hfhz89%28v=vs.110%29.aspx

  4. Mark Renton says:

    Moderator: After posting that, realized that the culture you get by specifying $null for the culture will probably be the one matching the user’s currently selected Windows language, rather than the Invariant culture (which in most cases will be [System.Globalization.CultureInfo]’EN-US’).

Leave a Reply

Submit Comment

© 2016 PowerShell Magazine. All rights reserved. XHTML / CSS Valid.
Proudly designed by Theme Junkie.
%d bloggers like this: