Use Culture Information in PowerShell to Format Dates

Use Culture Information in PowerShell to Format Dates

  • Comments 4
  • Likes

Summary: Learn how to use culture information in Windows PowerShell to format dates.

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! I enjoyed your article yesterday about manually changing the way a date is displayed using string techniques. But the problem is that is a bit complicated, and is even potentially error prone. Is there an easier way to work with dates and times in Windows PowerShell than manually creating string values in specific orders?

—KL

 

Hey, Scripting Guy! AnswerHello KL,

Microsoft Scripting Guy Ed Wilson here. The technique that allows for automatic conversion of date types is called culture settings. Whenever I think about culture, I remember Vienna, Austria. It seems the city’s motto is “Where business meets culture.” I have taught several Windows PowerShell, VBScript, and WMI classes in Vienna over the years, and it is one of my favorite cities. Here is a photo I took of the Mozart statue during one of my last trips over.

Photo taken in Vienna, Austria

To me, the Get-Culture cmdlet will always be associated with Viennese classical music and long walks in the park that was near to our hotel.

Whoops! It seems I have spoiled the surprise. To work automatically with dates, it is necessary to interact with the CultureInfo settings and the DateTime structure from the .NET Framework. It is easy to convert a string into an instance of the DateTime structure. This is called casting, and to do this, I place the DateTime inside square brackets. The code that appears here converts a string into a DateTime object:

[datetime]"8/25/11"

When converting a string into a DateTime object, the way the value displays depends on the current culture settings. I can use the Get-Culture cmdlet to determine my current culture settings. The command and associated output are shown here:

PS C:\Users\ed.IAMMRED> Get-Culture

 

LCID             Name             DisplayName                                                                 

----             ----             -----------                                                                 

1033             en-US            English (United States)    

 

By using the Get-Member cmdlet, I can see there is much more information available as well as a large number of methods that facilitate working with cultural settings. The Get-Member cmdlet (gm is the alias for the Get-Member cmdlet) and associated output are shown in the following figure.

Image of Get-Member cmdlet and associated output

The DateTimeFormat property that is returned from the Get-Culture cmdlet contains an object. This object is culture specific, and it contains DateTimeFormat information that corresponds to the cultural settings. Because the DateTimeFormat property returns an object, I can directly access by using a dotted notation:

(Get-culture).DateTimeFormat

The command and associated output are shown in the following figure.

Image of command and associated output

In the preceding figure, note that the ShortDatePattern m/d/yyyy is Month/Day/Year, which is the way dates are written in my cultural setting, en-US. The first two letters, en, correspond to English. The second two letters, US, correspond to the country. This is necessary because there are differences between English in the United States and in the United Kingdom (en-GB).

Now for the really cool stuff. Anyone who has played around with the Get-Date cmdlet has seen the format parameter. I can use this parameter to configure the way that I want a date to display. For example, if I want day/month/two-digit year, I can use the command shown here:

Get-Date -Format "dd-MM-yy"

By examining, the date patterns returned by the DateTimeFormatInfo object that comes back from the DateTimeFormat property, it dawned on me that I could use those patterns directly with the format parameter of the Get-Date cmdlet. This simplifies creating certain types of date outputs, and is more accurate as well because of the strong possibility of making a typo. For example, if I want to use the date in the UniversalSortableDateTimePattern format, I can use the command that is shown here:

Get-Date -Format "yyyy'-'MM'-'dd HH':'mm':'ss'Z'"

One problem is that this pattern appears somewhat cryptic. I can also directly use the UniversalSortableDateTimePattern property from the DateTimeFormatInfo object that is returned from the Get-Culture cmdlet. The UniversalSortableDateTimePattern property does not change from culture to culture, but other patterns, such as short date patterns, do change. Therefore, I can use the command that is shown here:

Get-Date -Format (Get-culture).DateTimeFormat.UniversalSortableDateTimePattern 

Because I can easily create a new instance of a CultureInfo class by supplying either the culture ID (LCID) or the culture name, that means I can convert the date output with ease, and with no hard-coding. In the code that follows, I create an instance of the German (Germany) cultureInfo class. I then use this class to display a short date in the German (Germany) pattern.

$de = New-Object system.globalization.cultureinfo("de-DE")

get-date -format ($de.DateTimeFormat.ShortDatePattern)

 After I know that I can create an instance of a specific cultureInfo class and use it to display a date in a particular format, I can write a script to display dates in a variety of outputs. The preferred way to create an instance of a cultureInfo class is to use the string method. The culture names are documented on the same page where the LCIDs are located. In the DisplayAlternateShortDates.ps1 script, I create an array of assorted culture string names. Next, I use the foreach statement to walk through the array of culture names. Inside the foreach loop, I use the New-Object cmdlet to create a new instance of a cultureinfo object. I pass the string name as an input argument to the cmdlet, and store the returned cultureinfo object in the $culture variable. Next, I use the Get-Date cmdlet to create the current date in the format specified by the shortDatePattern property. I then create a custom psobject that holds the culture name in a name property and the formatted short date in the date property. The complete DisplayAlternateShortDates.ps1 script s shown here:

$cultures = "en-US","en-GB","fr-CA","fr-FR","ms-MY","zh-HK"

foreach ($c in $cultures)

{

 $culture = New-Object system.globalization.cultureinfo($c)

 $date = get-date -format ($culture.DateTimeFormat.ShortDatePattern)

 New-Object psobject -Property @{"name"=$culture.displayname; "date"=$date}

}

 

The script and associated output are shown in the following figure.

Image of script and associated output

I can use the static GetCultures method from the globalization.cultureinfo .NET Framework class to return culture names and IDs. If I want to see all the cultures, I use the “allcultures” enumeration. This command is shown here:

[globalization.cultureinfo]::GetCultures("allCultures")

The output returns an object, and I can filter based upon the name. In the following command, I filter out all cultures that contain the cultures that begin with fr by using the following command:

[globalization.cultureinfo]::GetCultures("allCultures") | where {$_.name -match '^fr'} 

By using this approach, I can display the date for all French cultures as shown here in the DisplayAlternateShortDatesFrench.ps1 script:

$cultures = [globalization.cultureinfo]::GetCultures("allCultures") |

  where-object {$_.name -match '^fr'}

foreach ($c in $cultures)

{

 $culture = New-Object system.globalization.cultureinfo($c)

 $date = get-date -format ($culture.DateTimeFormat.ShortDatePattern)

 New-Object psobject -Property @{"name"=$culture.displayname; "date"=$date}

The script and output are shown in the following figure.

Image of script and associated output

KL that is all there is to using culture information to format dates. Join me tomorrow as I introduce a new Windows PowerShell superhero.

 

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

 

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Excellent article. Almost no more that can be said.  I wish you had done this about a year ago.

  • Hi Ed,

    this is more excellent information, Ed!

    Don't be despaired by jrv's comment!

    Better late than never!!!

    And perhaps you have "saved someone else's life" now :-)))

    Klaus.

  • Hi, I'm outputting exchange log information and trying to format the date output.  I can follow all the above examples fine but how do I put that into a script using -- SELECT timestamp, ...

    I've tried variations on timestamp -f s

  • Excellent article! One thing I'm stuggling with is the following:

    I need to enter long dates into an AD field, according to a "day month year 00:00:00" format, however!
    The server from which I perform the script is on an en-us locale, and the text needs to be formatted in Dutch.
    So with Dutch names for days and months.

    What's the easiest way to do this?