131529Shelbig/*-
231529Shelbig * Copyright (c) 1997 Wolfgang Helbig
331529Shelbig * All rights reserved.
431529Shelbig *
531529Shelbig * Redistribution and use in source and binary forms, with or without
631529Shelbig * modification, are permitted provided that the following conditions
731529Shelbig * are met:
831529Shelbig * 1. Redistributions of source code must retain the above copyright
931529Shelbig *    notice, this list of conditions and the following disclaimer.
1031529Shelbig * 2. Redistributions in binary form must reproduce the above copyright
1131529Shelbig *    notice, this list of conditions and the following disclaimer in the
1231529Shelbig *    documentation and/or other materials provided with the distribution.
1331529Shelbig *
1431529Shelbig * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1531529Shelbig * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1631529Shelbig * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1731529Shelbig * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1831529Shelbig * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1931529Shelbig * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2031529Shelbig * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2131529Shelbig * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2231529Shelbig * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2331529Shelbig * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2431529Shelbig * SUCH DAMAGE.
2531529Shelbig */
2631529Shelbig
2784197Sdillon#include <sys/cdefs.h>
2884197Sdillon__FBSDID("$FreeBSD$");
2984197Sdillon
3031529Shelbig#include "calendar.h"
3131529Shelbig
3231698Shelbigtypedef struct date date;
3331698Shelbig
3431611Shelbigstatic int	 easterodn(int y);
3531611Shelbig
3631529Shelbig/* Compute Easter Sunday in Gregorian Calendar */
3731529Shelbigdate *
3831529Shelbigeasterg(int y, date *dt)
3931529Shelbig{
4031529Shelbig	int c, i, j, k, l, n;
4131529Shelbig
4231529Shelbig	n = y % 19;
4331529Shelbig	c = y / 100;
4431529Shelbig	k = (c - 17) / 25;
4531529Shelbig	i = (c - c/4 -(c-k)/3 + 19 * n + 15) % 30;
4631529Shelbig	i = i -(i/28) * (1 - (i/28) * (29/(i + 1)) * ((21 - n)/11));
4731529Shelbig	j = (y + y/4 + i + 2 - c + c/4) % 7;
4831529Shelbig	l = i - j;
4931529Shelbig	dt->m = 3 + (l + 40) / 44;
5031529Shelbig	dt->d = l + 28 - 31*(dt->m / 4);
5131529Shelbig	dt->y = y;
5231529Shelbig	return (dt);
5331529Shelbig}
5431529Shelbig
5531611Shelbig/* Compute the Gregorian date of Easter Sunday in Julian Calendar */
5631611Shelbigdate *
5731611Shelbigeasterog(int y, date *dt)
5831611Shelbig{
5931611Shelbig
6031611Shelbig	return (gdate(easterodn(y), dt));
6131611Shelbig}
6231611Shelbig
6331611Shelbig/* Compute the Julian date of Easter Sunday in Julian Calendar */
6431529Shelbigdate   *
6531611Shelbigeasteroj(int y, date * dt)
6631529Shelbig{
6731529Shelbig
6831611Shelbig	return (jdate(easterodn(y), dt));
6931611Shelbig}
7031611Shelbig
7131611Shelbig/* Compute the day number of Easter Sunday in Julian Calendar */
7231611Shelbigstatic int
7331611Shelbigeasterodn(int y)
7431611Shelbig{
7531529Shelbig	/*
7631529Shelbig	 * Table for the easter limits in one metonic (19-year) cycle. 21
7731529Shelbig	 * to 31 is in March, 1 through 18 in April. Easter is the first
7831529Shelbig	 * sunday after the easter limit.
7931529Shelbig	 */
8031529Shelbig	int     mc[] = {5, 25, 13, 2, 22, 10, 30, 18, 7, 27, 15, 4,
8131529Shelbig		    24, 12, 1, 21, 9, 29, 17};
8231529Shelbig
8331529Shelbig	/* Offset from a weekday to next sunday */
8431529Shelbig	int     ns[] = {6, 5, 4, 3, 2, 1, 7};
8531611Shelbig	date	dt;
8631529Shelbig	int     dn;
8731529Shelbig
8831611Shelbig	/* Assign the easter limit of y to dt */
8931611Shelbig	dt.d = mc[y % 19];
9031529Shelbig
9131611Shelbig	if (dt.d < 21)
9231611Shelbig		dt.m = 4;
9331529Shelbig	else
9431611Shelbig		dt.m = 3;
9531529Shelbig
9631611Shelbig	dt.y = y;
9731529Shelbig
9831611Shelbig	/* Return the next sunday after the easter limit */
9931611Shelbig	dn = ndaysj(&dt);
10031611Shelbig	return (dn + ns[weekday(dn)]);
10131529Shelbig}
102