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

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
→‎PHP: Коррекция
оформление
Строка 1: Строка 1:
{{wikipedia|Вечный календарь}}
{{wikipedia|Вечный календарь}}
=Описание=
=Описание=
Существует довольно простой '''алгоритм вычисления дня недели''' для любой даты [[w:Григорианский календарь|григорианского календаря]], начиная с первого дня его действия — 15 октября [[w:1583|1583]] года. (Предыдущим днём было 4 октября, числа с 5 по 14 октября включительно были пропущены для устранения 11‑дневного отставания от фактической даты, накопившегося за время использования [[w:Юлианский календарь|юлианского календар]]).
Существует довольно простой '''алгоритм вычисления дня недели''' для любой даты [[w:Григорианский календарь|григорианского календаря]], начиная с первого дня его действия — 15 октября [[w:1582|1582]] года. (Предыдущим днём было 4 октября, числа с 5 по 14 октября включительно были пропущены для устранения 11‑дневного отставания от фактической даты, накопившегося за время использования [[w:Юлианский календарь|юлианского календаря]]).


Положим, дата задана так: ''год'' — год (от 1583), ''месяц'' — номер месяца (1…12), ''число'' — число месяца (1…31, согласно числу дней в соответствующем месяце), тогда:
Положим, дата задана так: ''год'' — год (от 1582), ''месяц'' — номер месяца (1…12), ''число'' — число месяца (1…31, согласно числу дней в соответствующем месяце), тогда:


a = (14 − месяц) / 12
a = (14 − месяц) / 12

Версия от 17:39, 22 июля 2019

Описание

Существует довольно простой алгоритм вычисления дня недели для любой даты григорианского календаря, начиная с первого дня его действия — 15 октября 1582 года. (Предыдущим днём было 4 октября, числа с 5 по 14 октября включительно были пропущены для устранения 11‑дневного отставания от фактической даты, накопившегося за время использования юлианского календаря).

Положим, дата задана так: год — год (от 1582), месяц — номер месяца (1…12), число — число месяца (1…31, согласно числу дней в соответствующем месяце), тогда:

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

либо, что почти то же самое:

если месяц = 1 или месяц = 2: // январь или февраль
	год = год − 1
	месяц = месяц + 10
иначе:
	месяц = месяц − 2
всё
ДеньНедели = (число + (31 * месяц) / 12 + год + год / 4 − год / 100 + год / 400) ОСТАТОК 7

Деление производится нацело (с отбрасыванием остатка).

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

Реализации

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 =(den + y + y4 - y100 + y400 + x)%7; //результат в переменной "ned"
}
//набирал с клавиатуры и убил вечер на тестирование - reodos

BASIC

GW-BASIC и совместимые диалекты

10 INPUT "Year", Y%: INPUT "Month", M%: INPUT "Day", D%
20 IF M% < 3 THEN Y% = Y% - 1: M% = M% + 10: ELSE M% = M% - 2
30 PRINT "Weekday: "; (D% + 31 * M% \ 12 + Y% + Y% \ 4 - Y% \ 100 + Y% \ 400) MOD 7

QuickBasic версий < 4.0, Turbo Basic

DEF FNWD%(Y%, M%, D%)
	IF M% < 3 THEN
		Y% = Y% - 1
		M% = M% + 10
	ELSE
		M% = M% - 2
	END IF
	FNWD% = (D% + 31 * M% \ 12 + Y% + Y% \ 4 - Y% \ 100 + Y% \ 400) MOD 7
END DEF

PowerBASIC, QBASIC, QuickBasic версий ≥ 4.0, Visual Basic

Function Weekday (year As Integer, month As Integer, day As Integer) As Integer
	If month < 3 Then
		year = year - 1
		month = month + 10
	Else
		month = month - 2
	End If
	Weekday = (day + 31 * month \ 12 + year + year \ 4 - year \ 100 + year \ 400) Mod 7 ' Для VB.NET следует заменить Weekday = на Return
End Function

C, C++

typedef unsigned short Year;
typedef unsigned char Month;
typedef unsigned char Day;
typedef unsigned char Weekday;

Weekday weekday(Year year, Month month, Day day) {
	if (month < 3) {
		year -= 1u;
		month += 10u;
	} else
		month -= 2u;
	return (Weekday)((day + 31u * month / 12u + year + year / 4u - year / 100u + year / 400u) % 7u);
}

C#

static byte Weekday(ushort year, byte month, byte day) {
	if (month < 3u) {
		year -= 1u;
		month += 10u;
	} else
		month -= 2u;
	return (byte)(((ushort)day + 31u * (ushort)month / 12u + year + year / 4u - year / 100u + year / 400u) % 7u);
}

Delphi, Pascal

type TYear = Word;
type TMonth = 1..12;
type TDay = 1..31;
type TWeekday = 0..6;

function Weekday(year: TYear; month: TMonth; day: TDay): TWeekday;
begin
	if month < 3 then
	begin
		month := month - 2;
		year := year - 1
	end
	else
		month := month + 10;
	Weekday := (day + 31 * month div 12 + year + year div 4 - year div 100 + year div 400) mod 7
end;

Go

type Year = uint16
type Month = uint8
type Day = uint8
type Weekday = uint8

func weekday(year Year, month Month, day Day) Weekday {
	if month < 3 {
		year -= 1
		month += 10
	} else {
		month -= 2
	}
	return Weekday((Year(day) + 31 * Year(month) / 12 + year + year / 4 - year / 100 + year / 400) % 7)
}

Java

static byte weekday(short year, byte month, byte day) {
	if (month < 3) {
		year -= 1;
		month += 10;
	} else
		month -= 2;
	return (byte)(((short)day + 31 * (short)month / 12 + year + year / 4 - year / 100 + year / 400) % 7);
}

JavaScript

function weekday(year, month, day) {
    year = parseInt(year, 10);
	month = parseInt(month, 10);
	day = parseInt(day, 10);
	if (month < 3) {
		year -= 1;
		month += 10;
	} else
		month -= 2;
	return (day + 31 * month / 12 + year + year / 4 - year / 100 + year / 400) % 7;
}

Microsoft Excel

А2 — ячейка, содержащая дату.

(English): =WEEKDAY(A2;2)
(Русский): =ДЕНЬНЕД(A2;2)

ЛИБО:

=ОКРВНИЗ(ОСТАТ((ДЕНЬ(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)

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 (DAY(@date) + @y + @y / 4 — @y / 100 + @y / 400 + (31 * @m) / 12) % 7

END

PHP

function weekday(int $year, int $month, int $day) {
	if ($month < 3) {
		$year -= 1;
		$month += 10;
	} else
		$month -= 2;
	return ($day + 31 * $month / 12 + $year + $year / 4 - $year / 100 + $year / 400) % 7;
}

Python

def weekday(year: int, month: int, day: int) -> int:
	if month < 3:
		year -= 1
		month += 10
	else:
		month -= 2
	return (day + 31 * month // 12 + year + year // 4 - year // 100 + year // 400) % 7

Ruby

def weekday(year, month, day)
	if month < 3
		year -= 1
		month += 10
	else
		month -= 2
	end
	return (day + 31 * month / 12 + year + year / 4 - year / 100 + year / 400) % 7
end

Rust

type Year = u16;
type Month = u8;
type Day = u8;
type Weekday = u8;

fn weekday(mut year: Year, mut month: Month, day: Day) -> Weekday {
	if month < 3 {
		year -= 1;
		month += 10;
	} else {
		month -= 2;
	}
	((day as Year + 31 * month as Year / 12 + year + year / 4 - year / 100 + year / 400) % 7) as Weekday
}

Командная строка Windows (cmd.exe)

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

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

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

Программируемые микрокалькуляторы «Электроника»

МК-52 / 61 / 152 / 161 / 163 / 1152

В вычислениях участвуют только регистры стека.

00. ↔      01. 3      02. −      03. 1      04. ↔      05. Fx<0   06. 15     07. F🔃     08. ↔      09. F🔃
10. −      11. 1      12. 3      13. ↔      14. F🔃    15. +      16. 3      17. 1       18. ×      19. 1
20. 2      21. ÷      22. К[x]   23. +      24. +      25. ↔      26. 4      27. ÷       28. К[x]   29. +
30. ↔      31. 2      32. F10ˣ   33. ÷      34. ↔      35. FВx    36. К[x]   37. −       38. ↔      39. 4
40. ÷      41. К[x]   42. +      43. В↑     44. В↑     45. 7      46. ÷      47. К[x]    48. 7      49. ×
50. −      51. С/П

Использование: <год> В↑ <месяц> В↑ <число> В/О С/П (номер дня недели на индикаторе).

Ссылки