easter.c revision 330897
1139743Simp/*- 2123474Swpaul * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3123474Swpaul * 4123474Swpaul * Copyright (c) 1997 Wolfgang Helbig 5123474Swpaul * All rights reserved. 6123474Swpaul * 7123474Swpaul * Redistribution and use in source and binary forms, with or without 8123474Swpaul * modification, are permitted provided that the following conditions 9123474Swpaul * are met: 10123474Swpaul * 1. Redistributions of source code must retain the above copyright 11123474Swpaul * notice, this list of conditions and the following disclaimer. 12123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright 13123474Swpaul * notice, this list of conditions and the following disclaimer in the 14123474Swpaul * documentation and/or other materials provided with the distribution. 15123474Swpaul * 16123474Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17123474Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18123474Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19123474Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20123474Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21123474Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22123474Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23123474Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24123474Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25123474Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26123474Swpaul * SUCH DAMAGE. 27123474Swpaul */ 28123474Swpaul 29123474Swpaul#include <sys/cdefs.h> 30123474Swpaul__FBSDID("$FreeBSD: stable/11/lib/libcalendar/easter.c 330897 2018-03-14 03:19:51Z eadler $"); 31123474Swpaul 32123474Swpaul#include "calendar.h" 33123474Swpaul 34123474Swpaultypedef struct date date; 35123474Swpaul 36123474Swpaulstatic int easterodn(int y); 37123474Swpaul 38123474Swpaul/* Compute Easter Sunday in Gregorian Calendar */ 39123474Swpauldate * 40123474Swpauleasterg(int y, date *dt) 41123474Swpaul{ 42123474Swpaul int c, i, j, k, l, n; 43123474Swpaul 44123474Swpaul n = y % 19; 45123474Swpaul c = y / 100; 46123474Swpaul k = (c - 17) / 25; 47123474Swpaul i = (c - c/4 -(c-k)/3 + 19 * n + 15) % 30; 48123474Swpaul i = i -(i/28) * (1 - (i/28) * (29/(i + 1)) * ((21 - n)/11)); 49123474Swpaul j = (y + y/4 + i + 2 - c + c/4) % 7; 50123474Swpaul l = i - j; 51123474Swpaul dt->m = 3 + (l + 40) / 44; 52129834Swpaul dt->d = l + 28 - 31*(dt->m / 4); 53123474Swpaul dt->y = y; 54123474Swpaul return (dt); 55123474Swpaul} 56123474Swpaul 57123474Swpaul/* Compute the Gregorian date of Easter Sunday in Julian Calendar */ 58123474Swpauldate * 59123474Swpauleasterog(int y, date *dt) 60123474Swpaul{ 61123474Swpaul 62123474Swpaul return (gdate(easterodn(y), dt)); 63123474Swpaul} 64123474Swpaul 65123504Swpaul/* Compute the Julian date of Easter Sunday in Julian Calendar */ 66123848Swpauldate * 67124122Swpauleasteroj(int y, date * dt) 68124272Swpaul{ 69125377Swpaul 70124272Swpaul return (jdate(easterodn(y), dt)); 71124272Swpaul} 72124272Swpaul 73125551Swpaul/* Compute the day number of Easter Sunday in Julian Calendar */ 74132973Swpaulstatic int 75132973Swpauleasterodn(int y) 76132973Swpaul{ 77123474Swpaul /* 78123474Swpaul * Table for the easter limits in one metonic (19-year) cycle. 21 79123474Swpaul * to 31 is in March, 1 through 18 in April. Easter is the first 80123474Swpaul * sunday after the easter limit. 81123474Swpaul */ 82123474Swpaul int mc[] = {5, 25, 13, 2, 22, 10, 30, 18, 7, 27, 15, 4, 83123474Swpaul 24, 12, 1, 21, 9, 29, 17}; 84124203Swpaul 85123474Swpaul /* Offset from a weekday to next sunday */ 86123474Swpaul int ns[] = {6, 5, 4, 3, 2, 1, 7}; 87123474Swpaul date dt; 88123474Swpaul int dn; 89123474Swpaul 90123474Swpaul /* Assign the easter limit of y to dt */ 91123474Swpaul dt.d = mc[y % 19]; 92123474Swpaul 93123474Swpaul if (dt.d < 21) 94123474Swpaul dt.m = 4; 95123695Swpaul else 96123695Swpaul dt.m = 3; 97123695Swpaul 98123474Swpaul dt.y = y; 99123474Swpaul 100123474Swpaul /* Return the next sunday after the easter limit */ 101123474Swpaul dn = ndaysj(&dt); 102123474Swpaul return (dn + ns[weekday(dn)]); 103123512Swpaul} 104128229Swpaul