Определение количества дней в месяце в Microsoft Excel. Как одной математической формулой по номеру месяца посчитать количество дней в нем? Сентябрь до 30 или 31

16.11.2023

Примечание : данный пост является переводом статьи cmcenroe.me/2014/12/05/days-in-month-formula.html (Часть I ), а также авторским к нему дополнением (Часть II ). Не следует относиться к материалу серьёзно, а скорее как к разминке для ума, требующей не более чем школьных знаний арифметики и не имеющей практического применения. Всем приятного чтения!

Часть I

Вступление

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

Формализуя Другими словами, необходимо найти функцию f , такую, что значение f(x) для каждого месяца x , представленного числом от 1 до 12, равняется количеству дней в этом месяце. Таблица значений аргумента и функции :

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 28 31 30 31 30 31 31 30 31 30 31

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

Ответ


Ниже следуют мои шаги по нахождению решения.

Математический аппарат

Сначала бегло освежим в памяти два жизненно необходимых в решении этой задачи оператора: целочисленное деление и остаток от деления.

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

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

Замечу, что остаток от деления имеет равный с делением приоритет.

Основы

Итак, применим наш математический аппарат для получения базовой формулы. В обычном месяце 30 или 31 день, так что мы можем использовать для получения поочерёдно 1 или 0, а затем просто прибавить к этому числу константу:

Получаем таблицу, полужирным выделены корректные значения:
x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 30 31 30 31 30 31 30 31 30 31 30

Неплохое начало! Уже есть правильные значения для января и для месяцев с марта по июль включительно. Февраль - особый случай, и с ним мы разберёмся чуть позже. После июля для оставшихся месяцев порядок получения 0 и 1 должен быть изменён на обратный.
Для этого мы может прибавить к делимому 1:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 30 31 30 31 30 31 30 31 30 31 30 31

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

Наложение маски

Для этого необходима кусочно-заданная функция, но - так как мне это показалось скучным - я задумался о другом пути решения, использующем одну часть функции на одном интервале, другую - на другом.
Полагаю, что проще всего будет найти выражение, равное 1 в одной области применения и 0 - в остальной. Метод, в котором умножая аргумент на выражение мы исключаем его из формулы вне области его применения, я назвал «наложением маски», потому такое поведение подобно некой битовой маске.
Для применения этого метода в последней части нашей функции необходимо найти выражение, равное 1 при , и - так как значения аргумента всегда меньше 16 - для этого прекрасно подходит целочисленное деление на 8.
x 1 2 3 4 5 6 7 8 9 10 11 12
x ⁄ 8 ⌋ 0 0 0 0 0 0 0 1 1 1 1 1

Теперь с помощью этой маски, используя в делимом выражение вместо 1, мы можем заменить порядок получения 0 и 1 формуле на обратный:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 30 31 30 31 30 31 31 30 31 30 31

Эврика! Всё правильно, кроме февраля. Сюрприз-сюрприз.

Февраль

В любом месяце 30 или 31 день, кроме февраля с его 28 (високосный год выходит за рамки этой задачи). На текущий момент по нашей формуле в нём 30 дней, поэтому неплохо бы вычесть выражение, равное 2 при .
Лучшее что мне удалось придумать это , что накладывает маску на все месяцы после февраля:
x 1 2 3 4 5 6 7 8 9 10 11 12
2 mod x 0 0 2 2 2 2 2 2 2 2 2 2

Изменив базовую константу на 28 с добавлением 2 к остальным месяцам получим формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 29 28 31 30 31 30 31 31 30 31 30 31

К сожалению, январь теперь короче на 2 дня. Но, к счастью, получить выражение, которое будет применяться только для первого месяца очень легко: это округлённое вниз обратное к число. Умножив его на 2 получаем окончательную формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 28 31 30 31 30 31 31 30 31 30 31

Послесловие

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

Function f(x) { return 28 + (x + Math.floor(x/8)) % 2 + 2 % x + 2 * Math.floor(1/x); }

Часть II

Вступление

В первой части была получена короткая и даже немного изящная формула, основными достоинствами которой являются простота математического аппарата, отсутствие ветвлений и условных выражений, лаконичность. К недостаткам - кроме того, что вы не будете применять её в вашем проекте - можно отнести отсутствие проверки на вискокосный и не високосный год.
Поэтому я поставил перед собой задачу создать функцию f , такую, что значение f(x, y) для каждого месяца x , представленного числом от 1 до 12 и года y , большего 0, равняется количеству дней в месяце x в году y .
Для нетерпеливых под спойлером находится готовый ответ, остальных же прошу следовать за мной.

Ответ

Остаток от деления: mod и ⌊⌋

Для визуальной наглядности договоримся, что в некоторых формулах оператор деления с остатком заменён нижними скобками, там где это показалось мне необходимым:

Високосный год

В високосный год вводится дополнительный день календаря: 29 февраля. Как известно, високосным является год, кратный 4 и не кратный 100, либо кратный 400. Запишем тождественное этому высказыванию выражение:

Для приведения этого выражения в алгебраическое, необходимо применить к результату выражения инъекцию вида:

Что позволит получить 1 при делении без остатка и 0 при делении с остатком, чтобы использовать её в формуле определения количества дней в месяце.

В качестве функции g" можно использовать 1 минус остаток от деления для :

x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g"(x) Infinity 1 0 0 0 0 0 0 0 0 0 0 0 0 0

Легко заметить, что увеличив делимое и делитель на 1 мы получим правильную формулу при :
x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g"(x) 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Таким образом выражение запишем как:


А выражение запишем как:

Применяя этот подход получим следующую функцию g(y) , значением которой будет 1, если год високосный, или 0 в обратном случае:

y 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
g(y) 0 0 1 0 0 0 1 0 0 0 1
y 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000
g(y) 1 0 0 0 1 0 0 0 1 0 0

Полужирным выделены високосные года.

Напоминаю, что в рамках принятой договорённости оператор получения остатка от деления может быть изображен как mod , так и ⌊⌋.

Наложение маски

В формуле часть является поправкой, прибавляющей 2 дня к январю. Если убрать множитель 2 и в числителе заменить 1 на 2, тогда эта формула будет прибавлять 2 дня к январю и 1 день к февралю, что даёт нам ключ к добавлению дня в високосном году. Для наглядности используем в формуле промежуточное значение g(y) и в качестве y используем 2000 (високосный) и 2001 (не високосный) годы:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f(x, 2001) 30 28 31 30 31 30 31 31 30 31 30 30

Значения для всех месяцев, кроме января не високосного года верны.

Для исправления этого досадного недоразумения добавим к январю 1 день уже известной нам формулой :


Или:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f(x, 2001) 31 28 31 30 31 30 31 31 30 31 30 30

Заключение

В результате получена уже значительно более громоздкая, но более универсальная формула, которую также можно использовать для получения количества дней в месяце определённого года:

Function f(x, y) { return 28 + ((x + Math.floor(x / 8)) % 2) + 2 % x + Math.floor((1 + (1 - (y % 4 + 2) % (y % 4 + 1)) * ((y % 100 + 2) % (y % 100 + 1)) + (1 - (y % 400 + 2) % (y % 400 + 1))) / x) + Math.floor(1/x) - Math.floor(((1 - (y % 4 + 2) % (y % 4 + 1)) * ((y % 100 + 2) % (y % 100 + 1)) + (1 - (y % 400 + 2) % (y % 400 + 1)))/x); }
Пример на C# ideone.com/fANutz .

1 . Я не умею пользоваться подобной мнемоникой, поэтому подсмотрел табличку в интернете.
2 . «Основы», или «Правило С Многими Исключениями», как и большинство правил.
3 . Изначально в римском календаре февраль был последним месяцем года, поэтому есть логика в том, что он короче всех остальных. Также есть логика в добавлении или удалении дня именно в конце года, поэтому его длина является переменной.

Upd. 1:
Альтернативный перевод первой части в

Примечание : данный пост является переводом статьи cmcenroe.me/2014/12/05/days-in-month-formula.html (Часть I ), а также авторским к нему дополнением (Часть II ). Не следует относиться к материалу серьёзно, а скорее как к разминке для ума, требующей не более чем школьных знаний арифметики и не имеющей практического применения. Всем приятного чтения!

Часть I

Вступление

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

Формализуя Другими словами, необходимо найти функцию f , такую, что значение f(x) для каждого месяца x , представленного числом от 1 до 12, равняется количеству дней в этом месяце. Таблица значений аргумента и функции :

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 28 31 30 31 30 31 31 30 31 30 31

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

Ответ


Ниже следуют мои шаги по нахождению решения.

Математический аппарат

Сначала бегло освежим в памяти два жизненно необходимых в решении этой задачи оператора: целочисленное деление и остаток от деления.

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

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

Замечу, что остаток от деления имеет равный с делением приоритет.

Основы

Итак, применим наш математический аппарат для получения базовой формулы. В обычном месяце 30 или 31 день, так что мы можем использовать для получения поочерёдно 1 или 0, а затем просто прибавить к этому числу константу:

Получаем таблицу, полужирным выделены корректные значения:
x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 30 31 30 31 30 31 30 31 30 31 30

Неплохое начало! Уже есть правильные значения для января и для месяцев с марта по июль включительно. Февраль - особый случай, и с ним мы разберёмся чуть позже. После июля для оставшихся месяцев порядок получения 0 и 1 должен быть изменён на обратный.
Для этого мы может прибавить к делимому 1:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 30 31 30 31 30 31 30 31 30 31 30 31

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

Наложение маски

Для этого необходима кусочно-заданная функция, но - так как мне это показалось скучным - я задумался о другом пути решения, использующем одну часть функции на одном интервале, другую - на другом.
Полагаю, что проще всего будет найти выражение, равное 1 в одной области применения и 0 - в остальной. Метод, в котором умножая аргумент на выражение мы исключаем его из формулы вне области его применения, я назвал «наложением маски», потому такое поведение подобно некой битовой маске.
Для применения этого метода в последней части нашей функции необходимо найти выражение, равное 1 при , и - так как значения аргумента всегда меньше 16 - для этого прекрасно подходит целочисленное деление на 8.
x 1 2 3 4 5 6 7 8 9 10 11 12
x ⁄ 8 ⌋ 0 0 0 0 0 0 0 1 1 1 1 1

Теперь с помощью этой маски, используя в делимом выражение вместо 1, мы можем заменить порядок получения 0 и 1 формуле на обратный:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 30 31 30 31 30 31 31 30 31 30 31

Эврика! Всё правильно, кроме февраля. Сюрприз-сюрприз.

Февраль

В любом месяце 30 или 31 день, кроме февраля с его 28 (високосный год выходит за рамки этой задачи). На текущий момент по нашей формуле в нём 30 дней, поэтому неплохо бы вычесть выражение, равное 2 при .
Лучшее что мне удалось придумать это , что накладывает маску на все месяцы после февраля:
x 1 2 3 4 5 6 7 8 9 10 11 12
2 mod x 0 0 2 2 2 2 2 2 2 2 2 2

Изменив базовую константу на 28 с добавлением 2 к остальным месяцам получим формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 29 28 31 30 31 30 31 31 30 31 30 31

К сожалению, январь теперь короче на 2 дня. Но, к счастью, получить выражение, которое будет применяться только для первого месяца очень легко: это округлённое вниз обратное к число. Умножив его на 2 получаем окончательную формулу:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x) 31 28 31 30 31 30 31 31 30 31 30 31

Послесловие

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

Function f(x) { return 28 + (x + Math.floor(x/8)) % 2 + 2 % x + 2 * Math.floor(1/x); }

Часть II

Вступление

В первой части была получена короткая и даже немного изящная формула, основными достоинствами которой являются простота математического аппарата, отсутствие ветвлений и условных выражений, лаконичность. К недостаткам - кроме того, что вы не будете применять её в вашем проекте - можно отнести отсутствие проверки на вискокосный и не високосный год.
Поэтому я поставил перед собой задачу создать функцию f , такую, что значение f(x, y) для каждого месяца x , представленного числом от 1 до 12 и года y , большего 0, равняется количеству дней в месяце x в году y .
Для нетерпеливых под спойлером находится готовый ответ, остальных же прошу следовать за мной.

Ответ

Остаток от деления: mod и ⌊⌋

Для визуальной наглядности договоримся, что в некоторых формулах оператор деления с остатком заменён нижними скобками, там где это показалось мне необходимым:

Високосный год

В високосный год вводится дополнительный день календаря: 29 февраля. Как известно, високосным является год, кратный 4 и не кратный 100, либо кратный 400. Запишем тождественное этому высказыванию выражение:

Для приведения этого выражения в алгебраическое, необходимо применить к результату выражения инъекцию вида:

Что позволит получить 1 при делении без остатка и 0 при делении с остатком, чтобы использовать её в формуле определения количества дней в месяце.

В качестве функции g" можно использовать 1 минус остаток от деления для :

x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g"(x) Infinity 1 0 0 0 0 0 0 0 0 0 0 0 0 0

Легко заметить, что увеличив делимое и делитель на 1 мы получим правильную формулу при :
x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
g"(x) 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Таким образом выражение запишем как:


А выражение запишем как:

Применяя этот подход получим следующую функцию g(y) , значением которой будет 1, если год високосный, или 0 в обратном случае:

y 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
g(y) 0 0 1 0 0 0 1 0 0 0 1
y 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000
g(y) 1 0 0 0 1 0 0 0 1 0 0

Полужирным выделены високосные года.

Напоминаю, что в рамках принятой договорённости оператор получения остатка от деления может быть изображен как mod , так и ⌊⌋.

Наложение маски

В формуле часть является поправкой, прибавляющей 2 дня к январю. Если убрать множитель 2 и в числителе заменить 1 на 2, тогда эта формула будет прибавлять 2 дня к январю и 1 день к февралю, что даёт нам ключ к добавлению дня в високосном году. Для наглядности используем в формуле промежуточное значение g(y) и в качестве y используем 2000 (високосный) и 2001 (не високосный) годы:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f(x, 2001) 30 28 31 30 31 30 31 31 30 31 30 30

Значения для всех месяцев, кроме января не високосного года верны.

Для исправления этого досадного недоразумения добавим к январю 1 день уже известной нам формулой :


Или:

x 1 2 3 4 5 6 7 8 9 10 11 12
f(x, 2000) 31 29 31 30 31 30 31 31 30 31 30 31
f(x, 2001) 31 28 31 30 31 30 31 31 30 31 30 30

Заключение

В результате получена уже значительно более громоздкая, но более универсальная формула, которую также можно использовать для получения количества дней в месяце определённого года:

Function f(x, y) { return 28 + ((x + Math.floor(x / 8)) % 2) + 2 % x + Math.floor((1 + (1 - (y % 4 + 2) % (y % 4 + 1)) * ((y % 100 + 2) % (y % 100 + 1)) + (1 - (y % 400 + 2) % (y % 400 + 1))) / x) + Math.floor(1/x) - Math.floor(((1 - (y % 4 + 2) % (y % 4 + 1)) * ((y % 100 + 2) % (y % 100 + 1)) + (1 - (y % 400 + 2) % (y % 400 + 1)))/x); }
Пример на C# ideone.com/fANutz .

1 . Я не умею пользоваться подобной мнемоникой, поэтому подсмотрел табличку в интернете.
2 . «Основы», или «Правило С Многими Исключениями», как и большинство правил.
3 . Изначально в римском календаре февраль был последним месяцем года, поэтому есть логика в том, что он короче всех остальных. Также есть логика в добавлении или удалении дня именно в конце года, поэтому его длина является переменной.

Upd. 1:
Альтернативный перевод первой части в

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

Прибавить дни к дате

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

Вычисление количества дней между датами

Этот метод расчета ответит на вопрос "сколько дней прошло с даты". Введите начальную дату и конечную дату и нажмите кнопку "рассчитать". Калькулятор покажет, сколько дней между введенными датами. Отдельно калькулятор покажет количество рабочих дней.

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

Праздничные дни

Калькулятор может вычислять, прибавлять и вычитать как календарные дни, так и рабочие. Официальными нерабочими праздничными днями являются:

  • 1,2,3,4,5,6,8 января - новогодние каникулы
  • 7 января - православное Рождество
  • 23 февраля - День защитника Отечества
  • 8 марта - Международный женский день
  • 1 мая - Праздник Весны и Труда
  • 9 мая - День Победы
  • 12 июня - День России
  • 4 ноября - День народного единства

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

Калькулятор при расчете дней учитывает как официальные праздничные даты, так и все переносы.

Бесплатный онлайн калькулятор Контур.Бухгалтерии вам поможет и подскажет, какое количество дней прошло между двумя заданными датами. Кроме того, если у вас возникла необходимость, вы можете посчитать сколько календарных, выходных или рабочих дней (часов) содержит указанный период года или нескольких лет.

Сколько дней между датами? Инструкция

Вы просто задаете конкретный день начала и конца и через доли секунд получаете расчет. Все данные онлайн-калькулятор считает самостоятельно. Если вы изменяете исходные дни недели, результат автоматически пересчитывается, с учетом високосного года.

Важно: нельзя брать из расчетов за прошлые года показатели рабочих дней/часов за месяц и предоставлять в качестве расчетов — данные будут различаться. Поэтому, лучше воспользуйтесь калькулятором.

Итак, порядок действий:

  1. В полях “Начальная дата” и “Конечная дата” выбираете соответственно начальный и конечный день отсчета, начиная с 2013 года и заканчивая в будущем 2018-м.
  2. Устанавливаете в следующем поле количество рабочих часов в сутках. По умолчанию в этом поле уже стоит 8 часов (40-часовая рабочая неделя), но вы можете эту цифру изменить.
  3. В правой части экрана на баннере вы увидите полученный результат: рабочие дни, календарные дни и рабочие часы между заданными датам. Результаты нужно скопировать и сохранить в своем документе.

Для чего можно использовать калькулятор

  1. Для расчета пени и просрочек по договорам
  2. Как понять эффективность использования какого-нибудь ресурса и предельные сроки использования
  3. Как случайно не назначить сроки выполнения задачи на выходной день
  4. Сколько времени осталось до дедлайна

Пример:

Вы — бухгалтер. Руководитель попросил вас в ближайшие пару минут предоставить данные по количеству рабочих часов, которые должны отработать все сотрудники компании в феврале. Количество работников вы можете легко определить — у вас перед глазами цифры. А вот количество часов нужно считать....А сколько там в феврале дней? А год-то високосный? А какие дни были выходными? А как определить количество дней праздников?

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

Вам понравился этот калькулятор? Тогда попробуйте другие наши возможности

Хотите вести бухучет, отправлять отчетность и делать расчеты в удобном и простом веб-сервисе? Попробуйте бесплатно 14 дней Контур.Бухгалтерии! Мы быстро вас научим, как сервисом пользоваться и ответим на все вопросы!