Как узнать дату любого дня в месяце?

#javascript #date

Вопрос:

Мне нужно исправить этот код, чтобы получить дату дня, выбранную для определенного месяца, из выбранного. Например, когда пользователь выбирает Октябрь в качестве месяца и вторник в качестве дня, в нем будет указана дата вторника в октябре.

Этот код работает только для понедельника.

Полный код здесь: Скрипка

 function getAllInstancesOfDayInMonth(fordate, forday) {
    fordate.setDate(1);
    var start  = getStartDay(fordate, forday)
       ,month  = fordate.getMonth()
       ,result = [start];

    while (fordate.getMonth() == month) {
      result.push(new Date(fordate.setDate(fordate.getDate() 7)));
    } 

    return result.slice(0,-1);

    function getStartDay(d, forday) {
     return d.getDay() !=  forday
            ? ( d.setDate( d.getDate()   1 ), getStartDay(d, forday) )
            : new Date(d);
    }

  }
  
  (function () {
 
   document.querySelector('#ddlMonths')
    .addEventListener('change', getDays);
  
   var result = document.querySelector('#result');
  
   result.innerHTML = '<h3>Selected day </h3>';
   result.innerHTML  = getAllInstancesOfDayInMonth(
                           new Date([2015,1,1].join('/')), 1
                        ).join('n');
  
  function getDays(e){
    var year = this.getAttribute('data-year')
       ,month =  this.options[this.selectedIndex].value
       ,monthstr = this.options[this.selectedIndex].innerHTML;
    
    result.innerHTML = '<h3>all mondays in ' monthstr ' '  year '</h3>';
    result.innerHTML  = getAllInstancesOfDayInMonth(
                           new Date([year,month 1,1].join('/')), 1
                        ).join('n');
  }
  
  function getAllInstancesOfDayInMonth(fordate, forday) {
    fordate.setDate(2);
    var start  = getStartDay(fordate, forday)
       ,month  = fordate.getMonth()
       ,result = [start];
    
    while (fordate.getMonth() == month) {
      result.push(new Date(fordate.setDate(fordate.getDate() 7)));
    } 
    
    return result.slice(0,-1);
    
    function getStartDay(d, forday) {
     return d.getDay() !=  forday
            ? ( d.setDate( d.getDate()   1 ), getStartDay(d, forday) )
            : new Date(d);
    }
    
  }
  
}())
 

Комментарии:

1. Вы имеете в виду, что если выбран месяц и день Tuesday , то вы хотите, чтобы все даты этого месяца сохранялись Tuesday ?

Ответ №1:

В вашем коде есть несколько проблем. Давайте рассмотрим их один за другим.

Значения в элементе select для дней не все уникальны. Исправьте их следующим образом:

 <select id="ddlDay" class="form-control">
<option value="0">Monday</option>
<option value="1">Tuesday</option>
<option value="2">Wednesday</option>
<option value="3">Thursday</option>
<option value="4">Friday</option>
<option value="5">Saturday</option>
<option value="6">Sunday</option>
</select>
 

Теперь перейдем к javascript…

Во-первых, ваша getDays функция вызывается только при изменении элемента выбора месяцев, а не элемента выбора дней. Мы добавляем следующее, чтобы ваш дисплей также обновлялся при изменении дня:

 document.querySelector('#ddlDay')
    .addEventListener('change', getDays);
 

Внутри getDays функции выбранный пользователем день никогда не вызывается, поэтому дисплей привязан к понедельнику. Мы можем исправить это следующим образом:

  var year = document.querySelector("#ddlMonths").getAttribute('data-year'),
     month = parseInt(document.querySelector("#ddlMonths").value) 1,
     monthstr = document.querySelector("#ddlMonths option:checked").innerText,
     day = parseInt(document.querySelector("#ddlDay").value) 1,
     daystr = document.querySelector("#ddlDay option:checked").innerText;
 

Этот код определенно мог бы использовать некоторое упрощение, но он просто работает. Обратите внимание, что month day переменные и также должны быть преобразованы в соответствующие значения int перед вводом в getAllInstancesOfDayInMonth функцию.

Наконец, мы обновляем дисплей и соответствующим образом запускаем вышеуказанную функцию:

 result.innerHTML = '<h3>all ' daystr 's in ' monthstr ' '  year '</h3>';
result.innerHTML  = getAllInstancesOfDayInMonth(
    new Date([year,month,1].join('/')), day % 7
).join('n');
 

Я думаю, что это должно быть все. Рабочую скрипку можно найти здесь: https://jsfiddle.net/m9nvekhd

Комментарии:

1. Нет проблем, я надеюсь, вы видите, что в вашей реализации пошло не так. Я также настоятельно рекомендую взглянуть на общее повторение вашего кода мистером Джоджо, которое намного чище.

Ответ №2:

Я думаю, что у тебя все очень сложно

 const
  myForm   = document.forms['my-form']
, dateYM   = { year: 'numeric', month: 'long'}
, dateLong = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }
, setDays  =_=>
  {
  let dt = new Date(`${myForm.Months.dataset.year}-${myForm.Months.value}-1`)  
  , mRef = dt.getMonth()
    ;
  myForm.result.innerHTML = `<h3>All ${myForm.Day.selectedOptions[0].textContent}in ${dt.toLocaleDateString('en-US',dateYM)} </h3>n`
    ;
  while ( mRef === dt.getMonth() )
    {
    if ( dt.getDay() == myForm.Day.value )
      myForm.result.innerHTML  = dt.toLocaleDateString('en-US',dateLong)   'n'
    dt.setDate(dt.getDate()   1) 
  } }
myForm.oninput = setDays

setDays() // init 
 body {
  font   : 12px/15px normal verdana, arial;
  margin : 1.5em;
  }
output {
  display     : block;
  white-space : pre;
  margin-top  : 2em;
  } 
 <form name="my-form">
  <select name="Months" data-year="2021">
    <option value="1" > January   </option>
    <option value="2" > February  </option>
    <option value="3" > March     </option>
    <option value="4" > April     </option>
    <option value="5" > May       </option>
    <option value="6" > June      </option>
    <option value="7" > July      </option>
    <option value="8" > August    </option>
    <option value="9" > September </option>
    <option value="10"> October   </option>
    <option value="11"> November  </option>
    <option value="12"> December  </option>
  </select>
  Select a month to retrieve all
  <select id="Day">
    <option value="1" >Monday </option>
    <option value="2" >Tuesday </option>
    <option value="3" >Wednesday </option>
    <option value="4" >Thursday </option>
    <option value="5" >Friday </option>
    <option value="6" >Saturday </option>
    <option value="0" >Sunday </option>  <!-- sunday JS is 0 -->
  </select>
  of it
  <output name="result"></output>
</form>