Converting WMI Date and Time

This topic contains 7 replies, has 4 voices, and was last updated by  Dave Wyatt 4 years ago.

  • Author
    Posts
  • #9935

    Lery
    Participant

    I'm currently trying to convert a date and time value returned from a WMI query to something more readable. I can accomplish this easily when one object is returned using [System.Management.ManagementDateTimeconverter]::ToDateTime. For example if my query returns just 20130807000004.000000+000 I can convert that. However, my current query returns multiple dates in that format. I want to convert them to a more readable format. I'm having trouble with this syntax. I'm thinking that I need a Foreach loop, but am stuck on that formatting as well. Any suggestions are appreciated.

  • #9938

    Don Jones
    Keymaster

    You'll have to loop them, but all WMI objects in PowerShell have a helper method, so you don't necessarily need to use that class. Assuming $var contains a property MyDate:

    foreach ($thing in $var) { $var.ConvertToDateTime($var.mydate) }

    In v3+, you can also switch to using CIM – those tend to return a normal DateTime rather than the underlying WMI weirdo date.

  • #9939

    Dave Wyatt
    Moderator

    It would help to see your starting code. Also, are you just trying to output the dates and times to the screen, or do you want to save the converted values in an object for later use?

    Here's a simple example that just writes to the screen, which might help get you started:

    foreach ($object in $someCollection)
    {
        $dateTime = [System.Management.ManagementDateTimeConverter]::ToDateTime($object.someWmiDateStringProperty)
        Write-Host $dateTime
    }
    
  • #9941

    Lery
    Participant

    @Don, I have v3, but the endpoints that I'm running this script against will most likely have v2. Can I still use CIM?

    When I try running your example, it complains that it does not have a ConvertToDateTime method.

    @dave, Your code is close to what I was already trying. When I run your code I get an error saying Cannot find an overload for "ToDateTime" and the argument count: "0".

    I cannot give you the complete code because it's a custom WMI class in the cimv2 namespace. I can give you an example, and the output I'm looking at:

    (gwmi namespacegoeshere -ComputerName 'test').endtime

    Returns:

    20130821000106.000000+000
    20130821000105.000000+000
    20130821000103.000000+000
    20130821000011.000000+000
    20130821000008.000000+000
    20130821000006.000000+000
    20130821000004.000000+000
    20130820000105.000000+000
    20130820000104.000000+000
    20130820000103.000000+000
    20130820000015.000000+000

    Again, if this just returned one entry I would be done already 🙂

    If I put my query into a variable and pipe the variable to get-member I have a TypeName: System.String. ToDateTime is a method that is available.

  • #9944

    Richard Siddaway
    Moderator

    If the end points are v2 you can still use the CIM cmdlets but you have to create a DCOM based CIMsession to the endpoint

    if you are staying with wmi cmdlets looks like your code will be something like

    (gwmi namespacegoeshere -ComputerName ‘test’).endtime | foreach { [System.Management.ManagementDateTimeConverter]::ToDateTime($_) }

    depends what else your class is returning as to whether you need to do anything else

  • #9946

    Don Jones
    Keymaster

    Ah. Custom class. You didn't mention that, and it's important. The ConvertToDateTime method is dynamically added by PowerShell, but it wouldn't know to do that to your custom class. So, yeah, in that case the class method would be the next choice. You *technically* ought not put custom classes into root/CIMV2 – the design intent is to create your own namespace. That's a nit, though.

    You *can* use the CIM commands against the WMI service directly. You have to create a CIMSession using DCOM as the protocol, and then target the CIM commands at that session. I don't know if it'll do any better of a job in terms of date/time that way, though.

    Interestingly, you could still use ConvertToDateTime, I bet. Say $x has your custom class in it, with $x.endtime being your date/time property.

    $os = Get-WmiObject Win32_OperatingSystem
    foreach ($x in $collection) {
    $os.ConvertToDateTime($x.endtime)
    }

    Might well work. ConvertToDateTime is added to all the inbuilt WMI classes. It's just a shortcut to the .NET method you're already using, though – it isn't special.

  • #9947

    Lery
    Participant

    [quote=9944]If the end points are v2 you can still use the CIM cmdlets but you have to create a DCOM based CIMsession to the endpoint
    if you are staying with wmi cmdlets looks like your code will be something like
    (gwmi namespacegoeshere -ComputerName ‘test’).endtime | foreach { [System.Management.ManagementDateTimeConverter]::ToDateTime($_) }
    depends what else your class is returning as to whether you need to do anything else
    [/quote]

    This worked perfectly. I was doing exactly that but I was using $_.endtime. I see you used just $_ and it worked like a champ. Thank you.

    [quote=9946]Ah. Custom class. You didn’t mention that, and it’s important. The ConvertToDateTime method is dynamically added by PowerShell, but it wouldn’t know to do that to your custom class. So, yeah, in that case the class method would be the next choice. You *technically* ought not put custom classes into root/CIMV2 – the design intent is to create your own namespace. That’s a nit, though.
    You *can* use the CIM commands against the WMI service directly. You have to create a CIMSession using DCOM as the protocol, and then target the CIM commands at that session. I don’t know if it’ll do any better of a job in terms of date/time that way, though.
    Interestingly, you could still use ConvertToDateTime, I bet. Say $x has your custom class in it, with $x.endtime being your date/time property.
    $os = Get-WmiObject Win32_OperatingSystem
    foreach ($x in $collection) {
    $os.ConvertToDateTime($x.endtime)
    }
    Might well work. ConvertToDateTime is added to all the inbuilt WMI classes. It’s just a shortcut to the .NET method you’re already using, though – it isn’t special.
    [/quote]

    I seem live in a world of custom and never out of the box. I tend to forget that when asking for assistance.

    I tried your code Don, even though I got it working with what Richard gave me. I get the following error:
    Exception calling "ConvertToDateTime" with "1" argument(s): "Exception calling "ToDateTime" with "1" argument(s): "Specified argument was out of the range of valid values.Parameter name: dmtfDate""

    So I modifed the code a little to this:

    $os = gwmi namespacegoeshere -ComputerName ‘test’
    foreach ($x in $os) {
    $os.ConvertToDateTime($x.endtime)
    }

    When I ran it that way, I ended up in a never ending loop of darkness and despair. I will say though, it did convert the date. It just never ends and keeps running.

  • #9949

    Dave Wyatt
    Moderator

    By the sound of it, you were using code like this:

    (gwmi namespacegoeshere -ComputerName ‘test’).endtime |
    ForEach-Object {
        [System.Management.ManagementDateTimeConverter]::ToDateTime($_.endtime)
    }
    

    You're essentially trying to read the value of $object.endtime.endtime , in that code (which will always be null). One or the other of the instances of ".endtime" in the code would have to go; in this case, it doesn't matter which one. In general, though, I would recommend keeping the one inside the loop (so you still have access to any other properties of the objects returned by Get-WmiObject):

    gwmi namespacegoeshere -ComputerName ‘test’ |
    ForEach-Object {
        [System.Management.ManagementDateTimeConverter]::ToDateTime($_.endtime)
    }
    

You must be logged in to reply to this topic.