Convert Unix time with PowerShell
60,971
Solution 1
See Convert a Unix timestamp to a .NET DateTime.
You can easily reproduce this in PowerShell.
$origin = New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0
$whatIWant = $origin.AddSeconds($unixTime)
Solution 2
Function Convert-FromUnixDate ($UnixDate) {
[timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($UnixDate))
}
$niceTime = Convert-FromUnixDate $ctime
PS C:\> $niceTime
Friday, 18 May 2012 8:24:18 p.m.
Solution 3
Use:
(([System.DateTimeOffset]::FromUnixTimeSeconds($unixTime)).DateTime).ToString("s")
FromUnixTimeMilliseconds is also available.
ToString("s"): Sortable: "The pattern reflects a defined standard (ISO 8601)"
Ref.: Standard Date and Time Format Strings, The Sortable ("s") Format Specifier
Solution 4
$date = get-date "1/1/1970"
$date.AddSeconds($unixTime).ToLocalTime()
Solution 5
A simple one-liner:
(Get-Date "1970-01-01 00:00:00.000Z") + ([TimeSpan]::FromSeconds($unixTime))
Author by
mrwh1t3
Updated on October 09, 2021Comments
-
mrwh1t3 over 1 yearI am parsing an SQLite database using the PowerShell SQLite module, and a couple of the return values are created and modified, both of which are in Unix time.
What I would like to do is somehow convert that into "human time". I have removed some of the other SQL queries for ease of reading.
Import-Module SQLite mount-sqlite -name GoogleDrive -dataSource E:\Programming\new.db $cloud_entry = Get-ChildItem GoogleDrive:\cloud_entry foreach ($entry in $cloud_entry) { $entry.created }The output looks like a large column of Unix timestamps:
1337329458Update: I ultimately went with the following:
$ctime = $entry.created [datetime]$origin = '1970-01-01 00:00:00' $origin.AddSeconds($ctime)-
mklement0 almost 4 yearsWhat you went with is ambiguous, because something like[datetime] '1970-01-01 00:00:00'creates a[datetime]instance whose.Kindproperty isUnspecified. By contrast, the start of Unix epoch time is unambiguously UTC. -
mklement0 about 3 years@Thomas[datetime] '1970-01-01Z', which gives you aLocal[datetime]instance; if you need aUtcinstance, use([datetime] '1970-01-01Z').ToUniversalTime() -
brianary over 1 year@mklement0 Using a UTC start time for a value during daylight saving time is giving me a result that is off by an hour (the DST offset). I think using that method is doing the time zone calculation based on the start datetime, instead of the ending datetime. -
mklement0 over 1 year@brianary You're correct: the correct solution is to get aUtc[datetime]instance, add the Unix epoch time (in seconds) to it, and then convert to local time:([datetime] '1970-01-01Z').ToUniversalTime().AddSeconds($ctime).ToLocalTime(). Alternatively, using[datetimeoffset](which is preferable in general):[datetimeoffset] '1970-01-01Z').AddSeconds($ctime).LocalDateTime -
brianary over 1 year@mklement0 Just to clarify, a UTC DateTime doesn't seem to work without some extra confusing steps, see the further discussion below, stackoverflow.com/a/10781745/54323
-
-
Torbjörn Bergstedt almost 11 years[datetime]$origin = '1970-01-01 00:00:00'works just as well, and is maybe a little easier to understand -
mrwh1t3 almost 11 yearsI'm getting this error: Any ideas? Cannot convert argument "0", with value: "", for "AddSeconds". Some of the values are "null", in that some of the items in the database are not assiged a created/modified date. I'm assuming this is where that error is coming from. -
bluuf over 4 yearsI feel stupid knowing that for the past years I've used [System.DateTime]::Parse('1-1-1970).AddSeconds($epoch) instead of DateTimeOffset -
user2190601 over 4 yearsNo worries, it looks like the method is new as of .net 4.6! -
mklement0 about 3 yearsGood idea to request a UTC time, but you can do that simply by passing another argument to theNew-Objectcall:New-Object -Type DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, 0, Utc -
brianary over 1 yearThe time zone is going to be wrong unless you add.ToLocalTime()to the end of that second line. You can't use[datetime]'1970-01-01Z'because that'll do the time zone offset of the start time, which will be off during daylight savings. -
brianary over 1 yearThis doesn't seem to work. For a value of1629937097, I'm getting2021-08-26T00:18:17instead of2021-08-26T17:18:17(see epochconverter.com or a similar reference converter). -
mklement0 over 1 yearGood point, @brianary:[datetime] '1970-01-01Z'by itself isn't enough, because it returns aLocal[datetime]instance, which locks in the DST offset at the start time. Instead, use([datetime] '1970-01-01Z').ToUniversalTime().AddSeconds($unixTime)to get the time as aUTCtime stamp, and([datetime] '1970-01-01Z').ToUniversalTime().AddSeconds($unixTime).ToLocalTime()to convert to aLocalone. Or, using[datetimeoffset], which is preferable in general:([datetimeoffset] '1970-01-01Z').AddSeconds($unixTime), then access.UtcDateTimeor.LocalDateTime, as needed. -
user2190601 over 1 year@brianary The powershell output will be UTC in 24h format. I'm seeing 2021-08-26T00:18:17 from powershell and from epochconverter (top field) GMT: Thursday, August 26, 2021 12:18:17 AM which is equivalent since the converter output in is 12h time. -
brianary over 1 year@mklement0 This works fine(Get-Date 1970-01-01).AddSeconds($unixTime).ToLocalTime(), without the confusion of code creating a UTC DateTime and then converting that to UTC again. The DateTimeOffset approach also gave me the wrong answer. -
brianary over 1 year@Fredrick It looks like I can use(([System.DateTimeOffset]::FromUnixTimeSeconds($unixTime)).DateTime.ToLocalTime()).ToString("s") -
brianary over 1 year@mklement0 Correction: DateTimeOffset does work, once converted to localtime. -
mklement0 over 1 yearYou're right @brianary (the alternative is([datetime] '1970-01-01').AddSeconds($unixTime).ToLocalTime()), but there is a pitfall:Get-Date 1970-01-01(and[datetime] '1970-01-01') create anUnspecified[datetime]instance. While this happens to work with.ToLocalTime(), if you need a local instance (because anUnspecifiedinstance is then treated asUTC), it misbehaves if you call.ToUniversalTime()(becauseUnspecifiedis then likeLocal). Working withUnspecifiedinstances can introduce subtle bugs. -
brianary over 1 year@mklement0Unspecifiedis exactly what you want from a start time, since you don't want the DateTime to calculate the time zone offset until you've calculated the final DateTime.([datetime] '1970-01-01').AddSeconds($unixTime).ToLocalTime().KindreturnsLocal, so the result of the expression isn't vulnerable to anyUnspecifiedbugs. Do you have an example of a value that would cause a problem? -
mklement0 over 1 year@brianary, please see my previous comment for an example (to recap: if you want aUtcinstance from anUnspecifiedone,.ToUniversalTime()assumes thatUnspecifiedmeansLocal) - my recommendation is to stay away fromUnspecified, for the reasons stated, and, taking a step back, to work with[datetimeoffset]whenever possible. Yes, if you know you want a local timestamp and you're aware of the general pitfalls, you can use your shortcut - but I wouldn't recommend it. I think we've covered all angles now. -
Garric over 1 yearTime zone in function. It's great. The bulky function is easily reduced if desired. Thank you.