Manipulating Date Ranges with Windows PowerShell


  Hey, Scripting Guy! Question Hey, Scripting Guy! I need to be able to add and subtract dates so that I can use the results in custom queries for various Windows event logs using Windows PowerShell. Is doing this type of date manipulation easy or hard to do with Windows PowerShell? If it is not too difficult to do, could you whip up some examples of searching date ranges? — SH Hey, Scripting Guy! Answer Hello SH, Microsoft Scripting Guy Ed Wilson here. One of the things I used to hate about writing VBScript code was working with dates. It is not that it was difficult, but it did seem a bit arcane. There must have been almost 20 different functions involved in date creation, parsing, and manipulation. Maybe not quite that many, but it seemed so. To make matters worse, I began to develop an aversion to parsing dates, and as a result I would do strange things to avoid parsing dates, which in turn made it more difficult (due to lack of familiarity) when I had to parse a date. So the vicious circle continued to wobble out of control until one day I forced myself to spend a day writing nothing but date manipulation code. Luckily, date parsing and manipulation in Windows PowerShell is much easier. However, you won’t know it is easier until you sit down and spend some time working with the system.datetime .NET Framework object. Why, you may ask, do I refer to the system.datetime .NET Framework object when just a minute ago I was talking about dates? Because a date in Windows PowerShell is an instance of a datetime (you can leave the word “system” off if you wish) object. You can use the Get-Member cmdlet to see what type of object you are working with. The Get-Date cmdlet returns the current date and time. When the current date and time are piped to the Get-Member cmdlet, the members of a System.DateTime .NET Framework class are displayed. This is shown here:

PS C:> Get-Date

Monday, August 02, 2010 10:38:36 AM

PS C:> Get-Date | Get-Member

   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 Compa…
Equals               Method         bool Equals(System.Object value), bool Equals…
GetDateTimeFormats   Method         string[] GetDateTimeFormats(), string[] GetDa…
GetHashCode          Method         int GetHashCode()
GetType              Method         type GetType()
GetTypeCode          Method         System.TypeCode GetTypeCode()
IsDaylightSavingTime Method         bool IsDaylightSavingTime()
Subtract             Method         System.TimeSpan Subtract(System.DateTime valu…
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 for…
ToUniversalTime      Method         System.DateTime ToUniversalTime()
DisplayHint          NoteProperty   Microsoft.PowerShell.Commands.DisplayHintType…
Date                 Property       System.DateTime Date {get;}
Day                  Property     &nbsp ; 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-Stri…

PS C:>

The members, methods, and properties of the System.DateTime .NET Framework class that are displayed are instance methods and properties. This means that they work on an instance of the class. Normally, an instance of a class is created when one uses a constructor. Constructors are detailed on MSDN. For example, the constructor for the System.DateTime class indicates that you can use a number of different ways to create an instance of the class. One constructor will accept three integers for input. However, when I supply the month, day, and year, an error arises. A closer look at the constructor indicates that the constructor wants year, month, and day. When this is supplied, a new instance of a system.datetime object is created. Because no time value was supplied to the constructor, the time is set to midnight. Here the New-Object cmdlet is used to create an instance of a system.datetime object: PS C:> $dte = New-Object system.datetime(8,1,2010)
New-Object : Exception calling “.ctor” with “3” argument(s): “Year, Month, and Day p
arameters describe an unrepresentable DateTime.”
At line:1 char:18
+ $dte = New-Object <<<< system.datetime(8,1,2010)
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationE
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell
PS C:> $dte = New-Object system.datetime(2010,8,1)
PS C:> $dte
Sunday, August 01, 2010 12:00:00 AM
PS C:> Now and today are both static properties from the system.datetime .NET Framework class that return instances of the class. To call a static property, place the class name inside square brackets, use two colons, and then add the property name. To prove that it is a datetime object that is returned, use the gettype method that is always available from any system.object. This is shown here:

PS C:> [datetime]::now

Monday, August 02, 2010 10:48:39 AM

PS C:> ([datetime]::now).gettype()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     DateTime                                 System.ValueType

PS C:> [datetime]::today

Monday, August 02, 2010 12:00:00 AM

PS C:> ([datetime]::today).gettype()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     DateTime                                 System.ValueType

PS C:>

Interestingly enough, the datetime object that is returned via the Get-Date cmdlet is the same object that is returned by the static now property from the datetime class. Use of one or the other is a matter of preference. I generally use the Get-Date cmdlet because it is easier to type. Each methodology is illustrated here: PS C:> [datetime]::now
Monday, August 02, 2010 10:51:32 AM
PS C:> Get-Date
Monday, August 02, 2010 10:51:35 AM
PS C:> After you have a datetime object, you can use the methods that are exposed by that object. For example, you can easily use one of the various methods to add minutes, hours, days, months, years, etc., to the current date to create a new date in the future or in the past (if you pass a negative number):

PS C:> $dte = Get-Date
PS C:> $dte | Get-Member -MemberType method add*

   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)

PS C:> $dte

Monday, August 02, 2010 10:58:58 AM

PS C:> $dte.AddDays(1)

Tuesday, August 03, 2010 10:58:58 AM

PS C:> $dte.AddDays(-1)

Sunday, August 01, 2010 10:58:58 AM

PS C:> $dte.AddHours(8)

Monday, August 02, 2010 6:58:58 PM

PS C:> $dte.AddHours(-8)

Monday, August 02, 2010 2:58:58 AM

PS C:>

This can easily be incorporated with a cmdlet such as Get-EventLog. If I want to see event log entries from the application log that occurred in the last hour, I can use code that looks like this:

PS C:> Get-EventLog -LogName application -After $dte.AddMinutes(-60)

   Index Time          EntryType   Source                 InstanceID Message
   —– —-          ———   ——                 ———- ——-
   19016 Aug 02 10:24  Information Office Software P…   1073742827 The Software…
   19015 Aug 02 10:24  Information Office Software P…   1073742827 The Software…
   19014 Aug 02 10:24  Information Office Software P…   1073742827 The Software…
   19013 Aug 02 10:24  0           Office Software P…   1073742726 The Software…
   19012 Aug 02 10:24  Information Office Software P…   1073742890 Initializati…
   19011 Aug 02 10:24  Information Office Software P…   1073742724 The Software…

PS C:>

When working with two datetime objects, you can subtract them and a timespan object is returned. This is shown here:

PS C:> $dte = Get-Date
PS C:> $sDate = Ge


Discussion is closed.

Feedback usabilla icon