Last Update: Sep 04, 2024 | Published: Apr 29, 2015
Usually when I write these articles, it is in response to a problem or question I’ve encountered. But this week, I’m the one that needs some help. Recently my personal blog was experiencing some access problems. During the course of investigation, I came across some log information that included a date time value, but the value looked like 1426582884.043993. Fortunately, the related column heading was called ctime. A little more digging showed that this value is related to Universal Coordinated Time (UTC). The ctime value the number of seconds that have passed since the epoch.
You can think of the epoch as the big bang of computing, except that we know the date is January 1, 1970. In the Unix world, time is often calculated from this starting point. In my case, my blog was running on a Linux-based host, which is why the log information used this value. I needed a way to convert 1426582884.043993 into a meaningful date time value. You might run into this issue if you need to process some log files. Fortunately, this wasn’t too difficult to resolve.
I knew I could create a datetime object for the epoch.
$epoch = [datetime]"1/1/1970"
This object has a method called AddSeconds, so all I needed to do was specify my ctime value as a parameter.
$epoch.AddSeconds(1426582884.043993)
More than likely this value is GMT or UTC, and since I’m not in that time zone, the next step would be to convert this into my local time zone. Since I want to solve this with PowerShell, I’ll need a way to determine my offset from GMT. I can use WMI and query the Win32_Timezone class.
$tz = Get-CimInstance win32_timezone
The bias property will show me the number of minutes I am offset from GMT. In mycase, $tz.bias has a value of -300.
$utc = $epoch.AddSeconds(1426582884.043993)
$utc.AddMinutes($tz.Bias)
That’s better and pretty close, but there is that pesky detail about Daylight Savings Time. As I’m working on this problem, I am in DST, which means my effective offset from GMT is not -300 by -240. The Win32_TimeZone class has another property called DaylightBias, which is the number of minutes to subtract from the normal offset bias. This would then be more accurate:
$utc.AddMinutes(($tz.Bias)-($tz.DaylightBias))
Of course, I need way to determine if I need to make this calculation. I think the easiest way is to query the Win32_ComputerSystem class and look at the DaylightInEffect property.
If this is True, then I can subtract the Daylight bias value.
Naturally since this is something I will likely need to do again, I’ll wrap all of this up into an advanced function.
Function Convert-Ctime { <# .Synopsis Convert a ctime value to a datetime value .Description Convert a ctime value to a more meaningful datetime value. The default behavior is to convert to local time, including any daylight saving time offset. Or you can view the time in GMT. .Parameter GMT Don't convert to local time. .Example PS C:> Convert-cTime 1426582884.043993 Tuesday, March 17, 2015 5:01:24 AM #> [cmdletbinding()] Param( [Parameter(Position=0,Mandatory, HelpMessage = "Enter a ctime value", ValueFromPipeline)] [ValidateNotNullorEmpty()] [double]$Ctime, [switch]$GMT ) Begin { Write-Verbose "Starting $($MyInvocation.Mycommand)" #define universal starting time [datetime]$utc = "1/1/1970" #test for Daylight Saving Time Write-Verbose "Checking DaylightSavingTime" $dst = Get-Ciminstance -ClassName Win32_Computersystem -filter "DaylightInEffect = 'True'" } #begin Process { Write-Verbose "Processing $ctime" #add the ctime value which should be the number of #seconds since 1/1/1970. $gmtTime = $utc.AddSeconds($ctime) if ($gmt) { #display default time which should be GMT if #user used -GMT parameter Write-verbose "GMT" $gmtTime } else { #otherwise convert to the local time zone Write-Verbose "Converting to $gmtTime to local time zone" #get time zone information from WMI $tz = Get-CimInstance -ClassName Win32_TimeZone #the bias is the number of minutes offset from GMT Write-Verbose "Timezone offset = $($tz.Bias)" #Add the necessary number of minutes to convert #to the local time. $local = $gmtTime.AddMinutes($tz.bias) if ($dst) { Write-Verbose "DST in effect with bias = $($tz.daylightbias)" $local.AddMinutes(-($tz.DaylightBias)) } else { #write the local time $local } } } #process End { Write-Verbose "Ending $($MyInvocation.Mycommand)" } #end } #close Convert-Ctime function
I can either specify a value or pipe one in. I also added plenty of Verbose output so you can see what is going on in the function.
With this I can import my log data and display it in a more meaningful way.
import-csv .Hits.csv | select @{Name="Date";Expression={Convert-ctime $_.ctime}},url
Even though I’m always going on about PowerShell and objects, sometimes we still need to parse and format simple text. Fortunately, PowerShell can make even that task a breeze.