I'm collecting a timestamp value and trying to transform it to a Unix format.
To do that, I'm using ParseExact method, like so:
$FILETIME = "20220709101112"
$EPOCHTIME = [datetime]::ParseExact($FILETIME,"yyyyMMddHHmmss",$null) | Get-Date -UFormat "%s"
echo $EPOCHTIME
1657361472
Get-Date transforms the timestamp to Unix format correctly, but there's an issue. The returned value uses the local timezone (UTC-3), not UTC-0.
Therefore, in another system that value might be displayed with the wrong timezone.
I've tried to add 3 hours, but it appended the number instead.
$EPOCHTIME = $EPOCHTIME 10800
echo $EPOCHTIME
165736147210800
How can I convert that timestamp correctly?
CodePudding user response:
Ok, so here's one way to do it (borrowing from https://stackoverflow.com/a/246529/3156906).
The key is to find the TimeZoneInfo for the timezone the $FILETIME
string is local to, and use that to convert the local time to UTC before converting to a Unix epoch timestamp.
# datetime string that is local to UTC-3,
# (equivalent to "2022-07-09 13:11:12 UTC")
$FILETIME = "20220709101112";
# because there's no timezone component in the custom
# format string (e.g. "z" or "zz") this gets converted
# to a datetime with "Kind = DateTimeKind.Unspecified"
# (see https://docs.microsoft.com/en-us/dotnet/api/system.datetime.parseexact?view=net-6.0#system-datetime-parseexact(system-string-system-string-system-iformatprovider))
$TIMESTAMP = [datetime]::ParseExact($FILETIME, "yyyyMMddHHmmss", $null);
# DateTime : 09 July 2022 10:11:12
# Kind : Unspecified
# get a reference to the timezone the original date
# string is stored local to. I guessed this by looking
# at the results of "[TimeZoneInfo]::GetSystemTimeZones()"
# and taking a timezone with -3:00 from UTC and no daylight savings
# but maybe there's a better match for your source data
$tz = [TimeZoneInfo]::FindSystemTimeZoneById("SA Eastern Standard Time");
# Id : SA Eastern Standard Time
# DisplayName : (UTC-03:00) Cayenne, Fortaleza
# StandardName : SA Eastern Standard Time
# DaylightName : SA Eastern Summer Time
# BaseUtcOffset : -03:00:00
# SupportsDaylightSavingTime : False
# this is the magic bit - treat $TIMESTAMP as a local time in
# timezone $tz, and convert it to UTC using the BaseUtcOffset
# and daylight saving rules for $tz
$UTCTIME = [TimeZoneInfo]::ConvertTimeToUtc($TIMESTAMP, $tz);
# DateTime : 09 July 2022 13:11:12
# Kind : Utc
# now convert it to a unix epoch timestamp
$EPOCHTIME = $UTCTIME | Get-Date -UFormat "%s";
# 1657372272
Bonus Round
You get the Unix epoch timestamp 1657361472 because the current timezone on the computer where you're running your script is UTC, which is 3 hours offset from the timezone the string is local to.
Notes on DateTime.ParseExact Method
If s does not represent a time in a particular time zone and the parse operation succeeds, the Kind property of the returned DateTime value is DateTimeKind.Unspecified. If s does represent the time in a particular time zone and format allows time zone information to be present (for example, if format is equal to the "o", "r", or "u" standard format specifiers, or if it contains the "z", "zz", or "zzz" custom format specifiers), the Kind property of the returned DateTime value is DateTimeKind.Local.
CodePudding user response:
This question has been answered in this post:
Get formatted universal date / time
Essentially, it depends on the version of PowerShell that you're using. If it's Powershell 7.1 , then you can do:
Get-Date -AsUTC -UFormat "%s"
Otherwise, if it's a lower version, you need to use
Get-Date ([datetime]::UtcNow) -UFormat "%s"