问题
With my limited knowledge of Powershell, I'm trying to convert a string in the current from:
2020-01-23 10:06:07
to a datetime object in the timezone Eastern Standard Time
. Ultimately I want to be able to format to ISO8601 standard with the correct offset from UTC.
20-01-23T10:06:07-05:00
Is this achievable within powershell? I have looked at ConvertTimeFromUtc
however I am struggling to initially specify that the timezone is Eastern Standard Time instead of GMT.
回答1:
To treat a given nominal date (one that is unspecified with respect to what time zone it relates to) as one in the EST (US Eastern Standard Time) time zone:
That is, convert a date string such as '2020-01-24 03:00:57'
into
a [datetimeoffset]
instance that represents this unspecified-in-terms-of-time-zone string as a date/time local to the EST (Eastern Standard Time) time zone (possibly with DST (daylight-saving time) offset applied), which can then be formatted in a ISO 8601 format that includes the resulting date's specific UTC offset.
# Construct a nominal [datetime] instance whose .Kind property value is
# Unspecified (which means unspecified with respect to any particular
# time zone), which a cast from a string achieves:
$nominalDate = [datetime] '2020-01-24 03:00:57'
# Determine the target time zone.
# Note: On macOS and Linux, use 'America/New_York' (ICU library IDs).
$tz = [TimeZoneInfo]::FindSystemTimeZoneById('Eastern Standard Time')
# Get the UTC offset for the nominal date (.Kind == Unspecified),
# which is interpreted as local to that time zone.
# The offset is returned as a [timespan] instance that properly reflects
# DST, if the date falls into the DST window of the target time zone.
# If the input date is ambiguous or invalid, standard time is assumed.
$utcOffset = $tz.GetUtcOffset($nominalDate)
# Construct a [datetimeoffset] instance with the UTC offset determined above.
# This in effect creates a date that represents the nominal date in the
# target time zone, using that time zone's DST-appropriate UTC offset.
$dto = [DateTimeOffset]::new($nominalDate.Ticks, $utcOffset)
# Format according to ISO 8601 with UTC offset, but remove the
# fractional-seconds part:
# Note: With the standar "o" format specifier, only [datetimeoffset]
# instances include their UTC offset in the resulting string,
# not [datetime] instances.
$dto.ToString('o') -replace '\.\d+(?=-)'
The above yields '2020-01-24T03:00:57-05:00'
, as desired.
With a DST-window input date such as '2020-07-24 03:00:57'
, it would yield'2020-07-24T03:00:57-04:00'
- note how the UTC offset is now one hour less.
See also: The System.DateTime ([datetime]
, as a PowerShell type literal), System.DateTimeOffset ([datetimeoffset]
), and System.TimeZoneInfo ([TimeZoneInfo]
) types, and Standard date and time format strings.
The following is a related use case with a different premise:
To translate a given local date into its EST equivalent:
That is, translate a local point in time, such as obtained by Get-Date
, into the equivalent time in the EST time zone.
# Start with a local date, in any time zone.
# (A [datetime] instance whose .Kind property value is Local, though
# Unspecified would work the same).
# Alternatively, start with a UTC date (where .Kind is UTC)
$localDate = Get-Date
# Translate it to Eastern Standard time, as a [datetimeoffset] instance.
# Note: Casting $localDate to [datetimeoffset] is crucial to ensure
# that a [datetimeoffset] with the proper UTC offset is returned.
# Without it, you'd get a [datetime] instance that is nominally
# the correct time, but has an Unspecified .Kind value.
# Also, only a [datetimeoffset] instance includes a UTC offset
# when stringified with format string 'o'
$dtoEST = [TimeZoneInfo]::ConvertTimeBySystemTimeZoneId(
[datetimeoffset] $localDate,
'Eastern Standard Time'
)
# Format according to ISO 8601 with UTC offset, but remove the
# fractional-seconds part:
$dtoEST.ToString('o') -replace '\.\d+(?=-)'
The above yields a string such as '2020-01-23T16:44:41-05:00'
.
回答2:
DataTime itself doesn't have info about time zone. If you want to convert UTC date to other zone date you may use ConvertTimeFromUtc as you mentioned. Example:
$DateTime = Get-Date "2020-01-23 10:06:07"
$TimeZone = [TimeZoneInfo]::FindSystemTimeZoneById("Eastern Standard Time")
[TimeZoneInfo]::ConvertTimeFromUtc($DateTime, $TimeZone)
Or you can convert from any time zone. Get time zones:
[TimeZoneInfo]::GetSystemTimeZones() | select Id | sort Id
Convert from one time zone to another:
$DateTime = Get-Date "2020-01-23 10:06:07"
$SourceTimeZone = [TimeZoneInfo]::FindSystemTimeZoneById("Eastern Standard Time")
$DestinationTimeZone = [TimeZoneInfo]::FindSystemTimeZoneById("Azores Standard Time")
[TimeZoneInfo]::ConvertTime($DateTime, $SourceTimeZone, $DestinationTimeZone)
来源:https://stackoverflow.com/questions/59883763/convert-string-to-datetime-object-in-specific-timezone-with-powershell