Learn about Windows PowerShell
Summary: Learn about using Windows PowerShell and specifying different calendar types to use with dates.
Microsoft Scripting Guy, Ed Wilson, is here. Today is day four of my PowerShell Essentials for the Busy Admin series of webcasts. The series has been a lot of fun, and the feedback so far has been great. It is encouraging to see the level of interest in this series. In addition, there have been a decent amount of questions via the firstname.lastname@example.org email alias about the series of live meetings in addition to the 2012 Scripting Games.
Today is the Ides of March. For the Scripting Wife, it means March Madness is underway. For me, I think back to the play by William Shakespeare, Julius Caesar. Beware the Ides of March…
If you want to work with calendars in Windows PowerShell, perhaps you should also beware of the Ides of March—or at least be aware of how to work with different calendar types.
Anyway, the .NET Framework classes are fun to play with. If I want to create a specific date, I can use the constructor for the System.DateTime .NET Framework class and create a date. To do this, I use the New-Object cmdlet to specify the name of the .NET Framework class I want to use, and I pass the arguments for the constructor to the ArgumenLlist parameter.
With the System.DateTime .NET Framework class, there are several different constructors. As a matter of a fact, MSDN lists 11 different constructors on the System.DateTime details page. To create a new DateTime object and specify the year, month, and day, requires me to use a particular constructor. Using Windows PowerShell to create a new instance of the System.DateTime class by passing the year, month, and day is shown here.
PS C:\> New-Object system.datetime -ArgumentList 2012,3,15
Thursday, March 15, 2012 12:00:00 AM
Of course, I can do the same thing by using the Get-Date cmdlet. I am not certain it is any easier, but it is a bit less typing. It is definitely easier to read the Get-Date command. This command and the output associated with the command are shown here.
PS C:\> Get-Date -Month 3 -Day 15 -Year 2012
Thursday, March 15, 2012 5:29:42 PM
The easiest way to create a specific date is to cast a string to the DateTime object. This technique is shown here.
PS C:\> [datetime]"3/15/12"
All three of the previous examples, however, use the same calendar—the Gregorian calendar. A problem arises if I need to specify a particular calendar. To do this, I need to first create an instance of the specific calendar I want to use. Next, I use the constructor for the System.DateTime class that permits supplying the specific calendar. Because today is the Ides of March, it makes sense to use the Julian calendar as an example. Julius Caesar ordered a calendar reform that resulted in the creation of the Julian calendar. The Julian calendar is the predecessor of the Gregorian calendar.
Luckily, the .NET Framework makes these types of conversions from calendar to calendar really easy. I only need to create a new instance of the JulianCalendar class to be able to use it in the constructor to create a Julian calendar type of date. Once again, I use the New-Object cmdlet to create an instance of the class. But I do not need to pass any arguments to the JulianCalendar class. Therefore, no ArgumentList parameter is needed.
In the code that follows, I use the New-Object cmdlet to create a new instance of the JulianCalendar class, and I store the resulting calendar in the $j variable. I then use this calendar in the New-Object command that creates a specific date. The result is a specific date, reflected in a specific calendar. These two lines of code are shown here.
$j = new-object system.globalization.julianCalendar
New-Object system.datetime -ArgumentList 2012,3,15,$j
There are lots of different types of calendars defined in the .NET Framework. All of the calendars reside in the System.Globalization .NET framework namespace. To get a feel for the different calendars, spend a bit of time on MSDN and review the various calendar classes.
In the image that follows, I first create a DateTime object that represents March 15, 2012, and I display that DateTime object to the Windows PowerShell console. I then create an instance of the JulianCalendar class, and store that calendar in the $j variable. I next use the New-Object cmdlet and create the date March 15, 2012 by using the Julian calendar. These commands and the associated output are shown in the image that follows.
If you want to know what a specific calendar does, you can create the calendar object, store it in a variable, and then display the contents of that variable. Information returned by doing this includes the minimum supported date and the maximum supported date. In the image that follows, I list information for both the Julian calendar and the Gregorian calendar.
Anyway, beware the Ides of March—especially if you are not sure what calendar is being used.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at email@example.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Hi quick comment on international dates.
The syntax shows month/day/year and results in
Living in the UK I'm more used to day/month/year but if I try
Cannot convert value "51/3/12" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
I have to do
Over the years I have found that its safer for me to do
[datetime]"15 March 2012"
as it always works.
This is caused by the culture settings in PowerShell
LCID Name DisplayName
---- ---- -----------
2057 en-GB English (United Kingdom)
1033 en-US English (United States)
a good short article that explains some details of dates.
It is quite ingteresting what we can do with dates and we should pay attention to date formats!
@Richard: Right! Living in Germany, I encounter the same problems, you do!
But there is one thing, I can asure you ... you typed in: [datetime]"51/3/12"
This will never be a valid date ... not in the UK, not in the US and not here :-)))
Having saved me the need to note the locale dependency in the article's example, there is a solution: Use ISO format. This is unambiguous with a four digit year:
will always give you midnight 10 August 2010.