javascripthtmltimercountdown

How to set a weekday as the starter and ender of a countdown instead of using an specific/static date in javascript


So, I have this personal project that I'm trying to do more for studying purposes. It would be two timers to monitor two different events in a week, in which one would countdown the remain time of a occuring event (how much days/hours until the event ends) and the other would countdown the remaining time until the next event begins. then they would switch when it marks 0 (the current one would turn into the next and vice-versa).

Exemple: Event A would start on Friday 8PM and end on Monday 2PM, Event B would be Tuesday from 6PM until 7PM. Timer 1 (Current Event) would calculate the duration of Event A and show the countdown of the remaining time until it reaches the end in days and/or hours, while Timer 2 (Next Event) would do the same, but countingdown to show how long until it's time for Event B to begin, on the same format (dd/hh:min:s). The moment Event A ends, Timer 1 should freeze at 00 00:00 and stays like that while Time 2 goes until the end, and only then the events would switch id's so Event B is now Current Event and Event A is Next Event (they are weekly and will loop indefinitely).

My major struggle now is to figure how I could set the timers to start and end on given weekdays, with a specific time, and not static days, since the events have fixed weekdays to happen.

I've looked up the Date() method but couldn't figure how to use it since it requests specific dates as parameters.

I'd like to keep the code as simple as possible, but any tips, suggestions, advices or possible solutions are very welcomed even if they involve more advanced ways. JavaScript is not my forte, but I think I can manage to do the loops and all the other stuff on my own - just need to figure this out to have a kickstart.


Solution

  • In the following functions, the first argument, dow is 0 = Sunday through to 6 = Saturday

    If I understand the logic, currently (i.e. Saturday) the Monday "end" is in 2 or so days, so the Friday start is yesterday (apologies if you are still in Friday before 8PM in your part of the world, the logic still works though)

    The logic as I see it, find the upcoming Monday 2PM, calculate the previous Friday 8pm (regardless if that is in the future or past, it just has to be before the upcoming Monday 2PM)

    Similarly, find the next Tuesday 7PM, then the previous 6PM in relation to that

    Once you have those 4 dates, I guess you already have the logic to know what to display

    const nextDateDow = (dow, hours = 0, minutes = 0, seconds = 0, milliseconds = 0) => {
        const now = Date.now();
        const target = new Date(now);
        target.setDate(target.getDate() + dow - target.getDay());
        target.setHours(hours, minutes, seconds, milliseconds);
        if (target < now) {
            target.setDate(target.getDate() + 7);
        }
        target.setHours(hours, minutes, seconds, milliseconds); // account for DST
        return target;
    };
    const prevDateDow = (dow, before = Date.now(), hours = 0, minutes = 0, seconds = 0, milliseconds = 0) => {
        const target = nextDateDow(dow, hours, minutes, seconds, milliseconds);
        while (target > before) {
            target.setDate(target.getDate() - 7);
        }
        target.setHours(hours, minutes, seconds, milliseconds); // account for DST
        return target;
    };
    const monday = nextDateDow(1, 14);
    const friday = prevDateDow(5, monday, 20);
    const tuesdayEnd = nextDateDow(2, 19);
    const tuesdayStart = prevDateDow(2, tuesdayEnd, 18);
    console.log(friday.toString())
    console.log(monday.toString())
    console.log(tuesdayStart.toString())
    console.log(tuesdayEnd.toString());

    Note: the above code should not break if DST starts/ends between current date and target date, since the days you are interested in (Monday, Tuesday, Friday) are not generally days on which DST starts or ends, and even if somewhere this does occur, it generally occurs in the early morning hours, so, 2PM, 6PM, 7PM and 8PM are not likely to cause an issue there either.