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 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  
; 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
xception
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell
.Commands.NewObjectCommand
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
0 comments