MediaWiki:Gadget-fix-schedule-times.js

// vim: ts=4 sw=4 et ai si $.when(   $.ready ).then( function  { // quit immediately if dontFixSchedule is in the URL after the ? if(window.location.search.indexOf("dontFixSchedule")>=0)return;

// Configuration var CONFERENCE_DAYS = { "Friday, October 8": Date.UTC( 2021, /* month index, not month number! */ 9, 8 ), "Saturday, October 9": Date.UTC( 2021, 9, 9 ), "Sunday, October 10": Date.UTC( 2021, 9, 10 ) };   var WRITTEN_SCHEDULE_OFFSET_SECONDS = -4 * 3600; // written schedule for WCNA 2021 is Eastern Time which is UTC-4

// Other constants var TIME_REGEX = /(\d\d):(\d\d)( - (\d\d):(\d\d)|\+)/;

function pl( n ) { return ( Math.floor( n ) === 1 ) ? "" : "s"; }

function formatRelativeTime( minutesUntilStart, minutesUntilEnd, countdownDuringEvent ) { if ( minutesUntilStart > /* one day */ 1440 ) { return "in " + Math.floor( minutesUntilStart / 1440 ).toFixed( 0 ) + " day" + pl( minutesUntilStart / 1440 ); } else if ( minutesUntilStart > /* 3 hours */ 180 ) { return "in " + Math.floor( minutesUntilStart / 60 ).toFixed( 0 ) + " hour" + pl( minutesUntilStart / 60 ); } else if ( minutesUntilStart > 120 ) { return "in 2 hours and " + Math.floor( minutesUntilStart % 60 ).toFixed( 0 ) + " minute" + pl( minutesUntilStart % 60 ); } else if ( minutesUntilStart > 60 ) { return "in an hour and " + Math.floor( minutesUntilStart % 60 ).toFixed( 0 ) + " minute" + pl( minutesUntilStart % 60 ); } else if ( minutesUntilStart > 1 ) { return "in " + Math.floor( minutesUntilStart ).toFixed( 0 ) + " minute" + pl( minutesUntilStart ); } else if ( minutesUntilStart > 0 ) { return "in less than a minute"; } else if ( minutesUntilStart > -1 ) { return "started just now"; } else if ( minutesUntilStart > -5 ) { return "started " + Math.floor( -minutesUntilStart ).toFixed( 0 ) + " minute" + pl( -minutesUntilStart ) + " ago"; } else if ( minutesUntilEnd > 1 ) { if ( countdownDuringEvent ) { return "ends in " + Math.floor( minutesUntilEnd ).toFixed( 0 ) + " minute" + pl( minutesUntilEnd ); } else { if ( minutesUntilStart > -60 ) { return "started " + Math.floor( -minutesUntilStart ).toFixed( 0 ) + " minute" + pl( -minutesUntilStart ) + " ago"; } else { return "started " + Math.floor( -minutesUntilStart / 60 ).toFixed( 0 ) + " hour" + pl( -minutesUntilStart / 60 ) + " ago"; }           }        } else if ( minutesUntilEnd > 0 ) { return "ends in one minute"; } else if ( minutesUntilEnd > -1 ) { return "ended just now"; } else if ( minutesUntilEnd > -60 ) { return "ended " + Math.floor( -minutesUntilEnd ).toFixed( 0 ) + " minute" + pl( -minutesUntilEnd ) + " ago"; } else if ( minutesUntilEnd > -1440 ) { return "ended " + Math.floor( -minutesUntilEnd / 60 ).toFixed( 0 ) + " hour" + pl( -minutesUntilEnd / 60 ) + " ago"; } else { return "ended " + Math.floor( -minutesUntilEnd / 1440 ).toFixed( 0 ) + " day" + pl( -minutesUntilEnd / 1440 ) + " ago"; }   }

function formatTime( unixTimestamp ) { return new Date( unixTimestamp * 1000 ).toLocaleTimeString.replace( /(\d\d?:\d\d):00/, "$1" ).replace( / /g, " " ); }

function makeHtml( originalTimeMatch, tableCell ) { var dayHeading = $( tableCell ).closest( "table" ).prev.prev; // skip icon key var dayHeadingText = dayHeading.find( ".mw-headline" ).text; var baseDateUnix = Math.floor( CONFERENCE_DAYS[dayHeadingText] / 1000 ); var isSoftEndingTime = !originalTimeMatch[4]; // if there's no group-4 match, no ending time was specified

// First, get the actual timestamps var startTimeUnix = baseDateUnix + parseInt( originalTimeMatch[1], 10 ) * 3600 + parseInt( originalTimeMatch[2], 10 ) * 60 - WRITTEN_SCHEDULE_OFFSET_SECONDS; var endTimeUnix = isSoftEndingTime ? ( startTimeUnix + 3600 * 5 ) : ( baseDateUnix + parseInt( originalTimeMatch[4], 10 ) * 3600 +               parseInt( originalTimeMatch[5], 10 ) * 60 - WRITTEN_SCHEDULE_OFFSET_SECONDS );

// Now, get some text like "Starts in 10 minutes". var nowUnix = Math.floor( new Date.getTime / 1000 ); var relativeTimeFormatted = formatRelativeTime(           ( startTimeUnix - nowUnix ) / 60,            ( endTimeUnix - nowUnix ) / 60,            /* countdownDuringEvent */ !isSoftEndingTime,        ); return formatTime( startTimeUnix ) + ( isSoftEndingTime ? "+" : ( " - " + formatTime( endTimeUnix ) ) ) + " (" + relativeTimeFormatted + ")"; }

$( "small" ).each( function {        if ( this.textContent === "(US Eastern Time)" ) { try{            $( this ).text( "In " + Intl.DateTimeFormat.resolvedOptions.timeZone.replace( /_/g, " " ) + " time" ); }catch(e){ console.error(e); $(this).text("In your local timezone (hover to see Eastern U.S. time)");        }        }    } );

$( "td" ).each( function {        var match = TIME_REGEX.exec( this.textContent );        if ( match ) {            this.innerHTML = this.innerHTML.replace( match[0], "" + match[0] + " " );        }    } );

function go { $( "span.fixed" ).each( function {            $( this ).html( makeHtml( TIME_REGEX.exec( this.dataset.original ), this.parentNode ) );        } ); }

go; window.setInterval( go, 60 * 1000 ); } );