javascriptmomentjsluxon

how to implement adding or subtracting days from selected dates?


I added codepen, but didn’t figure out how to connect Luxon there. But I think the problem should be clear. I need to toggle add dates and subtract only from selected dates. That is, if I click + I must select the nearest date greater than the one in the input.

If I click minus day then I should show the nearest day which is less I'm trying to solve this by finding the index of the smallest value. But the problem is that when the day decreases, the next difference between the dates will be 0 and it does not switch further.

I hope I was able to explain in detail. The task is generally so that I can switch between dates inside the array. Press plus to move to the next major date and vice versa

    const dateSwitch = (prev: boolean) => {
 let newDate: string = DateTime.fromJSDate(new Date()).startOf("day").toISO();
 if (enabledDates.value.length) {
   let selectedDate = DateTime.fromISO(newDate);
   let dates = enabledDates.value.map(date => DateTime.fromISO(date));
   let differences = dates.map(date => selectedDate.diff(date, 'days').days);
   let minIndex = differences.reduce((minIndex, diff, index) => diff < differences[minIndex] ? index : minIndex, 0);
   return dates[minIndex].toISO();

I do this in Vue. The code example is as follows. But it only works with one switch


Solution

  • Why not sort the list of dates. You can then increment or decrement the index of the current date to find the new date?

    Using this method we will need to prevent falling out of the array's bounds. We also do away with any date mathematics (which is always horrible) and no need for any date libraries.

    As we're passing a meaningful parameter the click event listeners need to be given a function that invokes addOrSubtractDay otherwise the only parameter that is passed will be this.

    The statement addBtn.addEventListener("click", addOrSubtractDay); will result in add being bound to this which will always be truthy and works inadvertently.

    The statement subtractBtn.addEventListener("click", addOrSubtractDay(true)); has a few issues.

    1. attempting to pass true would actually "add" the date, not "subtract" it.
    2. addOrSubtractDay(true) will invoke the function and pass the resulting undefined to addEventListener and nothing happening when the button is clicked.

    const input = document.querySelector('input');
    const addBtn = document.querySelector('#addBtn');
    const subtractBtn = document.querySelector('#subtractBtn');
    
    let value = "2023-06-02";
    const enableDates = [
      "2023-06-02",
      "2023-06-01",
      "2023-06-10",
    ].sort();
    
    const addOrSubtractDay = (add = false) => {
      const selectedDate = input.value;
    
      var selectedIndex = enableDates
        .indexOf(selectedDate);
    
      if (selectedIndex < 0) {
        console.error("selected date is not enabled");
      }
    
      if (add) {
        selectedIndex++;
        selectedIndex = Math.min(selectedIndex, enableDates.length - 1);
      } else {
        selectedIndex--;
        selectedIndex = Math.max(selectedIndex, 0);
      }
    
      input.value = enableDates[selectedIndex];
    }
    
    addBtn.addEventListener("click", () => addOrSubtractDay(true));
    subtractBtn.addEventListener("click", () => addOrSubtractDay(false));
    <main>
      <input type="date" id="start" name="trip-start" value="2023-06-02" min="2018-01-01" max="2018-12-31" />
    </main>
    <button id="addBtn" type="button">+ day</button>
    <button id="subtractBtn" type="button">- day</button>