Private/ConvertTo-VmPowerUtcTime.ps1

function ConvertTo-VmPowerUtcTime {
    <#
    .SYNOPSIS
    Read a timestamp as UTC, whether it arrived as a DateTime or as text.

    .DESCRIPTION
    The dwell store round-trips through an Automation variable, so a time written as a DateTime
    comes back as a string. Casting that back with [datetime] is the trap this module already
    documents: PowerShell converts '2026-09-10T18:00:00Z' to the local zone and labels it Local,
    and any code that then relabels it moves the value by the local offset without saying so.

    Parsed with RoundtripKind instead, so a Z keeps Kind Utc and an offset is honoured. A time with
    no zone at all is read as UTC rather than local, because everything that writes this store
    writes UTC. Reading it as local would move the dwell window by the local offset - and a safety
    guard that is quietly an hour out is worse than one that is switched off.

    .PARAMETER Value
    A DateTime, or a string in a round-trip format.
    #>

    [CmdletBinding()]
    [OutputType([datetime])]
    param(
        [Parameter(Mandatory)]
        [AllowNull()]
        $Value
    )

    if ($Value -is [datetime]) { return ([datetime]$Value).ToUniversalTime() }

    $text = "$Value".Trim()
    if (-not $text) { throw 'Empty value where a timestamp was expected.' }

    $parsed = [datetime]::Parse(
        $text,
        [cultureinfo]::InvariantCulture,
        [System.Globalization.DateTimeStyles]::RoundtripKind
    )
    if ($parsed.Kind -eq [System.DateTimeKind]::Unspecified) {
        $parsed = [datetime]::SpecifyKind($parsed, [System.DateTimeKind]::Utc)
    }
    $parsed.ToUniversalTime()
}