Average temperature

{fmtTemp(stats.avg)}{tempUnit.replace('°', '')}

{#if stats.tempAnomaly != null}

= 0} class:text-blue-600={stats.tempAnomaly < 0} class:dark:text-red-400={stats.tempAnomaly >= 0} class:dark:text-blue-400={stats.tempAnomaly < 0} > {fmtSigned(stats.tempAnomaly)} vs normal

{:else}

1991–2020 normal loading…

{/if}

Total precipitation

{fmtPrecip(stats.totalPrecip)}

{#if stats.normalPrecip != null}

normal {fmtPrecip(stats.normalPrecip)} · {stats.wetDays} wet {stats.wetDays === 1 ? 'day' : 'days'}

{:else}

{stats.wetDays} wet days

{/if}

Warmest day

{fmtTemp(stats.warm.t)}

{#if stats.warm.i >= 0}

{formatZoned(dailyDates[stats.warm.i], timezone, 'EEE d LLL')}

{/if}

Coldest day

{fmtTemp(stats.cold.t)}

{#if stats.cold.i >= 0}

{formatZoned(dailyDates[stats.cold.i], timezone, 'EEE d LLL')}

{/if}

Daily – select a day for hourly detail

{#if normals} {/if}
{#each dailyDates as date, i (date.getTime())} {@const selected = isSameDayInZone(date, selectedDay, timezone)} {@const tMax = daily.temperature_2m_max[i]} {@const tMin = daily.temperature_2m_min[i]} {@const tMean = daily.temperature_2m_mean[i]} {@const norm = normals ? normals.tmean[ordinals[i]] : NaN} {@const anomaly = finite(tMean) && finite(norm) ? tMean - norm : null} {@const precip = daily.precipitation_sum[i]} {/each}