locked
Date calculations using New-TimeSpan RRS feed

  • Question

  • I have extended the SCCM inventory on our server to retrieve additional WMI data from clients. We use a DCM rule to update the client machines with the current days data.  Inventory is run every day so we will have the latest data usage.  I have a problem though that the script for compliance only works for the UK.  The US machines have a differen regional and locale set and it seems to affect the way powershell commands work.


    # Discovery Script


    # Daily Compliance Check for OneDrive folder scan.
    $Today = get-date
    $Namespace = "ERM"
    $Class = "ERMOneDriveFolderScans"
    $ClassInfo = Get-WmiObject -Namespace "root\cimv2\ERM" -Class ERMOneDriveFolderScans -ErrorAction SilentlyContinue -ErrorVariable wmiclasserror
    $ClassCount = (Get-WmiObject -Namespace "root\cimv2\ERM" -Query "select * from ERMOneDriveFolderScans" -ErrorAction SilentlyContinue -ErrorVariable wmiclasserror | select-object -expandproperty key).count
    if ($wmiclasserror -or $ClassCount -eq 0) #  Class doesn't exist or no class instances (meaning ERMer has set up one drive yet)
    {
     $Updated = 0
    }
    else      # update if  more than a day old
    {      
     if ($ClassCount -eq 1)
            {
             if ((New-TimeSpan -start $classinfo.Scan_Date -End (Get-Date -Format "dd-MM-yyyy")).days -gt 0)
      {
       $Updated = 0
      }
      else
      {
       $Updated = 1
      }
     }                                
     else
     {
     if ((New-TimeSpan -start $classinfo[0].Scan_Date -End (Get-Date -Format "dd-MM-yyyy")).days -gt 0)
     {
              $Updated = 0
     }
     else
     {
      $Updated = 1
     }
    }
                                         
    }
    $Updated

    # Script End

                                         
    If I run this script on a US machine with the region and local being US with date formant "mm/DD/yyyy the New-TimeSpan will generate and error :

                                          [DBG]: PS C:\Tools\Scripts>> (New-TimeSpan -start $classinfo.Scan_Date -End (Get-Date -Format "dd-MM-yyyy")).days
                                          New-TimeSpan : Cannot convert 'System.Object[]' to the type 'System.DateTime' required by parameter 'Start'. Specified method is not supported.
                                          At line:1 char:22
                                          + (New-TimeSpan -start $classinfo.Scan_Date -End (Get-Date -Format "dd- ...
                                          +                      ~~~~~~~~~~~~~~~~~~~~
                                              + CategoryInfo          : InvalidArgument: (:) [New-TimeSpan], ParameterBindingException
                                              + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewTimeSpanCommand.
                                          This command gives the correct date if machine is in the UK.  The start date is a string in the same string format "dd-MM-yyyy".

    Does anyone know how to perform a universal date calculation as we have machines in multiple time zones but will was one constant date format when reporting?


    Regards,


    Nigel

    • Moved by Bill_Stewart Thursday, January 25, 2018 9:51 PM This is not SCCM forum
    Tuesday, October 17, 2017 2:24 PM

All replies

  • I must also add the $classinfo[0...].Scan_Date array contains all users that have been using the machine.  When I write the WMI values it is stored as a string in the format "dd-MM-yyyy"

    Regards,

    Nigel

    Tuesday, October 17, 2017 2:28 PM
  • You may need to convert the object in to a DateTime object. Try 

    New-TimeSpan -start (($classinfo.Scan_Date).ToDateTime()) -End (Get-Date -Format "dd-MM-yyyy")).days


    Regards Mark

    Tuesday, October 17, 2017 2:33 PM
  • What format is the "$classinfo.Scan_Date " in.  Is it WMI datetime format or something else?

    $classdate = (Convert from unknown format)$classinfo.Scan_Date
    (New-TimeSpan -start $classdate -End [DateTime]::ToDay).days


    \_(ツ)_/

    Tuesday, October 17, 2017 2:39 PM
  • PS C:\Tools\Scripts> $classinfo[0].Scan_Date.GetType()

    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     True     String                                   System.Object

    Tuesday, October 17, 2017 3:55 PM
  • I know it is a string but what is the format. Post the string.


    \_(ツ)_/

    Wednesday, October 18, 2017 1:29 AM
  • The format is "dd-MM-yyyy"
    Wednesday, October 18, 2017 9:43 AM
  • Take a look at this blog post for information about dealing with dates in different formats: https://blogs.technet.microsoft.com/heyscriptingguy/2011/08/25/use-culture-information-in-powershell-to-format-dates/

    As the script is running on the client, you should be able to do something like this:

    $culture = New-Object System.Globalization.CultureInfo "en-gb" $StartDate = Get-Date -Date ($class.Scan_Date) -Format $culture.DateTimeFormat.ShortDatePattern

    New-TimeSpan -start $StartDate -End (Get-Date -Format "dd-MM-yyyy")).days



    Regards Mark

    Wednesday, October 18, 2017 10:40 AM
  • Get-Date cannot convert a WMI date string.  Use Mangement datetime converter class;

    [System.Management.ManagementDateTimeConverter]

    https://msdn.microsoft.com/en-us/library/system.management.managementdatetimeconverter.todatetime(v=vs.110).aspx


    \_(ツ)_/

    Wednesday, October 18, 2017 11:19 AM
  • The format is "dd-MM-yyyy"

    Is that the string you have or is that what you want?


    \_(ツ)_/

    Wednesday, October 18, 2017 11:20 AM
  • Hi,

    That is the format I want.

    Wednesday, October 18, 2017 12:47 PM
  • I used string type  because when create a WMI instance using a DateTime object defining a property it throws up a 'type mismatch'

    i.e

     $newClass = New-Object System.Management.ManagementClass ("root\cimv2\$Namespace", [String]::Empty, $null);
     $newClass["__CLASS"] = $Class
     
     $newClass.Qualifiers.Add("Static", $true)
     $newClass.Properties.Add("Key", [System.Management.CimType]::String, $false)
     $newClass.Properties["Key"].Qualifiers.Add("Key", $true)
     # $newClass.Properties.Add("Scan_Date", [System.Management.CimType]::String, $false)

    $newClass.Properties.Add("Scan_Date", [System.Management.CimType]::DateTime, $false)
    $WMIURL = 'root\cimv2\'+$Namespace+':'+$Class
    $PushDataToWMI = ([wmiclass]$WMIURL).CreateInstance()
    $PushDataToWMI.Scan_Date = Get-Date

      $PushDataToWMI.Put()

    Wednesday, October 18, 2017 12:52 PM
  • As jrv pointed out you will need to convert between a WMI date and a .NET date format. Using the following code I was able to create the class with a WMI datetime property, set an instance and then convert that back again.

    $Class = "Test_Class"
    $newClass = New-Object System.Management.ManagementClass ("root\cimv2", [String]::Empty, $null)
    $newClass["__CLASS"] = $Class
    $newClass.Qualifiers.Add("Static", $true)
    $newClass.Properties.Add("Key", [System.Management.CimType]::String, $false)
    $newClass.Properties["Key"].Qualifiers.Add("Key", $true)
    $newClass.Properties.Add("Scan_Date", [System.Management.CimType]::DateTime, $false)
    $newClass.Put()
    
    # Get .NET DateTime
    $a = Get-Date
    # Convert to WMI DateTime
    $Date = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($a)
    Set-WmiInstance -Class $Class -Arguments @{Scan_Date=$a}
    
    $c = Get-WmiObject -class $Class
    # Convert WMI DateTime to .NET DateTime
    [System.Management.ManagementDateTimeConverter]::ToDateTime($c.Scan_Date)
    
    


    Regards Mark

    Thursday, October 19, 2017 12:27 PM