1

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.

Frak
  • 832
  • 1
  • 11
  • 32
fvurnle
  • 13
  • 1
  • 4
  • 1
    Does this answer your question? [Windows ISO 8601 timestamp](https://stackoverflow.com/questions/45689471/windows-iso-8601-timestamp) -> `Get-Date -Format "o"` gives you the format you are looking for – Jawad Jan 23 '20 at 17:15
  • 1
    Thanks for linking. This definitely answers my second part of formatting the time. However I'm not sure how initally specify the datetime object be in EST timezone (with my computer being in a GMT timezone). Is this feasible? – fvurnle Jan 23 '20 at 18:09

2 Answers2

1

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)
t1meless
  • 504
  • 2
  • 9
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'.

mklement0
  • 382,024
  • 64
  • 607
  • 775