import type { Media } from '$lib/Data/AniList/media'; import type { MediaPrequel } from '$lib/Data/AniList/prequels'; import type { SubsPlease } from '$lib/Media/Anime/Airing/Subtitled/subsPlease'; import settings from '$stores/settings'; import { injectAiringTime } from './Subtitled/match'; import { totalEpisodes } from '../episodes'; import { get } from 'svelte/store'; export const airingTime = ( originalAnime: Media, subsPlease: SubsPlease | null, upcoming = false, forceDays = false ) => { const anime = injectAiringTime(originalAnime, subsPlease); const airingAt = anime.nextAiringEpisode?.airingAt; const untilAiring = airingAt ? Math.round((airingAt - Date.now() / 1000) * 100) / 100 : undefined; const time = new Date(airingAt ? airingAt * 1000 : 0).toLocaleTimeString([], { hour12: !settings.get().display24HourTime, hour: 'numeric', minute: '2-digit' }); let timeFrame = ''; let hours = null; const shortenCountdown = get(settings).displayShortCountdown; if ( (anime as unknown as MediaPrequel).startDate && new Date( anime.startDate.year, (anime as unknown as MediaPrequel).startDate.month, (anime as unknown as MediaPrequel).startDate.day ) < new Date() ) return `on ${new Date( anime.startDate.year, (anime as unknown as MediaPrequel).startDate.month, (anime as unknown as MediaPrequel).startDate.day ).toLocaleDateString()}`; if (untilAiring !== undefined) { let minutes = untilAiring / 60; let few = true; if (minutes > 60) { hours = minutes / 60; if (hours > 24) { let weeks = Math.floor(hours / 24) / 7; few = false; if (weeks >= 1.5 && !forceDays) { weeks = Math.round(weeks); timeFrame = `${weeks}${shortenCountdown ? 'w' : ' week'}${ weeks === 1 || shortenCountdown ? '' : 's' }`; } else { const days = Math.round(Math.floor(hours / 24)); const residualHours = Math.floor(hours - days * 24); timeFrame += `${days.toFixed(0)}${shortenCountdown ? 'd' : ' day'}${ days === 1 || shortenCountdown ? '' : 's' }`; if (residualHours > 0) timeFrame += `${shortenCountdown ? '' : ' '}${residualHours}${ shortenCountdown ? 'h' : ' hour' }${residualHours === 1 || shortenCountdown ? '' : 's'}`; } } else { const residualMinutes = Math.round(minutes - Math.floor(hours) * 60); timeFrame += `${hours.toFixed(0)}${shortenCountdown ? 'h' : ' hour'}${ hours === 1 || shortenCountdown ? '' : 's' }`; if (residualMinutes > 0) timeFrame += `${shortenCountdown ? '' : ' '}${residualMinutes}${ shortenCountdown ? 'm' : ' minute' }${residualMinutes === 1 || shortenCountdown ? '' : 's'}`; } } else { minutes = Math.round(minutes); timeFrame += `${minutes}${shortenCountdown ? 'm' : ' minute'}${ minutes === 1 || shortenCountdown ? '' : 's' }`; } const opacity = Math.max(50, 100 - (untilAiring / 60 / 60 / 24 / 7) * 50); const nextEpisode = anime.nextAiringEpisode?.nativeAiringAt && !upcoming && anime.nextAiringEpisode.nativeAiringAt < Date.now() / 1000 + 1 * 24 * 60 * 60 ? anime.nextAiringEpisode.episode - 1 : anime.nextAiringEpisode?.episode || 0; const dateString = new Date(airingAt ? airingAt * 1000 : 0).toLocaleDateString([], { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }) + ' ' + time; if (upcoming) return `${nextEpisode}${totalEpisodes( anime )} in ${timeFrame} ${ few && get(settings).displayCoverModeAnime ? '
' : '' }${few ? `(${time})` : ''}
`; else return `${nextEpisode} in ${ few && get(settings).displayCoverModeAnime ? '
' : '' }${few ? '' : ''}${timeFrame}${few ? '' : ''} ${few ? `(${time})` : ''}
`; } return ''; };