Search code examples
powershelldatetimestring-formatting

Powershell Cleanest way to convert a string to mmddyyyy format


Thank you in advance...

I have String output:

2021-12-23

the string Base.Type is System.Object

I would like to convert it to:

12-23-2021  

or

12/23/2021

any ideas?


Solution

  • Note: This question is a near-duplicate of Change date format from "yyyymmdd" to "mm/dd/yyyy"; while the two are closely related, this question is more overtly focused on both parsing from a string to a date and then back to a string, using a different format; by contrast, the linked question has the from aspect covered as an incidental part of the question.


    Bali C, in a comment on the question, came up with the most concise solution, which only requires a small tweak:

    # Note the "\"-escaped separators - see below.
    PS> Get-Date -Date 2021-12-23 -Format dd\-MM\-yyyy # or dd\/MM\/yyyy
    23-12-2021
    

    This will work with most cultures in effect, because format yyyy-MM-dd (as exemplified by your sample input string, '2021-12-23') is a recognized format in all but a few cultures.

    PowerShell generally tries to use the invariant culture in order for code to work the same across cultures, but in the case of cmdlet arguments actually is culture-sensitive, which is a historical accident that cannot be fixed without breaking backward compatibility.

    See below for a truly culture-invariant solution, which also explains why separator chars. - and / should be escaped for maximum robustness.


    Since PowerShell's casts use the invariant culture and format yyyy-MM-dd (as exemplified by your sample input string, '2021-12-23') happens to be a recognized format in that culture, you can simply:

    • cast your string to [datetime] to create a System.DateTime instance
    • and then call .ToString() with the desired format string to produce the desired string format, as shown in the many answers to this question.

    The following should work irrespective of the specific culture in effect:

    PS> ([datetime] '2021-12-23').ToString('MM\-dd\-yyyy')
    12-23-2021
    
    PS> ([datetime] '2021-12-23').ToString('MM"/"dd"/"yyyy')
    12/23/2021
    

    Note that the separator chars. - and / are escaped / quoted so as to indicate that they're to be used verbatim (you're free to choose between \-escaping and embedded quoting).

    This is necessary, because characters such as / are by default interpreted as placeholders for the culture-appropriate date separator, for instance, so - depending on the culture in effect (as reflected in $PSCulture) - they may be translated to a different character, such as ., for instance.


    If your original string representation were not recognized in the invariant culture, you can use System.DateTime.ParseExact to parse your input string into a [datetime] (System.DateTime) instance before calling .ToString() as described above:

    [datetime]::ParseExact(
      '2021-12-23', 
      'yyyy\-MM\-dd', 
      $null  # current culture
    ).ToString('MM"-"dd"-"yyyy')
    

    The above again yields '12-23-2021'.

    Note that, due to use of $null, the current culture is used for parsing, which has no effect in this case, however, given that the separator chars. use embedded quoting, and given that only digits are involved, not (culture-dependent) names, such as month names.

    If you do need the context of a specific culture, pass a [cultureinfo] instance (System.Globalization.CultureInfo) instead of $null; e.g., to parse in the context of the French (France) culture, pass [cultureinfo] 'fr-FR'.