Jump to content

UTC/GMT to local time


Recommended Posts

I'm extracting events from the system event log, specifically 4226 warnings.

The events are recorded by the system in UTC time. I need to convert them to local time.

For sort purposes, I want to report in YYYY/MM/DD HH:MM:SS local time (not everybody comes from Yankee land).

I've looked at the help file and date example/includes from all angles, but cannot figure out the examples - some fundamental piece of information is missing that I have overlooked.

Here is the working part of the code - working well, but only reporting in UTC time.

$Event_Filehandle = FileOpen(@ScriptDir & "\4226.txt", 2) ;Open file 4226.txt for output, overwrite mode
FileWrite ($Event_Filehandle, "Report generated on " & @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " on " & @ComputerName & @CRLF & @CRLF)

$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate,(Security)}!\\" & @ComputerName & "\root\cimv2")
If IsObj($objWMIService) Then
    ;Get the total number of events in the System event Log file
    $colItems = $objWMIService.ExecQuery ("SELECT * FROM Win32_NTEventlogFile WHERE LogfileName = 'System'")
    If IsObj($colItems) Then
        For $objEvent In $colItems
            $countsystemlogentries = $objEvent.NumberOfRecords
            ExitLoop ; Only have to do this once
        Next
    EndIf
    $colItems = $objWMIService.ExecQuery ("Select * FROM Win32_NTLogEvent WHERE Logfile = 'System' AND EventCode = '4226'") ;Now just get the 4226 ones
    If IsObj($colItems) Then
        For $objEvent In $colItems
            $LocalTime = $objEvent.TimeWritten ;This gives the date in UTC format
;need an 'cdate' equivalent here
            $date4226 = StringMid($LocalTime,1,4) & "/" & StringMid($LocalTime,5,2) & "/" & StringMid($LocalTime,7,2) & " " & StringMid($LocalTime,9,2) & ":" &StringMid($LocalTime,11,2) & ":" & StringMid($LocalTime,13,2) & " UTC/GMT"
            FileWrite ($Event_Filehandle, $date4226 & " TCP/IP has reached the security limit imposed on the number of concurrent TCP connect attempts" & @CRLF) ;write the entry to the log
        Next
        $count4226 = $colItems.Count ;Count the number of entries in the query result set
    EndIf
    $objWMIService=0 ;Close object
Else
    FileWrite ($Event_Filehandle, "Couldn't access information from System Event log using WMI. Check if running in adminstrator mode." & @CRLF)
EndIf
FileWrite ($Event_Filehandle, @CRLF & "Total number of events recorded in the System Event log is " & $countsystemlogentries & @CRLF)
FileWrite ($Event_Filehandle, "Total number of 4226 warnings is " & $count4226)
If $count4226 > 0 Then
    FileWrite ($Event_Filehandle, " (" & Round($count4226/$countsystemlogentries*100,2) & "% of total)") ; Watch for divide by zero errors
EndIf
FileWrite ($Event_Filehandle, @CRLF & @CRLF & "The computer is running " & @OSVersion &  " " & @OSServicePack & " Build " & @OSBuild & ", Architecture " &  @OSArch & @CRLF)
FileClose ($Event_Filehandle)

ShellExecute (@ScriptDir & "\4226.txt","",@ScriptDir,"", @SW_MAXIMIZE) ; Open the results file for viewing using default handler

Oh for the equivalent of the 'cdate' function!

Any pointers, either for the appropriate date functions (a bit more than just a reference to _Date_Time_SystemTimeToTzSpecificLocalTime - I need some pointers on the parameters to pass) or some AutoIT code equivalent to 'cdate' would be appreciated.

Edited by Confuzzled
Link to comment
Share on other sites

There's an API function 'FileTimeToLocalFileTime' which converts UTC to local FileTime, and then you can use that number to pass to the function 'FileTimeToSystemTime'. I have a module in a few of my UDF's called '_WinTimeFunctions' that deals with the conversions, though you'll have to do simple formatting to get 'YYYY/MM/DD HH:MM:SS'. Check my _WinAPI_FileFind or _ProcessFunctions UDF's to get the module. Yashied might even have these functions in his WinAPIEx UDF.

Link to comment
Share on other sites

Just a quick shot: The _DATE UDF (part of standard AutoIt) has some functions to convert UTC to local time and vice versa.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Ahh, good catch water. The functions _Date_Time_FileTimeToLocalFileTime() and _Date_Time_FileTimeToSystemTime do what is needed here, although both require pointers to "$tagFILETIME" structures.

That's actually one of my gripes about some of the UDF's - they are supposed to simplify everything, not get you involved with creating structures and filling them in. Plus "$tagFILETIME" is just a 64-bit integer that doesn't need a structure at all. But then I'm not about to be the one that suggests a change in the UDF's and wind up causing people's code to break. I'll just use my simpler versions. (sorry water, that little bit of rhetoric really has got nothing to do with you :mellow: )

*edit: copy and paste issue

Edited by Ascend4nt
Link to comment
Share on other sites

It's not as bad as you think :mellow:

Use _Date_Time_EncodeSystemTime to fill the structure and then you can use all other _Date_* functions to convert.

#include <date.au3>
$DT = "20100622084804.000000+120" ; Date/Time as returned by $objEvent.TimeWritten
$ST = _Date_Time_EncodeSystemTime(StringMid($DT,5,2),StringMid($DT,7,2),StringMid($DT,1,4),StringMid($DT,9,2),StringMid($DT,11,2),StringMid($DT,13,2))
$LT = _Date_Time_SystemTimeToTzSpecificLocalTime(DllStructGetPtr($ST))
ConsoleWrite(_Date_Time_SystemTimeToDateTimeStr($LT,1) & @CRLF)
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

nope, can't do that with something that returns FileTime data. (a 64-bit integer). It's a whole other ballgame with FileTime - its a number "representing the # of 100-nanosecond intervals since January 1, 1601".

So you'd have to create the rather pointless $tagFILETIME structure when you get a 64-bit FileTime date as Confuzzled has. That can be accomplished by either chopping up the 64-bit integer, or creating a int64 structure, and then a $tagFILETIME structure with that as a pointer. Its all just a pain in the arse lol

*edit: oops, Confuzzled wasn't getting a 64-bit FileTime integer. (don't ask me where I got the idea he did). water is correct.

Edited by Ascend4nt
Link to comment
Share on other sites

nope, can't do that with something that returns FileTime data. (a 64-bit integer). It's a whole other ballgame with FileTime - its a number "representing the # of 100-nanosecond intervals since January 1, 1601".

So you'd have to create the rather pointless $tagFILETIME structure when you get a 64-bit FileTime date as Confuzzled has. That can be accomplished by either chopping up the 64-bit integer, or creating a int64 structure, and then a $tagFILETIME structure with that as a pointer. Its all just a pain in the arse lol

It's quite easy! I managed to do it myself - so it has to be easy :mellow:

I tested the example script. $objEvent.TimeWritten returns the date/time as a string. Based on a string my code snippet works (has been tested).

If you get a 64-bit FileTime and need to convert it, just post here and I can give you a working example.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Oh, my mistake.. I had thought for sure he was getting a FileTime value. Sorry for the misunderstanding, I should have tested his code to see what he was getting for sure.

And don't worry - I already have code for converting 64-bit FileTime values and working with structs. My issue was the fact that the UDF's make you work with DLL Structures at all. All my Windows API modules isolate that stuff from the caller, unless absolutely necessary.

Link to comment
Share on other sites

Oh, my mistake.. I had thought for sure he was getting a FileTime value. Sorry for the misunderstanding, I should have tested his code to see what he was getting for sure.

And don't worry - I already have code for converting 64-bit FileTime values and working with structs. My issue was the fact that the UDF's make you work with DLL Structures at all. All my Windows API modules isolate that stuff from the caller, unless absolutely necessary.

It's true, the Date UDF is a bit different compared to the other UDFs. You have to cope with DllStructCreate and DllStructGetPtr.

If you are familiar with programming it's quite easy to get into it.

On the other hand the UDF could easily hide this tasks from the user.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...