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