Реализации алгоритмов/Вечный календарь

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

Описание алгоритма[править]

Существует довольно простой алгоритм вычисления дня недели для любой даты григорианского календаря позднее 1583 года. Григорианский календарь начал действовать в 1582 — после 4 октября сразу настало 15 октября.

Положим год — год, месяц — номер месяца, день — день, тогда

a = (14 − месяц) / 12
y = год − a
m = месяц + 12 * a − 2
ДеньНедели = (7000 + день + y + y / 4 − y / 100 + y / 400 + (31 * m) / 12) ОСТАТОК 7

Все деления целочисленные (остаток отбрасывается).

Результат: 0 — воскресенье, 1 — понедельник и т. д.

Реализации алгоритма[править]

Arduino IDE[править]

Для Arduino IDE код выглядит следующим образом:

//==========================================================================================
//Глобальные переменные
//==========================================================================================
 byte den = 7;        //число
 byte mes = 7;        //месяц
 unsigned int god = 2017;  //год

//==========================================================================================
//Функция деления без остатка f_div
//==========================================================================================
unsigned int f_div(unsigned int x, unsigned int y){
  unsigned int result;
  result = (x-(x%y))/y;
  return result;
}

//==========================================================================================
//Функция вычисления дня недели
//==========================================================================================
void nedelya(){
  byte a = f_div((14-mes),12);
  unsigned int y = god-a;
  byte m = mes +12*a - 2;
  unsigned int y4 = f_div(y,4);
  byte y100 = f_div(y,100);
  byte y400 = f_div(y,400);
  byte x = f_div(31*m,12);
  byte ned =(7000 +den + y + y4 - y100 + y400 + x)%7; //результат в переменной "ned"
}
//набирал с клавиатуры и убил вечер на тестирование - reodos

JavaScript[править]

Для JavaScript код выглядит следующим образом:

function getDay(day,mon,year){
 var days = ["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"];
 day=parseInt(day, 10); //если день двухсимвольный и <10 
 mon=parseInt(mon, 10); //если месяц двухсимвольный и <10 
 var a=parseInt((14-mon)/12, 10);
 var y=year-a;
 var m=mon+12*a-2;
 var d=(7000+parseInt(day+y+parseInt(y/4, 10)-parseInt(y/100, 10)+parseInt(y/400, 10)+(31*m)/12, 10))%7;
 return days[d];
}

C[править]

Реализация на C: (// результат 0 при 01.09.2993)

struct struct_date
{
    short day;
    short month;
    short year;
};

int what_day(const struct struct_date* date)
{
    int a = (14 - date->month) / 12;
    int y = date->year - a;
    int m = date->month + 12 * a - 2;
    return (7000 + (date->day + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12)) % 7;
}

Delphi[править]

Реализация на Delphi и FreePascal:

function WhatDay(Year: Integer; Month: Integer; Day: Integer):integer;
var a,y,m: integer;
begin
 a := (14 - Month) div 12;
 y := year - a;
 m := month + 12 * a - 2;
 WhatDay := (7000 + (day + y + y div 4 - y div 100 + y div 400 + (31 * m) div 12)) mod 7;
end;

PHP[править]

Реализация на PHP:

function getDay($day, $mon, $year)
{
	$days = array("воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота");
	$day = (int)$day; //если день двухсимвольный и <10 
	$mon = (int)$mon; //если месяц двухсимвольный и <10 
	$a = (int)((14 - $mon) / 12);
	$y = $year - $a;
	$m = $mon + 12 * $a - 2;
	$d = (7000 + (int)($day+$y+ (int)($y/4) - (int)($y/100) + (int)($y/400) + (31*$m)/12))%7;
	return $days[$d];
}

MS SQL[править]

Реализация в MS SQL:

CREATE FUNCTION [dbo].[getDay](
@date datetime
)
RETURNS int
AS
BEGIN
 declare @a int
 declare @y int
 declare @m int

 set @a = (14 MONTH(@date)) / 12
 set @y = YEAR(@date) @a
 set @m = MONTH(@date) + 12*@a-2

 return (7000 + (DAY(@date) + @y + @y / 4 @y / 100 + @y / 400 + (31 * @m) / 12)) % 7

END

Cmd.exe[править]

Реализация для командного процессора Windows (cmd.exe):

@echo off
set /a день = %date:~0,2%
set /a месяц = %date:~3,2%
set /a год = %date:~6,4%

set /a a = ((14 - %месяц%) / 12)
set /a y = (%год% - %a%)
set /a m = (%месяц% + (12 * %a%) - 2)
set /a ДеньНедели = ((7000 + (%день% + %y% + (%y% / 4) - (%y% / 100) + (%y% / 400) + ((31 * %m%) / 12))) %% 7)

echo %ДеньНедели%

Python[править]

Реализация на Python:

def whatDay(day, month, year):
    days = ["пн","вт","ср","чт","пт","сб","вс"]
    a = (14 - month) // 12
    y = year - a
    m = month+12 * a-2
    result = ((7000 + (day + y + y//4 - y//100 + y//400 + (31*m) // 12)) % 7) - 1
    return days[result]

Microsoft Excel[править]

Реализация в MS Excel:

=ОКРВНИЗ(ОСТАТ((ДЕНЬ(A2)+(ГОД(A2)-ОКРВНИЗ((14-МЕСЯЦ(A2))/12;1))+ОКРВНИЗ((ГОД(A2)-ОКРВНИЗ((14-МЕСЯЦ(A2))/12;1))/4;1)-ОКРВНИЗ((ГОД(A2)-ОКРВНИЗ((14-МЕСЯЦ(A2))/12;1))/100;1)+ОКРВНИЗ((ГОД(A2)-ОКРВНИЗ((14-МЕСЯЦ(A2))/12;1))/400;1)+ОКРВНИЗ(31*(МЕСЯЦ(A2)+12*ОКРВНИЗ((14-МЕСЯЦ(A2))/12;1)-2)/12;1));7);1)

В ячейке А2 находится день календаря в формате даты. Результат выводится в виде номера дня недели(воскресение - 0)

ЛИБО:
(English): =CHOOSE(WEEKDAY(A1;2);"Monday";"Tuesday";"Wednesday";"Thursday";"Friday";"Saturday";"Sunday")
(Русский): =ВЫБОР(ДЕНЬНЕД(A1;2);"Понедельник";"Вторник";"Среда";"Четверг";"Пятница";"Суббота;"Воскресенье")
где А1 - это ваша ячейка с датой.

Ruby[править]

Реализация на Ruby:

def week_day(year, month, day)
  a = (14 - month) / 12
  y = year - a
  m = month + 12 * a - 2
  (7000 + (day + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12)) % 7
end

Java[править]

Реализация на Java:

public static String weekday(int day, int month, int year){
        String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
        int a = (14 - month) / 12, y = year - a, m = month + 12 * a - 2;
        return days[(7000 + (day + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12)) % 7];
}

Ссылки[править]