PowerShell 5 comes with Get-TimeZone which returns all defined time zones and their time offset. This is all you need for a one-liner world clock:

$isSummer = (Get-Date).IsDaylightSavingTime()

Get-TimeZone -ListAvailable | ForEach-Object { 
    $dateTime = [DateTime]::UtcNow + $_.BaseUtcOffset
    $cities = $_.DisplayName.Split(')')[-1].Trim()
    if ($isSummer -and $_.SupportsDaylightSavingTime)
        $dateTime = $dateTime.AddHours(1)
  '{0,-30}: {1:HH:mm"h"} ({2})' -f $_.Id, $dateTime, $cities

The result looks similar to this:

Dateline Standard Time         : 18:41h ()
UTC-11                         : 19:41h (Coordinated Universal Time-11)
Aleutian Standard Time         : 21:41h (Aleutian Islands)
Hawaiian Standard Time         : 20:41h (Hawaii)
Marquesas Standard Time        : 21:11h (Marquesas Islands)
Alaskan Standard Time          : 22:41h (Alaska)
UTC-09                         : 21:41h (Coordinated Universal Time-09)
Pacific Standard Time (Mexico) : 23:41h (Baja California)
UTC-08                         : 22:41h (Coordinated Universal Time-08)
Pacific Standard Time          : 23:41h ()
US Mountain Standard Time      : 23:41h (Arizona)
Mountain Standard Time (Mexico): 00:41h (Chihuahua, La Paz, Mazatlan)
Mountain Standard Time         : 00:41h ()
Central America Standard Time  : 00:41h (Central America)
Central Standard Time          : 01:41h ()
Easter Island Standard Time    : 01:41h (Easter Island)
Central Standard Time (Mexico) : 01:41h (Guadalajara, Mexico City, Monterrey)
Canada Central Standard Time   : 00:41h (Saskatchewan)
SA Pacific Standard Time       : 01:41h (Bogota, Lima, Quito, Rio Branco)
Eastern Standard Time (Mexico) : 02:41h (Chetumal)
Eastern Standard Time          : 02:41h ()

Twitter This Tip! ReTweet this Tip!

  • Thanks, SteveGTR. I understand now, all these little nuances catch me out.

    Thanks for the explanation.

  • JulianG, it's because the newline at the end for the:

    Get-TimeZone-ListAvailable | ForEach-Object

    line is an implied end of command. Like having a semi-***. If you wanted to put the opening script block enclosure on the next line you'd have to use a backwards tick mark like so:

    Get-timezone -ListAvailable | ForEach-Object `



    I don't like using them if I can get away with it.

  • Hi,

    Can you explain to me why this fails if I do not have the lines of code

    Get-TimeZone -ListAvailable | ForEach-Object {

    $dateTime = [DateTime]::UtcNow + $_.BaseUtcOffset

    Exactly like that, ie the { at the end of the line...

    If I have it like this :

    Get-timezone -ListAvailable | ForEach-Object


    $dateTime = [DateTime]::UtcNow + $_.BaseUtcOffset

    The code fails as it looks for the following:

    cmdlet ForEach-Object at command pipeline position 2

    Supply values for the following parameters:




  • Did you include the first line of code prior to Get-TimeZone? That's where $isSummer is initialized.

  • $isSummer is not defined, so DST is unsupported.