Private/Resolve-VmPowerTimeZone.ps1
|
function Resolve-VmPowerTimeZone { <# .SYNOPSIS A TimeZoneInfo for an id written in either form, whatever platform is asking. .DESCRIPTION A schedule is authored on somebody's laptop and resolved inside an Azure Automation sandbox, and those are not the same operating system. Measured on 2026-09-10 by running a probe runbook: the PowerShell 7.2 sandbox is **Windows Server 2019**, not Linux, and it carries 141 time zones - all of them Windows ids. `Europe/Zurich` does not resolve there. Neither does `Etc/UTC`. On macOS and Linux the reverse is true for ids like `W. Europe Standard Time` on older runtimes. So the id is not normalised when a schedule is stored - it stays as it was written - and is translated here, at the moment it is used. .NET 6 carries the CLDR mapping both ways, which is what makes a catalogue portable between the two. An earlier version of this project claimed both forms resolved in the sandbox. That was measured on a Mac and generalised, and the first real runbook job disproved it. .PARAMETER Id A time zone id in the Windows form ('W. Europe Standard Time') or the IANA form ('Europe/Zurich'). #> [CmdletBinding()] [OutputType([System.TimeZoneInfo])] param( [Parameter(Mandatory)] [string]$Id ) try { return [System.TimeZoneInfo]::FindSystemTimeZoneById($Id) } catch { Write-Verbose "Time zone '$Id' is not known to this platform as written; trying the other form." } # Not resolvable as written. Try the other form - IANA to Windows in a sandbox, Windows to IANA # on a laptop - and say which translation worked, because a silent one is hard to debug later. $translated = '' if ([System.TimeZoneInfo]::TryConvertIanaIdToWindowsId($Id, [ref]$translated) -and $translated) { try { $zone = [System.TimeZoneInfo]::FindSystemTimeZoneById($translated) Write-Verbose "Time zone '$Id' resolved as '$translated' on this platform." return $zone } catch { Write-Verbose "'$translated' is not known here either." } } $translated = '' if ([System.TimeZoneInfo]::TryConvertWindowsIdToIanaId($Id, [ref]$translated) -and $translated) { try { $zone = [System.TimeZoneInfo]::FindSystemTimeZoneById($translated) Write-Verbose "Time zone '$Id' resolved as '$translated' on this platform." return $zone } catch { Write-Verbose "'$translated' is not known here either." } } throw ("The time zone '$Id' cannot be resolved on this platform ($([System.Environment]::OSVersion.VersionString)), " + 'in either the Windows or the IANA form. Azure Automation runs PowerShell 7.2 on Windows Server, ' + "which knows ids like 'W. Europe Standard Time'; a Mac or Linux machine knows 'Europe/Zurich'. " + 'Both are accepted and translated, so this id is wrong rather than in the wrong form.') } |