Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to find the date for a specific holiday by using a web service.
Hey, Scripting Guy! I have a problem. I guess you hear that a lot. Anyway, my boss has given me what I think is an impossible task—to find the holidays we have coming up this year. Not just a list of the standard holidays, but the actual days they will be celebrated. I know there is a holiday thing I can turn on in Microsoft Outlook, and I thought about trying to write a script that would find holidays marked in my Outlook Calendar, but I suspect that my boss has other ideas. You see, he never tells me what is on his mind. It is always just a series of seemingly random requests. I really wish he would clue me in on what goes on in his fuzzy-headed brain, but that is a different story—so I have to try and anticipate him and that is not easy. Anyway, I suspect, eventually he wants a script that will be able to do something with holiday dates—got any clues, ideas, or suggestions, oh, scripting wizard?
Microsoft Scripting Guy, Ed Wilson, is here. This morning seems cold. A quick look outside reveals frost on the ground. In Charlotte, North Carolina, in the southern portion of the United States, having frost on the ground is not a normal event. In fact, I would not be surprised if they called off school. But as the old song goes, the weather outside is frightful, but the fire inside is delightful. Yes, I turned on the fire when I came down and saw the glittering grass in the early morning sunlight. I also decided today would be a good coffee day. The Scripting Wife had a nice bag of Kona coffee shipped from the island of Kauai, Hawaii, for me, and today seems like a nice day to open it. When I make coffee, I grind fresh beans, use fresh spring water, and I employ my French press. I usually use turbinado raw sugar, but today I am using crushed rock sugar I brought back from Munich—it is actually a nice addition. For me, I want to taste the coffee, not cheap flavoring. Nor do I want to drink a glass of warm milk with a shot of coffee in it.
Use a web service to obtain holiday dates
GG, there may be a completely international web service that returns holiday information, but I was unable to find one doing a few Bing searches. I was able to find a web service that contains holiday information for a few countries. I found the HolidayService2 web service. The service defines six methods. Opening the URL in Internet Explorer shows the six methods.
To use a method from a web service, I use the New-WebServiceProxy cmdlet, and I store the returned object in a variable. When using the New-WebServiceProxy cmdlet, the most important parameter is the URI for the web service. For this example, the class and the holiday parameters do not matter. To make things more readable, I always store the URI for the web service in a separate variable. I end up with two lines of code, as shown here.
$URI = "http://www.holidaywebservice.com/HolidayService_v2/HolidayService2.asmx"
$proxy = New-WebServiceProxy -Uri $URI -Class holiday -Namespace webservice
Calling a web service method
All I need to do now is figure out how to use the web service. This particular web service is really nice because it is based on the .NET Framework, and it returns .NET objects—I will get to that in a minute. First, I need to know what countries or regions are supported by the web service. To do this, I call the GetCountriesAvailable method.
Note Keep in mind this web service is case-sensitive. Therefore, UnitedStates must be cased as shown (I cannot do everything in lowercase as I often do), as it is required for the other countries or regions and holidays.
To call GetCountriesAvailable, I begin typing and use the tab expansion to complete the method name. This command is shown here.
The command and associated output appear in the image that follows.
OK, so I know what countries or regions the service supports. Now I need to know what holidays the service supports. To do this, I call the GetHolidaysAvailable method, as shown here.
The neat thing about the service returning objects is that I can pipe the returned objects to other Windows PowerShell cmdlets. For example, looking through a random listing of holidays may not be too illuminating, but if I sort them alphabetically, it makes things easier to see. This command is shown here.
$proxy.GetHolidaysAvailable("UnitedStates") | sort code
The command and associated output appear here.
Hey, want to know the difference between holidays celebrated in Northern Ireland and the holidays celebrated in the Republic of Ireland? I call the GetHolidaysAvailable method twice (once for each region), store the results in variables, and pass the resultant objects to the Compare-Object cmdlet. Piece of cake. The three commands are shown here.
$in = $proxy.GetHolidaysAvailable("IrelandNorthern") | sort code
$ir = $proxy.GetHolidaysAvailable("IrelandRepublicOf") | sort code
Compare-Object -Property code -ReferenceObject $in -DifferenceObject $ir
The commands and the associated output are shown here.
Get the holiday date
Now, I can figure it out. It might take a bit of time. A few of my attempts are shown here.
Rather than cluttering up my Windows PowerShell console with red, how about if I go back to the HolidayService2 web page and look at the parameters for the GetHolidayDate method. In fact, there is even a little form I can use to see if what I am thinking about using will actually work. The web page with the form and the SOAP definition are shown here.
So, the correct way to call the GetHolidayDate method appears here.
PS C:\> $proxy.GetHolidayDate("UnitedStates","LABOR-DAY",2013)
Monday, September 2, 2013 12:00:00 AM
Notice that the returned date looks amazingly like the good old-fashioned System.DateTime object we PowerShellers know and love. Once again, because this web service returns .NET objects, I can do some really cool Windows PowerShell stuff. For example, if I want to know how long it is until Labor Day in the United States, I can use the New-TimeSpan cmdlet, as shown here.
PS C:\> New-TimeSpan -Start (get-date) -End ($proxy.GetHolidayDate("UnitedStates","LA
Days : 196
Hours : 11
Minutes : 19
Seconds : 45
Milliseconds : 909
Ticks : 171479859090373
TotalDays : 198.472059132376
TotalHours : 4763.32941917703
TotalMinutes : 285799.765150622
TotalSeconds : 17147985.9090373
TotalMilliseconds : 17147985909.0373
GG, that is all there is to using a web service to work with holidays. It should be much easier for you than attempting to parse your Outlook calendar. Join me tomorrow when I will talk about a cool function I wrote to determine if a command exists or not in Windows PowerShell.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy