Convert String to DateTime Object in specific timezone with Powershell

耗尽温柔 提交于 2021-02-19 08:26:23

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!