{"id":3318,"date":"2013-06-29T00:01:00","date_gmt":"2013-06-29T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2013\/06\/29\/weekend-scripter-understanding-timespan-objects\/"},"modified":"2013-06-29T00:01:00","modified_gmt":"2013-06-29T00:01:00","slug":"weekend-scripter-understanding-timespan-objects","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-understanding-timespan-objects\/","title":{"rendered":"Weekend Scripter: Understanding TimeSpan Objects"},"content":{"rendered":"<p><strong style=\"font-size: 12px\">Summary<\/strong><span style=\"font-size: 12px\">: Guest bloggers, June Blender and Justin Hall, investigate strange behavior with <\/span><strong style=\"font-size: 12px\">TimeSpan<\/strong><span style=\"font-size: 12px\"> objects in the <\/span><strong style=\"font-size: 12px\">Search-ADAccount<\/strong><span style=\"font-size: 12px\"> cmdlet.<\/span><\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Today we have a blog written by two guests: <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/june+blender\/\" target=\"_blank\">June Blender<\/a> and Justin Hall. First, a little bit about Justin (June is already well known to our readers).<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4810.wes-6-29-13-1.jpg\"><img decoding=\"async\" title=\"Photo of Justin Hall\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4810.wes-6-29-13-1.jpg\" alt=\"Photo of Justin Hall\" \/><\/a><\/p>\n<p style=\"padding-left: 30px\">Justin Hall is a technical writer and editor who has covered Active Directory and related technologies at Microsoft since 2001. He publishes articles on Microsoft TechNet and contributes to the <a href=\"http:\/\/blogs.technet.com\/b\/activedirectoryua\/\" target=\"_blank\">Active Directory Documentation Team Blog<\/a>.<\/p>\n<h3>Justin explains a misrepresentation&hellip;<\/h3>\n<p><a href=\"http:\/\/mvp.microsoft.com\/en-us\/mvp\/Michael%20B.%20Smith-10415\" target=\"_blank\">Michael Smith<\/a>, an Active Directory MVP, recently mentioned an error in the documentation for the <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/ee617247.aspx\" target=\"_blank\">Search-ADAccount<\/a> cmdlet. The examples in the Help misrepresent the <strong>TimeSpan<\/strong> parameter by treating the argument as if it was a number of days, when it is actually a number of ticks. The examples showed how to use <strong>TimeSpan<\/strong> with a switch parameter, such as <strong>AccountExpiring<\/strong> or <strong>AccountInactive<\/strong>. But because the examples mistreated the <strong>TimeSpan<\/strong> argument, they produce unexpected results. For instance, the example for <strong>AccountExpiring<\/strong> said:<\/p>\n<p>The following example shows how to specify a search for accounts that expire in the next 10 days.<\/p>\n<p style=\"padding-left: 30px\">-AccountExpiring -TimeSpan 10<\/p>\n<p>But that example really searches for accounts that expire in 10 ticks, or .001 milliseconds. For the <strong>TimeSpan<\/strong> parameter argument to be 10 days, it must be presented like this:<\/p>\n<p style=\"padding-left: 30px\">-TimeSpan &ldquo;10&rdquo;<\/p>\n<p><span style=\"font-size: 12px\">&nbsp; &nbsp; &nbsp;-or-<\/span><\/p>\n<p style=\"padding-left: 30px\">-TimeSpan 10.00:00:00<\/p>\n<p>This seemed like a simple documentation error to me. And because Windows PowerShell documentation is updatable, I could correct the Help topic, any then user who runs <strong>Update-Help<\/strong> will download the corrected Help for that cmdlet. So I asked June how to make the correction because she has much more expertise with Windows PowerShell documentation.<\/p>\n<p>June reviewed the feedback and the topic and saw something odd. Why was it that when a parameter takes a <strong>TimeSpan<\/strong> object and you give it the integer 10, it interprets it as 10 ticks, and if you give it 10:00, it interprets it as 10 hours (not 10 days), but if you give it &#8220;10&#8221; as a string, it interprets it as 10 days? I will stop here so June can better explain what she discovered.<\/p>\n<h3>June explains&#8230;<\/h3>\n<p>Yes, as Justin said, our MVP friend, Michael Smith, was correct indeed, but we couldn&#8217;t figure out why. So we turned to Windows PowerShell super-developer, Lee Holmes, for the answer. (Lee wrote a more advanced blog post about this question, too. Take a peek at <a href=\"http:\/\/blogs.msdn.com\/b\/powershell\/archive\/2013\/06\/11\/understanding-powershell-s-type-conversion-magic.aspx\" target=\"_blank\">Understanding PowerShell&#8217;s Type Conversion Magic<\/a>.)<\/p>\n<p>It turns out that it&#8217;s all about <em>constructors<\/em>. When we use a parameter value to create a new object, such as using the <strong>TimeSpan<\/strong> parameter of the <strong>Search-ADAccount<\/strong> cmdlet to create a new <strong>TimeSpan<\/strong> object, Windows PowerShell uses the constructors for the <strong>TimeSpan<\/strong> class in the .NET library, because&hellip;well&hellip;there&#8217;s no other way to do it. And the interesting behavior that we saw results from the <strong>TimeSpan<\/strong> class constructors.<\/p>\n<p>I&#8217;ll explain more about constructors soon, and we&#8217;ll take a trip to the Microsoft .NET library to look at the constructors for the <strong>TimeSpan<\/strong> class. While we&#8217;re doing this, keep in mind that you can use this technique to figure out what Windows PowerShell needs to do to interpret the values of ANY<em> <\/em>parameter. Windows PowerShell might have some additional help for you, but when you learn about constructors, you have another detective tool in your scripting toolbox.<\/p>\n<h2>About .NET constructors<\/h2>\n<p>A .NET constructor tells you how to create or &#8220;construct&#8221; an instance of a .NET class. Every .NET class that allows you to create instances has at least one constructor, and some have many constructors, so they provide many different ways to create the object.<\/p>\n<p>You can think of a group of constructors for a .NET class as the <em>parameter sets<\/em> for creating an instance of that .NET class. They tell you all of the valid parameter and parameter value combinations.<\/p>\n<p>You can also think of constructors as recipes for creating an instance of the class. When there are different ways to create the class, there are multiple recipes, all with different ingredients.<\/p>\n<p>Let&#8217;s look at the constructors for the <strong>TimeSpan<\/strong> object. To see them, go to the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/269ew577.aspx\" target=\"_blank\">System.Timespan<\/a> class page in MSDN.&nbsp; The <strong>TimeSpan Constructor<\/strong> is listed as the first subtopic.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4075.wes-6-29-13-2.png\"><img decoding=\"async\" title=\"Image of menu\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4075.wes-6-29-13-2.png\" alt=\"Image of menu\" \/><\/a><\/p>\n<p>Click <strong>TimeSpan Constructor<\/strong> (or scroll down to the first item on the <strong>TimeSpan<\/strong> page). These should look somewhat familiar&mdash;like parameter sets. Each one gives you a recipe for creating a <strong>TimeSpan<\/strong> object.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2045.wes-6-29-13-3.png\"><img decoding=\"async\" title=\"Image of menu\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2045.wes-6-29-13-3.png\" alt=\"Image of menu\" \/><\/a><\/p>\n<p>The <strong>TimeSpan<\/strong> class has four constructors, or four different ways of creating a time span.<\/p>\n<p>Let&#8217;s look at them one at a time. Here&#8217;s the first constructor:<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-size: 12px\">TimeSpan(Int64)<\/span><\/p>\n<p>The first constructor creates a <strong>TimeSpan<\/strong> object from one Int64 (one big number). The description explains that when you create a time span from just one number, .NET interprets the number as the number of <strong>ticks<\/strong>. Interesting, eh?<\/p>\n<p>The second constructor takes three 32-bit numbers:<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-size: 12px\">TimeSpan(Int32, Int32, Int32)<\/span><\/p>\n<p>The description says that when you use three numbers to create a <strong>TimeSpan<\/strong> object, .NET interprets the three numbers as <strong>hours, minutes, and seconds<\/strong>&mdash;in that order.<\/p>\n<p>The third constructor takes four 32-bit numbers:<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-size: 12px\">TimeSpan(Int32, Int32, Int32, Int32)<\/span><\/p>\n<p>When you create a <strong>TimeSpan<\/strong> object with four numbers, .NET interprets them as <strong>days, hours, minutes, and seconds<\/strong>.<\/p>\n<p>The last constructor takes five 32-bit numbers:<\/p>\n<p style=\"padding-left: 30px\">TimeSpan(Int32, Int32, Int32, Int32, Int32)<\/p>\n<p>.NET interprets the numbers as <strong>days, hours, minutes, seconds, and milliseconds<\/strong>.<\/p>\n<p>Aha! So this explains most of what we see when we use the <strong>TimeSpan<\/strong> parameter of <strong>Search-ADAccount<\/strong>, or other parameters that take <strong>TimeSpan<\/strong> values, such as the <strong>IdleTimeOut<\/strong> and <strong>IdleDuration<\/strong> parameters of <strong>New-ScheduledJobObject<\/strong>.&nbsp;<span style=\"font-size: 12px\">For the following examples, I&#8217;m going to use the <\/span><strong style=\"font-size: 12px\">IdleTimeout<\/strong><span style=\"font-size: 12px\"> parameter of <\/span><strong style=\"font-size: 12px\">New-ScheduledJobObject<\/strong><span style=\"font-size: 12px\">, because the commands are a bit simpler, but the idea is exactly the same as <\/span><strong style=\"font-size: 12px\">Search-ADAccount<\/strong><span style=\"font-size: 12px\">.<\/span><\/p>\n<p>When the value of <strong>IdleTimeout<\/strong> is one number, such as 10, it&#8217;s interpreted as the number of ticks, or 10 ticks, because it uses the first constructor, TimeSpan(Int64), which interprets its value as ticks.<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/2046.A.PNG\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/2046.A.PNG\" alt=\"Image of command output\" \/><\/a>&nbsp;<\/p>\n<p>When the value of <strong>IdleTimeout<\/strong> is two or three numbers (if you give Windows PowerShell two numbers, it fills in the third for you), it uses the second constructor, TimeSpan(Int32, Int32, Int32), which interprets the values as hours, minutes, and seconds. In this case, the 10 is interpreted as 10 hours.<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/2350.B.PNG\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/2350.B.PNG\" alt=\"Image of command output\" \/><\/a>&nbsp;<\/p>\n<p>As the constructors showed, to get days, you need to give it four numbers. So, when the 10 is the first of four numbers, it&#8217;s interpreted as 10 days.<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/8130.C.PNG\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/8130.C.PNG\" alt=\"Image of command output\" \/><\/a>&nbsp;<\/p>\n<p>And if you give it five numbers, it uses the last constructor. The first number is still interpreted as days and the last number is interpreted as milliseconds.<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/1145.D.PNG\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/1145.D.PNG\" alt=\"Image of command output\" \/><\/a>&nbsp;<\/p>\n<p>So why does the string value &#8220;10&#8221; produce days, as Michael noted, instead of hours or something else? For this, we have to look at the methods of the <strong>TimeSpan<\/strong> class. Windows PowerShell needs a method that converts a string into a <strong>TimeSpan<\/strong> object. The <strong>TimeSpan<\/strong> class has one&mdash;it&#8217;s called <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/se73z7b9.aspx\" target=\"_blank\">Parse<\/a>. The <strong>Parse<\/strong> method is pretty complex, because strings can vary so much.<\/p>\n<p style=\"padding-left: 30px\">[ws][-]{ d | [d.]hh:mm[:ss[.ff]] }[ws]<\/p>\n<p>But if you give the <strong>Parse<\/strong> method a string, it interprets the first non-white space characters as days.<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/0456.E.PNG\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/0456.E.PNG\" alt=\"Image of command output\" \/><\/a><\/p>\n<h3>And back to Justin&#8230;<\/h3>\n<p>So that explains why the examples were producing unexpected results. And the difference in this case is significant because if you are searching for accounts that are set to expire, any accounts that expire in the next 10 days are interesting, and accounts that expire in the next .001 milliseconds probably don&rsquo;t exist.<\/p>\n<p>Special thanks to Michael Smith for alerting us to the documentation problem; to Lee Holmes for educating us about how this works; and to June for asking why, investigating the cause of the error, and writing this explanation in language that is easy to understand.<\/p>\n<p>~Justin and June<\/p>\n<p>Thank you, Justin and June. This is an awesome post and a great explanation! Join me tomorrow when I will talk about chasing errant ACLs in a folder full of files. It is cool&mdash;trust me.<\/p>\n<p>I 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=\"mailto: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.<\/p>\n<p><strong>Ed Wilson, Microsoft Scripting Guy<\/strong><span style=\"font-size: 12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Guest bloggers, June Blender and Justin Hall, investigate strange behavior with TimeSpan objects in the Search-ADAccount cmdlet. Microsoft Scripting Guy, Ed Wilson, is here. Today we have a blog written by two guests: June Blender and Justin Hall. First, a little bit about Justin (June is already well known to our readers). Justin Hall [&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":[51,56,370,429,3,4,430,61,45],"class_list":["post-3318","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-guest-blogger","tag-june-blender","tag-justin-hall","tag-scripting-guy","tag-scripting-techniques","tag-timespan","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Guest bloggers, June Blender and Justin Hall, investigate strange behavior with TimeSpan objects in the Search-ADAccount cmdlet. Microsoft Scripting Guy, Ed Wilson, is here. Today we have a blog written by two guests: June Blender and Justin Hall. First, a little bit about Justin (June is already well known to our readers). Justin Hall [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/3318","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=3318"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/3318\/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=3318"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=3318"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=3318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}