fix: invalid date strings (#2145)

* fix: invalid date strings

Fixes #2113

* fix: polls without expiry date

Fixes #2112
This commit is contained in:
Nolan Lawson 2022-05-14 11:27:32 -07:00 committed by GitHub
parent 78687479df
commit 5fd8d0ac23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 7 deletions

View file

@ -306,7 +306,8 @@
multiple: ({ poll }) => poll.multiple,
expired: ({ poll }) => poll.expired,
expiresAt: ({ poll }) => poll.expires_at,
expiresAtTS: ({ expiresAt }) => new Date(expiresAt).getTime(),
// Misskey can have polls that never end. These give expiresAt as null
expiresAtTS: ({ expiresAt }) => typeof expiresAt === 'number' ? new Date(expiresAt).getTime() : null,
expiresAtTimeagoFormatted: ({ expiresAtTS, expired, $now }) => (
expired ? formatTimeagoDate(expiresAtTS, $now) : formatTimeagoFutureDate(expiresAtTS, $now)
),

View file

@ -3,6 +3,9 @@ import { mark, stop } from '../_utils/marks.js'
// Format a date in the past
export function formatTimeagoDate (date, now) {
if (typeof date !== 'number') { // means "never" in Misskey
return 'intl.never'
}
mark('formatTimeagoDate')
// use Math.min() to avoid things like "in 10 seconds" when the timestamps are slightly off
const res = format(Math.min(0, date - now))
@ -12,6 +15,9 @@ export function formatTimeagoDate (date, now) {
// Format a date in the future
export function formatTimeagoFutureDate (date, now) {
if (typeof date !== 'number') { // means "never" in Misskey
return 'intl.never'
}
mark('formatTimeagoFutureDate')
// use Math.max() for same reason as above
const res = format(Math.max(0, date - now))

View file

@ -1,24 +1,44 @@
import { LOCALE } from '../_static/intl.js'
import { thunk } from './thunk.js'
export const absoluteDateFormatter = thunk(() => new Intl.DateTimeFormat(LOCALE, {
const safeFormatter = (formatter) => {
return {
format (date) {
if (typeof date !== 'number') {
return 'intl.never' // null means "never" in Misskey
}
try {
return formatter.format(date)
} catch (e) {
if (e instanceof RangeError) {
// The fediverse is wild, so invalid dates may exist. Don't fail with a fatal error in that case.
// https://github.com/nolanlawson/pinafore/issues/2113
return 'intl.never'
}
throw e
}
}
}
}
export const absoluteDateFormatter = thunk(() => safeFormatter(new Intl.DateTimeFormat(LOCALE, {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
}))
})))
export const shortAbsoluteDateFormatter = thunk(() => new Intl.DateTimeFormat(LOCALE, {
export const shortAbsoluteDateFormatter = thunk(() => safeFormatter(new Intl.DateTimeFormat(LOCALE, {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
}))
})))
export const dayOnlyAbsoluteDateFormatter = thunk(() => new Intl.DateTimeFormat(LOCALE, {
export const dayOnlyAbsoluteDateFormatter = thunk(() => safeFormatter(new Intl.DateTimeFormat(LOCALE, {
year: 'numeric',
month: 'short',
day: 'numeric'
}))
})))