July 8th, 2011

Use PowerShell to Get the Number of the Week of the Year

Summary: Learn how to use Windows PowerShell to easily get the number of the week of the year.

Microsoft Scripting Guy, Ed Wilson, is here. It seems that at times things appear to be too hard. At other times, things that I figure might be too hard, end up being super simple. I guess this is why I was never that good at project estimation tasks. A case in point is the solar collector that I decided to build for our swimming pool. The first task is to build the frame to support the collectors, then it needs a little plumbing to tie it into the pool. I figured the entire task could be accomplished in one weekend. Six weeks later, the frame itself is not even completed—and that is with Dr. Scripto’s help. The frame and Dr. Scripto appear in the following photo.

Photo of solar frame

Today I decided that I needed to know the number of the week of the year. For example, is this the 23rd week of the year or what? The reason is that I am trying to be 30 days ahead with the Hey! Scripting Guy Blog by the time that December rolls around. Because I publish a new blog every single day, it means that if I want to take a week off, I need to be at least 10 days ahead. This is because I do not like to write, edit, and publish a blog all in the same day. Plus the fact that when I come back from a week of vacation, it takes several days just to get caught up on meeting requests, email, and phone messages. Therefore, I do not want to worry about a Hey! Scripting Guy blog as well when I return from a holiday.

So with all the normal days off in December and in January, coupled with taking a couple weeks of holiday with the Scripting Wife, I always like to be 30 days ahead by the time that December 1 rolls around. This buffer also gives me time to begin working on Scripting Games events, which takes an awful lot of work as well.

At first I figured that I should be able to get the week of the year by using Get-Date. I knew there was the DayOfYear property, so I figured there might be a WeekOfYear property as well. Unfortunately, such was not the case. The Get-Member command and its associated output are shown here.

PS C:\Users\ed> get-date | gm

 

   TypeName: System.DateTime

 

Name                 MemberType     Definition

—-                 ———-     ———-

Add                  Method         System.DateTime Add(System.TimeSpan value)

AddDays              Method         System.DateTime AddDays(double value)

AddHours             Method         System.DateTime AddHours(double value)

AddMilliseconds      Method         System.DateTime AddMilliseconds(double value)

AddMinutes           Method         System.DateTime AddMinutes(double value)

AddMonths            Method         System.DateTime AddMonths(int months)

AddSeconds           Method         System.DateTime AddSeconds(double value)

AddTicks             Method         System.DateTime AddTicks(long value)

AddYears             Method         System.DateTime AddYears(int value)

CompareTo            Method         int CompareTo(System.Object value), int CompareTo(System.DateTime value)

Equals               Method         bool Equals(System.Object value), bool Equals(System.DateTime value)

GetDateTimeFormats   Method         string[] GetDateTimeFormats(), string[] GetDateTimeFormats(System.IFormatProvide…

GetHashCode          Method         int GetHashCode()

GetType              Method         type GetType()

GetTypeCode          Method         System.TypeCode GetTypeCode()

IsDaylightSavingTime Method         bool IsDaylightSavingTime()

Subtract             Method         System.TimeSpan Subtract(System.DateTime value), System.DateTime Subtract(System…

ToBinary             Method         long ToBinary()

ToFileTime           Method         long ToFileTime()

ToFileTimeUtc        Method         long ToFileTimeUtc()

ToLocalTime          Method         System.DateTime ToLocalTime()

ToLongDateString     Method         string ToLongDateString()

ToLongTimeString     Method         string ToLongTimeString()

ToOADate             Method         double ToOADate()

ToShortDateString    Method         string ToShortDateString()

ToShortTimeString    Method         string ToShortTimeString()

ToString             Method         string ToString(), string ToString(string format), string ToString(System.IForma…

ToUniversalTime      Method         System.DateTime ToUniversalTime()

DisplayHint          NoteProperty   Microsoft.PowerShell.Commands.DisplayHintType DisplayHint=DateTime

Date                 Property       System.DateTime Date {get;}

Day                  Property       System.Int32 Day {get;}

DayOfWeek            Property       System.DayOfWeek DayOfWeek {get;}

DayOfYear            Property       System.Int32 DayOfYear {get;}

Hour                 Property       System.Int32 Hour {get;}

Kind                 Property       System.DateTimeKind Kind {get;}

Millisecond          Property       System.Int32 Millisecond {get;}

Minute               Property       System.Int32 Minute {get;}

Month                Property       System.Int32 Month {get;}

Second               Property       System.Int32 Second {get;}

Ticks                Property       System.Int64 Ticks {get;}

TimeOfDay            Property       System.TimeSpan TimeOfDay {get;}

Year                 Property       System.Int32 Year {get;}

DateTime             ScriptProperty System.Object DateTime {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHin…

 

PS C:\Users\ed>

“Major bummer,” I thought. Now I figure it is going to be pain to retrieve the information. I open up MSDN in my Internet Explorer 9 browser, and begin searching. It does indeed look like it will be a pain. I have to create calendar rules, calendar types, and all kinds of culture specific things (such as when the first day of the week appears, and how to determine the first week of the year). Ugh, I hate messing around with all that stuff. Whine whine whine whine whine (as the Scripting Wife would say).

But I am positive that I have seen a week of the year before, and it did not involve a lot of messy .NET Framework programming. I decided to look up the help on Get-Date to be on the safe side before I started all that work. In the –uformat section I found my answer…I can use the %V value for the UFormat parameter. This is shown here where the command tells me that I am in the 23rd week as I write this Hey! Scripting Guy blog.

PS C:\Users\ed> get-date -UFormat %V

23

PS C:\Users\ed>

I decided to write a quick function to return a custom DateTime object. At first, I was only going to return the week of the year, but hey, I might want to know what that week of the year is associated with, and so I incorporated a call to the Add-Member Windows PowerShell cmdlet. The complete Get-ExtendedDate function is shown here.

Get-ExtendedDate Function

function Get-ExtendedDate

{

 $a = get-date

  add-member -MemberType scriptmethod -name GetWeekOfYear `

     -value {get-date -uformat %V} -inputobject $a

 $a

 } #end function Get-ExtendedDate

In the Get-ExtendedDate function, I first obtain a copy of the System.DateTime object by calling the Get-Date cmdlet. I store the returned object in the $a variable. This is shown here.

$a = get-date

The object stored in the $a variable is the base object upon which I will add an additional member. There are several different types of members to add to an object—I am adding a ScriptMethod member because I want to perform a calculation when the member is called. To use the Add-Member Windows PowerShell cmdlet, I specify the type of member to add, a name for the member, how the member value is obtained, and an object upon which to add the member. The command is shown here.

add-member -MemberType scriptmethod -name GetWeekOfYear `

     -value {get-date -uformat %V} -inputobject $a

The last thing I need to do is to return the modified object that is stored in the $a variable, and close my curly brackets as shown here.

$a

 } #end function Get-ExtendedDate

When I call the Get-ExtendedDate function, a standard DateTime object is returned. Because it is a standard DateTime, the display specifier returns the standard display. This is shown in the following image.

Image of command output

If I pipe the results of the function to the Get-Member cmdlet, I can tell that the additional member is added to the DateTime object. The command to do this is shown here.

Get-ExtendedDate | get-member

The command and its associated output are shown in the following image.

Image of command output

To access the new ScriptMethod, I have a number of options. The one I have a tendency to use is to call the method directly from the function by using a dotted notation. It sounds more complicated than it is. I use a pair of parentheses to surround the function and then call the method. The only hard part is to remember that I created a method, and therefore an empty pair of parentheses is required at the end of the method name. This is shown here.

PS C:\Users\ed> (Get-ExtendedDate).getWeekOfYear()

23

Of course, one can always store the resulting object into a variable, and call the method that way. This is shown here.

PS C:\Users\ed> $b = Get-ExtendedDate

PS C:\Users\ed> $b.GetWeekOfYear()

23

In fact, it is because you can store the object in a variable that I decided to add my ScriptMethod to the DateTime object in the first place. I can use any of the properties and methods of a normal DateTime object in addition to calling my custom ScriptMethod. For example, I might want to do something like the following:

“Today is $($b.ToShortDateString())”

“There are $(365 – $($b.DayOfYear)) days left in the year.”

“This means there are $(52 – $($b.GetWeekOfYear())) weeks left in the year.”

In short, I have complete access to the DateTime object, and I have access to my new ScriptMethod as well. Dude, that makes for a cool solution. By the way, here are the previous commands and their associated output.

Image of command output

Well, that is all there is to extending the DateTime object to include the GetWeekOfYear ScriptMethod. Join me tomorrow for more Windows PowerShell goodness.

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

Author

0 comments

Discussion are closed.