Measure-Latest: finding latest date/time

Today I needed to find the latest date/time value from a set of values and stumbled upon an issue with the standard measure-object cmdlet failing for DateTime values (click the link to vote for this to be fixed by the way).

Obviously, as a true PowerSheller, whenever I come across a limitation like that I simply use the extensibility of PowerShell to get through. Here’s the Measure-Latest function which I created. It takes the values from the pipeline and outputs the latest of them (or $null if the pipeline was empty or only had $null values):

# get a set of DateTime values from the pipeline
# filter out $nulls and produce the latest of them
# (c) Dmitry Sotnikov
function Measure-Latest {
    BEGIN { $latest = $null }
    PROCESS {
            if (($_ -ne $null) -and (($latest -eq $null) -or ($_ -gt $latest))) {
                $latest = $_ 
            }
    }
    END { $latest }
}

Usage is pretty simple:

# when was the last time something was modified in the current folder?
dir | foreach { $_.LastWriteTime } | Measure-Latest

Enjoy!

Tags: , , , ,

Advertisement

19 Responses to “Measure-Latest: finding latest date/time”


  1. 1 tojo2000 July 16, 2008 at 6:05 pm

    I like it, but this is useful for more than datetime objects. This can be used for any object where -gt works. I’m thinking of stealing this but calling it Get-Max. 🙂

  2. 2 dmitrysotnikov July 16, 2008 at 6:08 pm

    Be my guest 🙂

  3. 3 EBGreen July 16, 2008 at 8:43 pm

    This is a nice example, but would this not do the same thing:

    dir | Sort-Object LastWriteTime | Select-Object -Last 1

  4. 4 dmitrysotnikov July 17, 2008 at 7:15 am

    It would, but if I remember what I was being told in my computer science classes loooong time ago: sorting was a more resource expensive operation than just determining the maximum value. To find max you just scan the collection once. Sorting requires going through the collection more than that.

    With that said, yes, sorting and picking the last value should also give you the latest one.

  5. 5 EBGreen July 17, 2008 at 1:03 pm

    Good point. You are correct that sorting is more expensive. I was just in command line mode. 🙂

  6. 6 EBGreen July 17, 2008 at 2:31 pm

    Completely redundant since it has already been pointed out that sorting is more expensive, but here is an example. This is looking at the windows dir on my laptop:

    $dirOnly = Measure-Command {dir -rec}
    $dirSorting = Measure-Command {dir -rec | Sort-Object LastWriteTime | Select-Object -Last 1}
    $dirMax = Measure-Command {dir -rec | foreach { $_.LastWriteTime } | Measure-Latest}

    $dirOnly.TotalSeconds
    10.4870283

    $dirMax.TotalSeconds
    15.1897679

    $dirSorting.TotalSeconds
    19.300323

  7. 7 dmitrysotnikov July 17, 2008 at 2:40 pm

    Yep, and the bigger the dataset the bigger the difference will be.

  8. 8 jimhowe March 4, 2009 at 7:15 pm

    Forgive me if this is too elementary a question, but how would I get this value exported in a csv along with other user account values such as pwdlastset, creationdate, etc.?
    Thanks!
    Jim

    Your blog is an excellent resource, Dmitry! Forgive me if I haven’t searched well enough for the answer.

  9. 9 jimhowe March 4, 2009 at 7:45 pm

    Sorry… (again!) my comment above was with regard to the last true logon post which uses this function (“Finding the latest logon time « Dmitry’s PowerBlog: PowerShell and beyond”). How can you feed the “Measure-Latest” value of the latest logon query into a spreadsheet with rest of the other get-qaduser information?

    • 10 Anonymous July 14, 2009 at 11:51 am

      One cool thing I found out recently is the ability in PowerShell to use a variable in place of an explicit property name. I’ve refactored the example given here to look a bit more like Measure-Object.

      function Measure-Latest([String] $Property = $null, [Switch] $Earliest) {
      BEGIN { $value = $null }
      PROCESS {

      if($Property){
      $TestObject = $_.$Property
      }else{
      $TestObject = $_
      }

      if($Earliest){
      $Logic = $TestObject -lt $value
      }else
      {
      $Logic = $TestObject -gt $value
      }

      if (($TestObject -ne $null) -and (($value -eq $null) -or ($Logic))) {
      $value = $TestObject
      }

      }
      END { $value }
      }
      “Earliest”
      dir | measure-Latest LastWriteTime -earliest

      “Latest”
      dir | measure-Latest LastWriteTime

  10. 11 Dmitry Sotnikov July 14, 2009 at 12:38 pm

    This looks very cool! Thanks!

  11. 12 Donald Garber August 26, 2011 at 12:54 am

    Hey mate, I recently used (slightly modified) this script in order to find the most recent folder in a given share. I’m quite new to PS.

    cd C:\SD\projects\folder\MoveProject\Archive
    dir | foreach { $_.LastWriteTime } | Measure-Latest
    write-host $latest

    Here’s how I figured out how to incorporate it. This script displays the latest, I think this is how it’s done, it works, anyway.

    Now, to actually GET files FROM that latest folder and copy them locally…
    🙂

  12. 14 Russell Young February 27, 2012 at 10:19 pm

    when i run this I don’t get any results back. I can see it hitting each domain controller but nothing comes back. Do I have to wrap this around some other code to get it to work.

    Get-QADComputer -ComputerRole DomainController | foreach {
    Write-Host $_.Name
    (Get-QADUser -Service $_.Name -SamAccountName username).LastLogon.Value } |
    Measure-Latest

    • 15 Dmitry Sotnikov February 27, 2012 at 10:26 pm

      I am not with the team anymore, so cannot say for sure, but I would try to remove .Value – they could have made LastLogon to just work without it.

      If that does not help, you can also contact the team at the PowerShell and AD forum at http://powergui.org

      Dmitry

  13. 16 zj February 21, 2018 at 3:43 pm

    I know this is very old post, I learned a lots from you, including your ‘Pro Windows PowerShell’ book, so I would like your comment.
    I think issue that you experienced with standard measure-object cmdlet failing for DateTime values is related to object being passed is the String and measure-object does string ordering. If you pass DateTime type then it looks that works properly ( got same results as your example):
    (dir c:\temp | foreach { [datetime []] $_.LastWriteTime} | Measure-Object -Maximum).Maximum


  1. 1 Finding the latest logon time « Dmitry’s PowerBlog: PowerShell and beyond Trackback on July 18, 2008 at 10:01 am
  2. 2 Right Click Houdini » Blog Archive » MD5 Hash Deduplication Trackback on November 10, 2011 at 12:24 am
  3. 3 Finding the latest logon time « kb4you Trackback on April 9, 2012 at 4:10 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s




Legal

The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

July 2008
M T W T F S S
 123456
78910111213
14151617181920
21222324252627
28293031  

%d bloggers like this: