{"id":8261,"date":"2015-01-21T00:01:00","date_gmt":"2015-01-21T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2015\/01\/21\/adding-and-subtracting-dates-with-powershell\/"},"modified":"2019-02-18T10:35:52","modified_gmt":"2019-02-18T17:35:52","slug":"adding-and-subtracting-dates-with-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/adding-and-subtracting-dates-with-powershell\/","title":{"rendered":"Adding and Subtracting Dates with PowerShell"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Microsoft Scripting Guy, Ed Wilson, talks about adding and subtracting dates with Windows PowerShell.<\/span>\nMicrosoft Scripting Guy, Ed Wilson, is here. One of the things I really like about Windows PowerShell is the way it simplifies adding and subtracting from dates. For example, if I want to find users who haven&rsquo;t logged in to the domain for 120 days, I need to be able to create a date that was 120 days ago. Then I need to get the date of their last log-in, and see if that date is more recent than 120 days ago.\nI may need to do the same thing with the last time that files were accessed or to examine the date that print jobs were submitted to a print server. I may simply want to see all events from the security log that occurred within a specific date range. I may want to see how many days until a user&#8217;s password expires so that I can warn them when the password comes within 10 days of expiring.\nWhatever the need, quite often dates come into play. When I know how to create a specific <b>DateTime<\/b> object, whether in the past, in the future, or even for the present, I can use that <b>DateTime<\/b> object as an input parameter for other Windows PowerShell cmdlets.\nThere are six core Windows PowerShell cmdlets that accept <b>DateTime<\/b> objects as input parameters. These cmdlets are:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Get-Command -ParameterType [datetime] | ft -AutoSize<\/p>\n<p style=\"margin-left:30px\">CommandType Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ModuleName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">&#8212;&#8212;&#8212;&#8211; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8212;&#8212;&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">Cmdlet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get-Date&nbsp;&nbsp;&nbsp;&nbsp; Microsoft.PowerShell.Utility&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">Cmdlet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get-EventLog Microsoft.PowerShell.Management<\/p>\n<p style=\"margin-left:30px\">Cmdlet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get-Job&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Microsoft.PowerShell.Core&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">Cmdlet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; New-TimeSpan Microsoft.PowerShell.Utility&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">Cmdlet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set-Date&nbsp;&nbsp;&nbsp;&nbsp; Microsoft.PowerShell.Utility&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">Cmdlet&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Test-Path&nbsp;&nbsp;&nbsp; Microsoft.PowerShell.Management\n<span style=\"font-size:12px\">To find which parameters accept a <\/span><b style=\"font-size:12px\">DateTime<\/b><span style=\"font-size:12px\"> object, I can use the <\/span><b style=\"font-size:12px\">Get-Help<\/b><span style=\"font-size:12px\"> cmdlet and look at the syntax for the various parameter sets. This technique is shown here for the <\/span><b style=\"font-size:12px\">Test-Path<\/b><span style=\"font-size:12px\"> cmdlet:<\/span><\/p>\n<p style=\"margin-left:30px\">PS C:&gt; (Get-Help test-path).syntax<\/p>\n<p style=\"margin-left:30px\">Test-Path [-Path] &lt;String[]&gt; [-Credential &lt;PSCredential&gt;] [-Exclude &lt;String[]&gt;]<\/p>\n<p style=\"margin-left:30px\">[-Filter &lt;String&gt;] [-Include &lt;String[]&gt;] [-IsValid] [-PathType &lt;TestPathType&gt;]<\/p>\n<p style=\"margin-left:30px\">[-UseTransaction [&lt;SwitchParameter&gt;]] [&lt;CommonParameters&gt;]<\/p>\n<p style=\"margin-left:30px\">Test-Path [-Credential &lt;PSCredential&gt;] [-Exclude &lt;String[]&gt;] [-Filter &lt;String&gt;]<\/p>\n<p style=\"margin-left:30px\">[-Include &lt;String[]&gt;] [-IsValid] [-PathType &lt;TestPathType&gt;] -LiteralPath<\/p>\n<p style=\"margin-left:30px\">&lt;String[]&gt; [-UseTransaction [&lt;SwitchParameter&gt;]] [&lt;CommonParameters&gt;]<\/p>\n<p style=\"margin-left:30px\">Test-Path [-NewerThan &lt;DateTime&gt;] [-OlderThan &lt;DateTime&gt;] [&lt;CommonParameters&gt;]<\/p>\n<h2>Adding dates and times&mdash;the easy way<\/h2>\n<p>If I want to add hours to a <b>DateTime<\/b> object, all I need to do is to create an instance of a <b>DateTime<\/b> object, and call the <b>AddHours<\/b> method. Here is an example using the <b>Get-Date<\/b> cmdlet:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; (Get-Date).AddHours(2)<\/p>\n<p style=\"margin-left:30px\">Friday, January 16, 2015 6:27:46 PM\nI can also use an intermediate variable to hold the <b>DateTime<\/b> object and to call the method. This technique appears here:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $dte = Get-Date<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $dte.AddHours(3)<\/p>\n<p style=\"margin-left:30px\">Friday, January 16, 2015 7:29:00 PM\nIt is also possible to convert a string into a <b>DateTime<\/b> object by using the [dateTime] type accelerator. I first create a specific date and time, and then I call the <b>AddHours<\/b> method:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $dte = Get-Date<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; $dte.AddHours(3)<\/p>\n<p style=\"margin-left:30px\">Friday, January 16, 2015 7:29:00 PM\nIf I want to add days, it is the same technique, but I call the <b>AddDays<\/b> method instead of <b>AddHours<\/b>. This technique is shown here by using the <b>Get-Date<\/b> cmdlet:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Get-Date<\/p>\n<p style=\"margin-left:30px\">Friday, January 16, 2015 4:32:57 PM<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; (Get-date).AddDays(12)<\/p>\n<p style=\"margin-left:30px\">Wednesday, January 28, 2015 4:33:00 PM\nI can add lots of stuff to <b>DateTime<\/b> objects. Here is a list of the various <b>Add<\/b> methods.<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Get-date | Get-Member -MemberType Method -Name a*<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; TypeName: System.DateTime<\/p>\n<p style=\"margin-left:30px\">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MemberType Definition&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">Add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp; datetime Add(timespan value)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">AddDays&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddDays(double value)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">AddHours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddHours(double value)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">AddMilliseconds Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddMilliseconds(double value)<\/p>\n<p style=\"margin-left:30px\">AddMinutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddMinutes(double value)&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">AddMonths&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddMonths(int months)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">AddSeconds&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddSeconds(double value)&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">AddTicks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddTicks(long value)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">AddYears&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Method&nbsp;&nbsp;&nbsp;&nbsp; datetime AddYears(int value)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\nIf I want to create a <b>DateTime<\/b> object that represents a date in the past, I still use the appropriate <b>Add<\/b> method, but I supply a negative number. So in the following example, I create a <b>DateTime<\/b> object that is 12 days in the past:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Get-Date<\/p>\n<p style=\"margin-left:30px\">Friday, January 16, 2015 4:34:53 PM<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; (Get-Date).adddays(-12)<\/p>\n<p style=\"margin-left:30px\">Sunday, January 4, 2015 4:35:12 PM\nThe technique works exactly the same way for subtracting hours. Here, I create a <b>DateTime<\/b> object that is five hours in the past:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; Get-Date<\/p>\n<p style=\"margin-left:30px\">Friday, January 16, 2015 4:36:24 PM<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; (Get-Date).AddHours(-5)<\/p>\n<p style=\"margin-left:30px\">Friday, January 16, 2015 11:36:46 AM\nI can even combine methods, so I do not have to add -1 day and then add -2 hours by using intermediate expressions (unless I want to). Here is an example of using intermediate expressions:<\/p>\n<p style=\"margin-left:30px\">$dte = Get-Date<\/p>\n<p style=\"margin-left:30px\">$dte = $dte.AddDays(-1)<\/p>\n<p style=\"margin-left:30px\">$dte = $dte.AddHours(-2)<\/p>\n<p style=\"margin-left:30px\">$dte\nBut I can simplify this into a single line as shown here:<\/p>\n<p style=\"margin-left:30px\">PS C:&gt; ((Get-Date).AddDays(-1)).addhours(-2)<\/p>\n<p style=\"margin-left:30px\">Thursday, January 15, 2015 2:42:28 PM\nThe advantage of using the intermediate expressions is it is probably easier to read.<\/p>\n<h2>Some fun with DateTime objects<\/h2>\n<p>Because it is so easy to use WMI to find the remaining runtime on a laptop battery, and it is so easy to add minutes, I created a simple script to let me know when my laptop will shut down. I use the <b>Get-CimInstance<\/b> cmdlet to retrieve the <b>Win32_Battery<\/b> WMI class. I then choose the <b>EstimatedRunTime<\/b> property (which displays in minutes remaining on the battery), and I store the result in the <b>$MinutesRunTime<\/b> variable.\nI then use the <b>AddMinutes<\/b> method from the <b>DateTime<\/b> object that I get from <b>Get-Date<\/b>, and I display the result. Because I want to perform the date calculation before I display the string, I use the subexpression <b>$()<\/b> to force the evaluation of the expression first. Here is the script:<\/p>\n<p style=\"margin-left:30px\">$MinutesRunTime = (Get-CimInstance win32_battery).EstimatedRunTime\n&#8220;The laptop will shut down at $((Get-Date).AddMinutes($MinutesRunTime))&#8221;<\/p>\n<p style=\"margin-left:30px\"><b>Note&nbsp;<\/b> I only have an instance of <b>Win32_Battery<\/b> if I am using a laptop or other portable device (such as a Microsoft Surface). Also, if I am plugged in and charging, it does not display accurate results.\nThat is all there is to adding and subtracting dates. Date Time Week will continue tomorrow when I will talk about more cool stuff.\nI invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.\n<b>Ed Wilson, Microsoft Scripting Guy<\/b><span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about adding and subtracting dates with Windows PowerShell. Microsoft Scripting Guy, Ed Wilson, is here. One of the things I really like about Windows PowerShell is the way it simplifies adding and subtracting from dates. For example, if I want to find users who haven&rsquo;t logged in to [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[13,3,4,45],"class_list":["post-8261","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-dates-and-times","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about adding and subtracting dates with Windows PowerShell. Microsoft Scripting Guy, Ed Wilson, is here. One of the things I really like about Windows PowerShell is the way it simplifies adding and subtracting from dates. For example, if I want to find users who haven&rsquo;t logged in to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/8261","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=8261"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/8261\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=8261"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=8261"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=8261"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}