2016-03-17 4 views
1

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

У меня также есть отладочная переменная, называемая totalNumDays, которая хранит количество дней за каждый месяц, так как это значение отличается. (Январь имеет 31 день, апрель - 30 дней, февраль - 28 или 29 дней). Проблема, с которой я сталкиваюсь, заключается в том, чтобы число было правильным в течение месяца февраля.

То, что я сделал, было создать массив всех месяцев с 31 дней:

//1 = January, 3 = March, 5 = May,..., etc. 
var monthNumsWith31 = [1, 3, 5, 7, 8, 10, 12]; 

Тогда позже я использую цикл для перебора, чтобы определить количество дней. Я попробовал пару разных вещей. Один я думал, что имело смысл был:

for(var i = 0; i < monthNumsWith31.length; i++) 
{ 
    if(month == monthNumsWith31[i]) 
    { 
     totalNumDays = 31; 
    } 
    else 
    { 
     if(month == 2 && isLeapYear() == true) 
     { 
     totalNumDays = 29; 
     } 
     else if(month == 2 && isLeapYear() == false) 
     { 
     totalNumDays = 28; 
     } 
     else 
     { 
     totalNumDays = 30; 
     } 
    } 

Я попытался целую кучу разных вещей и не могу показаться, чтобы получить его, чтобы сохранить правильное количество дней, в течение февраля. Я даже попытался создать второй массив из monthNumsWith30 и использовать два разных цикла для итерации через оба из них и установить соответствующее количество дней в течение нескольких месяцев с 30 и 31 днями. Я думаю, проблема может быть в моей функции isLeapYear(). Вот код для isLeapYear(). Обратите внимание, что year является глобальным, поэтому функция имеет к нему доступ.

function isLeapYear() { 
    if(year % 4 == 0) 
    { 
     if(year % 100 == 0) 
     { 
      if(year % 400 == 0) 
      { 
      return true; 
      } 
      else 
      { 
      return false; 
      } 
     } 
     else 
     { 
      return true; 
     } 
    } 
    else 
    { 
     return false; 
    } 
} 

Я попытался следовать формуле, чтобы определить, является ли год високосным годом или нет. Формула может быть представлена ​​здесь: https://gyazo.com/9e4b7fb92014d1e27315807c188fd5e0

Кто-нибудь знает, почему моя функция не делает то, что она должна делать? Благодарю.

ОБНОВЛЕНИЕ Теперь я правильно его работаю, чтобы определить правильное количество дней для каждого месяца. Однако у меня есть еще одна проблема.

Чтобы узнать, в какой день недели наступает данная дата, я использую Конгруэнцию Целлера. Конкретной формулой, которую я использую, является ((26M - 2)/10 + D + Y + Y/4 + C/4 + 5C) MOD 7, где M, D, Y - это именно то, что они кажутся, и C - это век (первые две цифры года). Существует часть алгоритма, который содержит

IF Month < 3 THEN 
    Year = Year - 1 
    Month = Month + 10 
ELSE 
    Month = Month - 2 
END IF 

У меня все работает правильно. Я включил множество операторов отладки, чтобы убедиться, что он получает правильные значения, которые он есть, но по какой-то причине компьютер неправильно вычисляет это выражение.

Этот алгоритм даст число от 0 до 6. 0 является воскресенью, 1 является понедельником и т. Д. Например, взята дата 2/15/16. Эта дата произошла в понедельник. Понедельник, 15 Февраля 2016 г.

В моей программе у меня есть следующий код

var weekdayIndex = (Math.floor((26 * monthVal) - 2/10) + dayVal + 
    yearVal + Math.floor(yearVal/4) + Math.floor(centuryVal/4) + 
    (5 * centuryVal)) % 7; 

Когда это выражение работает, оно должно быть равно 1, но по какой-то причине она равна 0.Я сделал математику вручную и оценивал каждое индивидуальное выражение снова и снова и продолжал получать 1. Сделав это вручную, я получил цифры . Когда я помещаю это выражение в компьютер напрямую (без всех имен переменных и выражений Math.floor, просто числа), он правильно получает значение. Я не знаю, почему это неправильно, когда я использую имена переменных и выражения. Есть идеи?

+0

, если ваша проблема просто вычисляя день неделю заданной даты, почему вы не используете [Date api] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getDay)? –

+0

Нам сказали, что нам не разрешено использовать это. – GenericUser01

ответ

2

Вашей функции нормально, за исключением простой вещи: вам не хватает параметр года!

function isLeapYear(year) { 
    return year % 4 == 0 && 
    (year % 100 !== 0 || year % 400 === 0); 
} 

Но, с расширенными синтаксис слишком хорошо:

function isLeapYear(year) { 
    if(year % 4 == 0) 
    { 
     if(year % 100 == 0) 
     { 
      if(year % 400 == 0) 
      { 
      return true; 
      } 
      else 
      { 
      return false; 
      } 
     } 
     else 
     { 
      return true; 
     } 
    } 
    else 
    { 
     return false; 
    } 
} 

isLeapYear(1900) дает false, как и ожидалось, 2000 true, 1996 true, 1997 false.

Кажется, для меня это законно.

+0

Я не думал, что мне нужен параметр 'year', так как он глобальный, и функция уже имеет к нему доступ. Я могу попытаться это изменить. – GenericUser01

+0

Я добавил в параметр год и по какой-то причине все еще не работает:/ – GenericUser01

+0

Я получил его для работы сейчас, но по какой-то причине он не позволит мне работать, если я не ставлю значение для февраля, это отдельный массив сам по себе и используйте для этого цикл for. Кажется очень избыточным. – GenericUser01

1

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

CsiLgrDate.leap_year = function (year) 
{ return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); }; 
+0

Это не имеет значения. У ОП нет проблем с определением високосных лет, только с установкой количества дней в феврале. – RobG

1

Ваша функция верна, ошибка связана с тем, что javascript Array для month имеет нулевую индексацию.

Изменить эту строку:

var monthNumsWith31 = [1, 3, 5, 7, 8, 10, 12]; 

Для этого:

var monthNumsWith31 = [0, 2, 4, 6, 7, 9, 11]; 

И вычитать один из всех ваших ссылок месяц (февраля является индекс массива 1)


Вы можете t наберите (new Date()).getMonth() на консоли: вы увидите, что march == 2.

Надеюсь, это поможет.

+0

Номер месяца в OP вводится пользователем, поэтому это номер месяца календаря, а не значение, возвращаемое * getMonth *. – RobG

0

Here give this a shot. Я предполагаю, что вы только начинаете. Мы можем избежать множества вложенных операторов if. Кроме того, вы захотите начать привыкать к использованию тройных равных (===), так как он проверяет тип и не будет делать странные вещи с «правными» значениями.

Прежде всего, глядя на ваш isLeapYear функция. Когда вы выполняете проверку для оператора if и используете равный оператор для их сравнения, он возвращает true или false, поэтому, если мы не делаем странных вещей, мы ожидаем, что true будет ложным (хотя есть простые способы сделайте это тоже), мы можем просто вернуть выражение, чтобы получить true или false, вместо того, чтобы возвращать true или false, если ваше выражение истинно или false.

В качестве аргумента также может стоить дикая передача в качестве аргумента вместо того, чтобы получать ее из сферы действия родителя. Но в этом случае это не имеет значения, я уверен.

&& проверит, является ли утверждение истинным, затем оно выполнит следующее выражение. И вы можете связать это, если вы ожидаете, что все будет истинным, потому что, если одно ложно, тогда все ложно. Поэтому нет необходимости писать вложенные операторы if.

function checkLeapYear(yearToCheck) { 
    return yearToCheck%4 === 0 && yearToCheck%100 === 0 && yearToCheck%400 === 0; 
} 

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

This is a switch statement. Это очень удобно, если у вас есть значения, необходимые для того, чтобы они совпадали. Но вы можете услышать от многих людей, как я написал мой, это неправильный и что вы никогда не должны пропускать случай. Я не согласен с этими людьми, потому что я думаю, что это отличный пример того, когда вы захотите сделать именно это.

Этот переключатель примет переменную, месяц в этом случае. Сравните его со значением в случаях, затем выполните код для случая. Он попадет в следующий случай без break;. Поскольку мы хотим, чтобы 1, 3, 5, 7, 8, 10, 12 всем производили totalNumDays = 31, мы установили это для самого нижнего регистра и оставим все.

Но если month равно 2, мы хотим, чтобы он был totalNumDays, чтобы быть на високосный год или 28 в противном случае. Тернарный оператор Он в основном работает как сокращение, если утверждение. Вы даете ему выражение, в этом случае функцию checkLeapYear, затем ?, чтобы запустить тернарный оператор. Тогда значение, когда оно истинно, в этом случае мы хотим, чтобы оно равнялось 29. Тогда для ложных значений используйте :, затем поставьте хотите, чтобы вы имели значение false. В этом случае 28.

В заявлении switch по умолчанию просто означает это, если совпадений нет. Что делает totalNumDays равным 30. Что это может быть немного опасно, как если бы мы сделали месяц равным 13 или «А», он все равно сделает totalNumDays равным 30. Но подготовка к каждой возможности не является чем-то, о чем я слишком беспокоюсь Теперь.

switch(month) { 
    case 1: 
    case 3: 
    case 5: 
    case 7: 
    case 8: 
    case 10: 
    case 12: 
    totalNumDays = 31; 
    break; 
    case 2: 
    totalNumDays = checkLeapYear(year) ? 29 : 28; 
    break; 
    default: 
    totalNumDays = 30; 
    break; 
} 

В любом случае, я надеюсь, что это поможет и не так уж много, чтобы принять участие. Что касается того, почему ваш код не работает. Я думаю, это может быть потому, что ваша петля начинается в месяце 0. Это будет 30-дневный месяц.

1

код на самом деле работает, если год параметр используется в ISLEAPYEAR вызова и в объявлении функции.

Вот код точно так, как отвечал (ну, я добавил отсутствует закрывающий }, что я предполагаю, был постинг упущения):

// Set some test values 
 
var monthNumsWith31 = [1, 3, 5, 7, 8, 10, 12]; 
 
var month = 2; 
 
var year = 2000 
 

 
for(var i = 0; i < monthNumsWith31.length; i++) 
 
{ 
 
    if(month == monthNumsWith31[i]) 
 
    { 
 
     totalNumDays = 31; 
 
    } 
 
    else 
 
    { 
 
     if(month == 2 && isLeapYear(year) == true) 
 
     { 
 
     totalNumDays = 29; 
 
     } 
 
     else if(month == 2 && isLeapYear(year) == false) 
 
     { 
 
     totalNumDays = 28; 
 
     } 
 
     else 
 
     { 
 
     totalNumDays = 30; 
 
     } 
 
    } 
 
} 
 

 
function isLeapYear(year) { 
 
    if(year % 4 == 0) 
 
    { 
 
     if(year % 100 == 0) 
 
     { 
 
      if(year % 400 == 0) 
 
      { 
 
      return true; 
 
      } 
 
      else 
 
      { 
 
      return false; 
 
      } 
 
     } 
 
     else 
 
     { 
 
      return true; 
 
     } 
 
    } 
 
    else 
 
    { 
 
     return false; 
 
    } 
 
} 
 

 
document.write(totalNumDays);

Смежные вопросы