The Wonders of Date Math using Windows PowerShell

Larry Hayden posted a query about dates at:
http://techtasks.com/bookmarks/powershell/2006/09/interview-with-a-scripter-jeffrey-snover/


He has a script which gets all the Application Events that happened TODAY:


————————————————————
$today = [DateTime]::Today
$Events = Get-Eventlog -New 1024 Application | Where {$Today -le $_.TimeWritten}
$Events |Group EntryType,Source |Format-Table Count,Name -Auto
————————————————————


What Larry really wants is the Application Events that happend in the last 24 hours.  We’ll Larry – you’re in luck because PowerShell leverages the awesome .NET frameworks which support Date Math.  Check this out:


PS> [DateTime]::Now  |Get-Member -MemberType Method

   TypeName: System.DateTime
Name                 MemberType Definition
—-                 ———- ———-
Add                  Method     System.DateTime Add(TimeSpan value)
AddDays              Method     System.DateTime AddDays(Double value)
AddHours             Method     System.DateTime AddHours(Double value)
AddMilliseconds      Method     System.DateTime AddMilliseconds(Double v…
AddMinutes           Method     System.DateTime AddMinutes(Double value)
AddMonths            Method     System.DateTime AddMonths(Int32 months)
AddSeconds           Method     System.DateTime AddSeconds(Double value)
AddTicks             Method     System.DateTime AddTicks(Int64 value)
AddYears             Method     System.DateTime AddYears(Int32 value)
CompareTo            Method     System.Int32 CompareTo(Object value), Sy…
Equals               Method     System.Boolean Equals(Object value), Sys…
GetDateTimeFormats   Method     System.String[] GetDateTimeFormats(), Sy…
GetHashCode          Method     System.Int32 GetHashCode()
GetType              Method     System.Type GetType()
GetTypeCode          Method     System.TypeCode GetTypeCode()

IsDaylightSavingTime Method     System.Boolean IsDaylightSavingTime()
Subtract             Method     System.TimeSpan Subtract(DateTime value)…
ToBinary             Method     System.Int64 ToBinary()
ToFileTime           Method     System.Int64 ToFileTime()
ToFileTimeUtc        Method     System.Int64 ToFileTimeUtc()
ToLocalTime          Method     System.DateTime ToLocalTime()
ToLongDateString     Method     System.String ToLongDateString()
ToLongTimeString     Method     System.String ToLongTimeString()
ToOADate             Method     System.Double ToOADate()
ToShortDateString    Method     System.String ToShortDateString()
ToShortTimeString    Method     System.String ToShortTimeString()
ToString             Method     System.String ToString(), System.String …
ToUniversalTime      Method     System.DateTime ToUniversalTime()


So lets see this in action:


PS> [DateTime]::Now
Saturday, September 16, 2006 9:29:29 PM

PS> [DateTime]::Now.AddDays(1)
Sunday, September 17, 2006 9:29:29 PM

PS> [DateTime]::Now.AddDays(7)
Saturday, September 23, 2006 9:29:30 PM

PS> [DateTime]::Now.AddDays(-1)
Friday, September 15, 2006 9:29:30 PM

PS> [DateTime]::Now.AddDays(-7)
Saturday, September 09, 2006 9:29:31 PM


Yes that’s right – you can provide negative numbers to AddDays() and it will do the old Way-Back Machine trick.


So all you have to do to get the Application Events for the last 24 hours is:


————————————————————
$24HoursAgo = [DateTime]::Now.AddHours(-24)
$Events = Get-Eventlog -New 1024 Application | Where {$24HoursAgo -le $_.TimeWritten}
$Events |Group EntryType,Source |Format-Table Count,Name -Auto
————————————————————


Date math VERY simple to learn once you know that it is possible and it is very useful so take a couple of minutes and try it out – it’s an investment that will pay rich dividends over the next few years.


Here is how you find out which processes have been started in the last hour:
PS> $1HourAgo = [DateTime]::Now.AddHours(-1)
PS> Get-Process |where {$_.StartTime -ge $1HourAgo}


Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
——-  ——    —–      —– —–   ——     — ———–
     52       2     1244       9520    51     0.13   4240 notepad
    216       8    32296      31008   173     4.39   2420 powershell
    117       4     3124       5564    54     0.06   5276 SearchFilterHost
    287       5     4044       6972    58     0.17   2380 SearchProtocol…


Here is how you can find out what type of files you have been working on most in the last month:


PS> dir \ -Recurse | where {$1MonthAgo -le $_.LastWriteTime} |
>>  Group Extension | sort -Descending Count |Select -First 10 |
>>  Format-Table Count,Name -AutoSize


Count Name
—– —-
  297 .cs
  249 .zip
  128 .ps1
   96 .txt
   90 .log
   51 .xml
   30 .dll
   21 .msg
   20 .dbf
   15 .url


By the way – check out the readability of the scripts required to accomplish this.  Imagine you wrote this script and the day after you installed it on all your production servers, you got hit by a beer truck.  What are the odds that the person replacing you would be able to understand and maintain this script?  I think they are pretty good.


So avoid beer trucks that drive at high speeds on the sidewalk but write your scripts like you might not be quick enough one day.  🙂  (And apologizes in advance to anyone that has recently lost a loved one to a stray beer-truck.)


Cheers!


Jeffrey Snover [MSFT]
Windows PowerShell/Aspen Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx


PSMDTAG:DOTNET: DateTime


PSMDTAG:FAQ: How do I events that occured in the last 24 hours?