From 537d3fe17dd4f3b146716f1e209f165773a7584d Mon Sep 17 00:00:00 2001 From: Julien Cornebise Date: Sun, 10 May 2026 17:33:21 +0100 Subject: [PATCH] Fix podcast episode sort for pre-1970 broadcast dates Same root cause as #3620: String(value).localeCompare(..., {numeric:true}) treats the "-" of negative ms epochs as a non-numeric character, so pre-1970 broadcast dates sort lexically. Switch the primary publishedAt branch and the same-named tiebreaker to numeric subtraction. Other sort keys remain on localeCompare for natural-sort behaviour. Verified with a paste-into-console reproducer; see PR description. Developed with the help of Claude (Anthropic), reviewed and verified by me. --- .../tables/podcast/LazyEpisodesTable.vue | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/client/components/tables/podcast/LazyEpisodesTable.vue b/client/components/tables/podcast/LazyEpisodesTable.vue index d23ee3d3..44b9a320 100644 --- a/client/components/tables/podcast/LazyEpisodesTable.vue +++ b/client/components/tables/podcast/LazyEpisodesTable.vue @@ -194,14 +194,18 @@ export default { bValue = b[this.sortKey] } - // Sort episodes with no pub date as the oldest + // publishedAt is a numeric ms epoch (negative for pre-1970 broadcasts). + // Compare numerically so the leading "-" of negative epochs doesn't + // break Intl.Collator{numeric:true}, which only handles unsigned digit + // runs. Missing dates count as oldest. if (this.sortKey === 'publishedAt') { - if (!aValue) aValue = Number.MAX_VALUE - if (!bValue) bValue = Number.MAX_VALUE + const av = aValue == null ? Number.NEGATIVE_INFINITY : Number(aValue) + const bv = bValue == null ? Number.NEGATIVE_INFINITY : Number(bValue) + return av < bv ? -1 : av > bv ? 1 : 0 } const primaryCompare = String(aValue).localeCompare(String(bValue), undefined, { numeric: true, sensitivity: 'base' }) - if (primaryCompare !== 0 || this.sortKey === 'publishedAt') return primaryCompare + if (primaryCompare !== 0) return primaryCompare // When sorting by season, secondary sort is by episode number if (this.sortKey === 'season') { @@ -212,11 +216,10 @@ export default { if (secondaryCompare !== 0) return secondaryCompare } - // Final sort by publishedAt - let aPubDate = a.publishedAt || Number.MAX_VALUE - let bPubDate = b.publishedAt || Number.MAX_VALUE - - return String(aPubDate).localeCompare(String(bPubDate), undefined, { numeric: true, sensitivity: 'base' }) + // Final tiebreaker: numeric publishedAt + const apa = a.publishedAt == null ? Number.NEGATIVE_INFINITY : Number(a.publishedAt) + const bpa = b.publishedAt == null ? Number.NEGATIVE_INFINITY : Number(b.publishedAt) + return apa < bpa ? -1 : apa > bpa ? 1 : 0 }) }, episodesList() {