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'
.