ostern.c revision 169343
1129199Scognet/*
2129199Scognet * Copyright (c) 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
3129199Scognet * All rights reserved.
4129199Scognet *
5129199Scognet * Redistribution and use in source and binary forms, with or without
6129199Scognet * modification, are permitted provided that the following conditions
7129199Scognet * are met:
8129199Scognet * 1. Redistributions of source code must retain the above copyright
9129199Scognet *    notice, this list of conditions and the following disclaimer.
10129199Scognet * 2. Redistributions in binary form must reproduce the above copyright
11135670Scognet *    notice, this list of conditions and the following disclaimer in the
12129199Scognet *    documentation and/or other materials provided with the distribution.
13129199Scognet *
14129199Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15135670Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16129199Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17129199Scognet * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18129199Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19129199Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20169612Swkoszek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21129199Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22129199Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23129199Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24129199Scognet * SUCH DAMAGE.
25129199Scognet */
26129199Scognet
27129199Scognet#include <sys/cdefs.h>
28129199Scognet__FBSDID("$FreeBSD: head/usr.bin/calendar/ostern.c 169343 2007-05-07 11:18:30Z dwmalone $");
29129199Scognet
30129199Scognet#include <stdio.h>
31129199Scognet#include <stdlib.h>
32129199Scognet#include <string.h>
33209131Sraj#include <time.h>
34209131Sraj
35135670Scognet#include "calendar.h"
36135670Scognet
37140479Scognet/* return year day for Easter */
38157165Scognet
39153112Scognet/*
40147630Scognet * This code is based on the Calendar FAQ's code for how to calculate
41150862Scognet * easter is. This is the Gregorian calendar version. They refer to
42248126Sandrew * the Algorithm of Oudin in the "Explanatory Supplement to the
43245838Sandrew * Astronomical Almanac".
44248126Sandrew */
45245838Sandrew
46160629Scognetint
47253396Sandreweaster(int year) /* 0 ... abcd, NOT since 1900 */
48160629Scognet{
49248365Sandrew    int G,	/* Golden number - 1 */
50253396Sandrew	C,	/* Century */
51245675Sandrew	H,	/* 23 - epact % 30 */
52248126Sandrew	I,	/* days from 21 March to Paschal full moon */
53248126Sandrew	J,	/* weekday of full moon */
54248126Sandrew	L;	/* days from 21 March to Sunday on of before full moon */
55160629Scognet
56248126Sandrew    G = year % 19;
57160629Scognet    C = year / 100;
58243664Smarcel    H = (C - C/4 - (8*C+13)/25 + 19*G + 15) % 30;
59152742Scognet    I = H - (H/28)*(1 - (H/28)*(29/(H + 1))*((21 - G)/11));
60152742Scognet    J = (year + year/4 + I + 2 - C + C/4) % 7;
61153549Scognet
62152742Scognet    L = I - J;
63152742Scognet
64152742Scognet    if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
65152742Scognet	return 31 + 29 + 21 + L + 7;
66152742Scognet    else
67153566Scognet	return 31 + 28 + 21 + L + 7;
68175984Sraj}
69175984Sraj
70175984Sraj/* return year day for  Easter or easter depending days
71175984Sraj * Match: Easter([+-][0-9]+)?
72159084Scognet * e.g: Easter-2 is  Good Friday (2 days before Easter)
73159084Scognet */
74159084Scognet
75171619Scognetint
76183840Srajgeteaster(char *s, int year)
77239268Sgonzo{
78239268Sgonzo	int offset = 0;
79239268Sgonzo
80177895Simp#define EASTER "easter"
81177895Simp#define EASTERNAMELEN (sizeof(EASTER) - 1)
82153566Scognet
83159758Scognet	if (strncasecmp(s, EASTER, EASTERNAMELEN) == 0)
84153566Scognet	    s += EASTERNAMELEN;
85153566Scognet	else if (   neaster.name != NULL
86153549Scognet		 && strncasecmp(s, neaster.name, neaster.len) == 0
87248362Sandrew		)
88171619Scognet	    s += neaster.len;
89171619Scognet	else
90171619Scognet	    return(0);
91153549Scognet
92248362Sandrew#if DEBUG
93159557Scognet	printf("%s %d %d\n", s, year, EASTERNAMELEN);
94248362Sandrew#endif
95181294Scognet
96248362Sandrew	/* Easter+1  or Easter-2
97248362Sandrew	 *       ^            ^   */
98181294Scognet
99248362Sandrew	switch(*s) {
100248362Sandrew
101248363Sandrew	case '-':
102248363Sandrew	case '+':
103248362Sandrew	    offset = atoi(s);
104153566Scognet	    break;
105248362Sandrew
106154561Scognet	default:
107248362Sandrew	    offset = 0;
108238464Simp	}
109153112Scognet
110248362Sandrew	return (easter(year) + offset);
111223116Scognet}
112223116Scognet