Public/Get-TvProgram.ps1

function Get-TvProgram
{
    param
    (
        [Parameter(Mandatory)]
        [string[]]$Channel,

        [switch]$Force
    )

    if (-not $script:TvDataCache -or $Force)
    {
        Write-Verbose 'Updating tv data cache'
        Update-TvDataCache
    }
    else
    {
        Write-Verbose 'Using existing tv data cache'
    }

    $AllChannels = Get-TvChannel
    $AllPrograms = $script:TvDataCache.tv.programme
    $SelectedChannels = [Ordered]@{}

    $Channel.ForEach{
        $AllChannels
        | Where-Object 'display-name' -Like $_
        | ForEach-Object {
            if (-not $SelectedChannels.Contains($_.id))
            {
                $SelectedChannels.Add($_.id, $_.'display-name')
            }
        }
    }

    if ($SelectedChannels.Keys.Count -eq 0)
    {
        Write-Warning 'No channels matched the specified channel filter.'
    }

    $SelectedChannels.Keys.ForEach{
        Write-Verbose "Exporting channel $_"
        $ChannelID = $_

        $AllPrograms
        | Where-Object channel -EQ $ChannelID
        | ForEach-Object {
            $CurrentProgram = $_

            [PSCustomObject]@{
                PSTypeName  = 'UncommonSense.TvGuide.TvProgram'
                Channel     = $SelectedChannels[$ChannelID]
                StartTime   = [DateTime]::ParseExact($CurrentProgram.start, 'yyyyMMddHHmmss \+\0\0\0\0', $null, 'AssumeUniversal')
                EndTime     = [datetime]::ParseExact($CurrentProgram.stop, 'yyyyMMddHHmmss \+\0\0\0\0', $null, 'AssumeUniversal')
                Title       = $CurrentProgram.title.InnerText
                Description = $CurrentProgram.desc.InnerText
                Category    = $CurrentProgram.Category.InnerText
                EpisodeNo   = ($CurrentProgram.'episode-num' | Where-Object system -EQ onscreen).InnerText
            }
        }
    }
}