Use PowerShell to Convert Date Formats Easily

Summary: Microsoft Scripting Guy Ed Wilson discusses four different techniques for using Windows PowerShell to convert date formats.

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! I have a problem. Although I am sure you hear this a lot, this problem is causing me a major problem at work. Here is the deal. We are a large company and we have operations both in the United States and in Germany. The problem is that in the United States, as you are well aware, we write the date like this: 8/24/11. Or we write it like this: 8/24/2011. We always list the month, then the day, and then the year. In Germany, however, they seem to write it day, then month, and then year. They also use a period for the separator instead of the forward slash. Therefore, my German colleagues would write today’s date as 24.8.11 or 24.8.2011.

This is causing major confusion in our office, and I do not think it is fair to just tell our German colleagues to write the date the way we do in the United States. I need a Windows PowerShell script that will translate the date from the way we write it in the United States to the way they write the date in Germany. Please help—this is driving me crazy!

—SL

 

Hey, Scripting Guy! AnswerHello SL,

Microsoft Scripting Guy Ed Wilson here. Writing a date as day.month.year is not just a German thing. In fact, many countries write the date in that format. In fact, day.month.year is a very good way to write dates (and is used by the military) because, while it may be possible that I might not remember what day it is, I nearly always remember what month it is.

SL, you specifically asked for a script that could convert a month/day/year formatted string to a day.month.year formatted string. In the first case, the separator is a forward slash, and in the second case, the separator is a period. Here is such a script, ConvertMonthDayYearToDayMonthYear.ps1:

$usdate = “8/24/11”

$dateParts = $usdate -split “/”

$deDate = “$($dateparts[1]).$($dateParts[0]).$($dateParts[2])”

$deDate

In the ConvertMonthDayYearToDayMonthYear.ps1 script, the first thing I do is assign a month/day/year string to a variable named $usdate, as shown here:

$usdate = “8/24/11”

Next, I use the split operator to split the string into three parts (it creates an array with three elements in it). The obvious place to split the string is at the forward slash character. The cool thing about the split operator is that it does not include the character that is split upon in the parts that are created. The syntax of the split operator is really simple, I use it after the string that I want to split, and I specify the character to split upon. After I use the split operator to break the string into three parts, I store the parts (an array) in the $dateParts variable. Here is the line of code that uses the split operator to create the array from the string:

$dateParts = $usdate -split “/”

Now that I have the three parts of the date from the string stored in a variable named $dateParts, I can reassemble them into the format that is required by your German colleagues. To do this, I use square brackets to indicate which portion I want to retrieve. I then build up the string in the order and manner you specified. Because the parts are stored in an array, I can use array notation to retrieve specific elements of the array. To retrieve the month from the array, I would use a zero inside square brackets. All arrays begin with zero in Windows PowerShell, so the first element is zero. Here is the code that would retrieve the month (the first element of the array) from the parts stored in the $dateParts variable:

$dateParts[0]

To build the German date, I use an expanding string. An expanding string in Windows PowerShell is one that will expand to display the value contained inside a variable. Unfortunately, at times rather than just expand and reveal the value contained inside the object, it will unravel the object itself. When that happens, it is necessary to use a subexpression to force evaluation of the object first. After the object has been evaluated, it will return only the value that is referenced. A subexpression begins with a dollar sign, and then opens a pair of parentheses and ends by closing the parentheses. These subexpression characters are shown here:

$( )

A subexpression that will force the return of the value that is stored in element 1 that is contained in the array stored in the variable $dateparts is shown here:

$($dateparts[1])

After I use the subexpression to return the numbers stored in the various elements of the array, I place a period between each of the three elements. I then return the German formatted date to the $deDate variable, as shown here:

$deDate = “$($dateparts[1]).$($dateParts[0]).$($dateParts[2])”

Some people do not like using subexpressions, and therefore tend to avoid expanding strings. One way to avoid using subexpressions and expanding strings is to use literal strings and concatenation. For example, I have already shown that when addressing an element in an array, it returns the value that is contained inside that element, unless that technique occurs inside expanding strings. If I avoid the strings, and simply place the reference to the element number on a line, I get the value in the element. If I then concatenate (glue) the element reference with a period, and glue it to another element reference, another period, and another element reference, I get the date I wanted to create. The concatenation operator is the plus sign (+). Here is the portion of the script that creates the date string; one key point to remember is that concatenation is required on both sides of the period (+ ‘.’ +).

$dateparts[1] + ‘.’ + $dateParts[0] + ‘.’ + $dateParts[2]

The remainder of the ConvertMonthDayYearToDayMonthYearUseLiteralString.ps1 script is the same as the previous code. The complete script is shown here:

$usdate = “8/24/11”

$dateParts = $usdate -split “/”

$deDate = $dateparts[1] + ‘.’ + $dateParts[0] + ‘.’ + $dateParts[2]

$deDate 

Personally, I hate concatenation (was abused with VBScript), so I will do anything to avoid concatenation—even use the format operator. In fact, in my second list of top ten Windows PowerShell tricks, it will probably figure rather high in the ranking. (For the first list of my favorite top ten Windows PowerShell tricks, see this collection of Hey, Scripting Guy! Blog posts). Anyway, I can build a string by using a string with symbols for substitution. The first position is 0, next is 1, and then 2. The curly brackets surround the element for which substitution will take place. I place the period between the curly brackets and then supply an array of elements that are used when creating the string. The f is the format operator. This sounds more complicated than it really is. Here is the code I use:

“{0}.{1}.{2}” -f $dateparts[1],$dateParts[0],$dateParts[2]

The remainder of the script is the same as the other ones in today’s article. The complete ConvertMonthDayYearToDayMonthYearUseFormatSpecifier.ps1 script is shown here:

# ConvertMonthDayYearToDayMonthYearUseFormatSpecifier.ps1

# hsg-8-24-11

$usdate = “8/24/11”

$dateParts = $usdate -split “/”

$deDate = “{0}.{1}.{2}” -f $dateparts[1],$dateParts[0],$dateParts[2]

$deDate

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

Image of script and associated output

SL, that is all there is to using string techniques to work with dates. Join me tomorrow when I will talk about using culture settings to convert dates.

 

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