簡體   English   中英

在PowerShell跨平台中獲取固定時區的時間

[英]Get time in a fixed timezone in PowerShell Cross-Platform

我想要HH:mm格式的中歐標准時間 (CET) 時間。 以下在設置了 CET 的計算機上正常工作:

Get-Date -f HH:mm
15:55

但是,在具有 GMT 的機器上,它返回13:55

以下適用於某些 Windows 機器:

Get-Date ([System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId((Get-Date), 'Central Europe Standard Time')) -f HH:mm
15:55

然而,Linux (pwsh/PowerShell Core) 機器不知道Central Europe Standard Time ,而是類似Europe/Zurich 無論如何,我不喜歡這個長字符串而不是簡單的CET代碼,所以有沒有更好的方法來轉換為已知時區?

很遺憾:

  • 不,沒有更短的方法來識別時區,因為您提供的示例確實是System.TimeZoneInfo實例的.Id屬性值。

  • 不,沒有跨平台的方式來識別時區,因為Windows 和類 Unix 平台之間內置時區不僅在標識符( .Id ) 方面不同,而且在地理粒度歷史范圍方面也不同

    • 例如,在Windows上由單一時區Eastern Standard Time (美國和加拿大)表示(基於注冊表中的信息),在類 Unix平台(macOS 和 Linux,基於ICU 庫)上表示為多個時區),例如America/New_YorkAmerica/Toronto等等。
    • Unix 上這些更細粒度的時區不僅是同一事物的不同名稱,它們還攜帶特定的歷史信息,因此,例如,基於歷史日期的轉換可能在America/New_YorkAmerica/Toronto之間有所不同,即使今天它們對應於同一個時區。

以上暗示,如果您想在所有情況下保證跨平台的相同行為,則需要做更多的工作,因為您不能依賴內置時區,而是使用序列化時區定義,您可以源自一個平台上的內置時區。

以下示例顯示如何使用通過System.TimeZoneInfo.ToSerializedString從 Windows上的Central Europe Standard Time時區獲得的序列化時區定義,可跨平台使用以表現出相同的行為:

# Note: The string was obtained *on Windows* as follows:
#   [System.TimeZoneInfo]::FindSystemTimeZoneById(
#     'Central Europe Standard Time'
#    ).ToSerializedString()
$tz = [System.TimeZoneInfo]::FromSerializedString(
  'Central Europe Standard Time;60;(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague;Central Europe Standard Time;Central Europe Daylight Time;[01:01:0001;12:31:9999;60;[0;02:00:00;3;5;0;];[0;03:00:00;10;5;0;];];'
)

# Convert the current local date to the target time zone.
[System.TimeZoneInfo]::ConvertTime(
  (Get-Date), # better: [datetimeoffset]::now
  $tz
)

筆記:

  • 最好使用[datetimeoffset] ( System.DateTimeOffset ) 實例作為輸入的原因是ConvertTime()調用也返回一個[datetimeoffset]實例,這是一個明確的、完全指定的時間點,基於適用的 UTC 偏移量價值被構建到價值中。

  • 相比之下,作為輸入的[datetime] ( System.DateTime ) 實例會導致ConvertTime()返回一個[datetime]實例,其.Kind屬性值為Unspecified 也就是說,它代表一個名義時間點,只有在與外部時區/UTC 偏移信息結合時才完全指定。

您可以像下面這樣轉換時間:

[System.TimeZoneInfo]::ConvertTime((Get-Date),[System.TimeZoneInfo]::FindSystemTimeZoneById("W. Europe Standard Time"))

為了建立在Guenther 的好答案的基礎上,另一種方法是利用 PowerShell 5+ 中提供的 Get-TimeZone cmelet。

$Date      = Get-Date
$TimeZone  = Get-TimeZone -Id "W. Europe Standard Time"
$OtherDate = [System.TimeZoneInfo]::ConvertTime( $Date, $TimeZone )

Get-TimeZone 允許您按 ID 或名稱查找時區,並返回與段[System.TimeZoneInfo]::FindSystemTimeZoneById("W. Europe Standard Time")相同的 TimeZoneInfo 對象,但它稍微更原生。

這被變量分解了一點,但它可以是單行的。

[System.TimeZoneInfo]::ConvertTime( (Get-Date), (Get-TimeZone -Id "W. Europe Standard Time") )

這些在 PowerShell 5.1 和 7.0 中測試良好

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM