svn commit: r203154 - user/edwin/calendar

Edwin Groothuis edwin at FreeBSD.org
Fri Jan 29 06:39:58 UTC 2010


Author: edwin
Date: Fri Jan 29 06:39:57 2010
New Revision: 203154
URL: http://svn.freebsd.org/changeset/base/203154

Log:
  Support for sun-position calculation: solstice and equinox

Added:
  user/edwin/calendar/chinesecalendar.txt
  user/edwin/calendar/cny.c
  user/edwin/calendar/sunpos.c
  user/edwin/calendar/sunpos.txt
Modified:
  user/edwin/calendar/Makefile
  user/edwin/calendar/calendar.h
  user/edwin/calendar/io.c
  user/edwin/calendar/ostern.c
  user/edwin/calendar/parsedata.c
  user/edwin/calendar/paskha.c

Modified: user/edwin/calendar/Makefile
==============================================================================
--- user/edwin/calendar/Makefile	Fri Jan 29 05:44:20 2010	(r203153)
+++ user/edwin/calendar/Makefile	Fri Jan 29 06:39:57 2010	(r203154)
@@ -5,7 +5,7 @@ CFLAGS=	 -pipe  -g -std=gnu99 -fstack-pr
 
 PROG=	calendar
 SRCS=   calendar.c locale.c events.c dates.c parsedata.c io.c day.c \
-	ostern.c paskha.c pom.c
+	ostern.c paskha.c pom.c sunpos.c
 LDADD=	-lm
 INTER=          de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \
 		hr_HR.ISO8859-2 hu_HU.ISO8859-2 ru_RU.KOI8-R uk_UA.KOI8-U
@@ -13,9 +13,6 @@ DE_LINKS=       de_DE.ISO8859-15
 FR_LINKS=       fr_FR.ISO8859-15
 TEXTMODE?=	444
 
-pom: pom.c
-	gcc -g -Wall -o pom pom.c -lm
-
 beforeinstall:
 	${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${TEXTMODE} \
 	    ${.CURDIR}/calendars/calendar.* ${DESTDIR}${SHAREDIR}/calendar

Modified: user/edwin/calendar/calendar.h
==============================================================================
--- user/edwin/calendar/calendar.h	Fri Jan 29 05:44:20 2010	(r203153)
+++ user/edwin/calendar/calendar.h	Fri Jan 29 06:39:57 2010	(r203154)
@@ -48,31 +48,40 @@ extern time_t t1, t2;
 extern const char *calendarFile;
 extern int yrdays;
 extern struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
+extern struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
 
 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
 
 /* Flags to determine the returned values by determinestyle() in parsedata.c */
-#define	F_NONE			0x0000
-#define	F_MONTH			0x0001
-#define	F_DAYOFWEEK		0x0002
-#define	F_DAYOFMONTH		0x0004
-#define	F_MODIFIERINDEX		0x0008
-#define	F_MODIFIEROFFSET	0x0010
-#define	F_SPECIALDAY		0x0020
-#define	F_ALLMONTH		0x0040
-#define	F_ALLDAY		0x0080
-#define	F_VARIABLE		0x0100
-#define	F_EASTER		0x0200
-#define	F_CNY			0x0400
-#define	F_PASKHA		0x0800
-#define	F_NEWMOON		0x1000
-#define	F_FULLMOON		0x2000
+#define	F_NONE			0x00000
+#define	F_MONTH			0x00001
+#define	F_DAYOFWEEK		0x00002
+#define	F_DAYOFMONTH		0x00004
+#define	F_MODIFIERINDEX		0x00008
+#define	F_MODIFIEROFFSET	0x00010
+#define	F_SPECIALDAY		0x00020
+#define	F_ALLMONTH		0x00040
+#define	F_ALLDAY		0x00080
+#define	F_VARIABLE		0x00100
+#define	F_EASTER		0x00200
+#define	F_CNY			0x00400
+#define	F_PASKHA		0x00800
+#define	F_NEWMOON		0x01000
+#define	F_FULLMOON		0x02000
+#define	F_MAREQUINOX		0x04000
+#define	F_SEPEQUINOX		0x08000
+#define	F_JUNSOLSTICE		0x10000
+#define	F_DECSOLSTICE		0x20000
 
 #define	STRING_EASTER	"Easter"
 #define	STRING_PASKHA	"Paskha"
 #define	STRING_CNY	"ChineseNewYear"
 #define STRING_NEWMOON	"NewMoon"
 #define STRING_FULLMOON	"FullMoon"
+#define STRING_MAREQUINOX	"MarEquinox"
+#define STRING_SEPEQUINOX	"SepEquinox"
+#define STRING_JUNSOLSTICE	"JunSolstice"
+#define STRING_DECSOLSTICE	"DecSolstice"
 
 extern int	debug;		/* show parsing of the input */
 extern int	f_dayAfter;	/* days after current date */
@@ -152,3 +161,5 @@ void	addtodate(struct event *e, int year
 #define	MAXMOONS	15
 void	pom(int year, int *fms, int *nms);
 
+/* sunpos.c */
+void	equinoxsolstice(int year, double UTCoffset, int *equinoxdays, int *solsticedays);

Added: user/edwin/calendar/chinesecalendar.txt
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/edwin/calendar/chinesecalendar.txt	Fri Jan 29 06:39:57 2010	(r203154)
@@ -0,0 +1,387 @@
+http://www.webexhibits.org/calendars/calendar-chinese.html
+Title: The Chinese Calendar | Calendar
+Important stuff: Prefixed with |
+
+
+   The Chinese Calendar
+                                     Dragon
+
+   Chinese New Year Celebrations
+
+   Chinese New Year parades have their origins in the California Gold Rush,
+   when immigrants sought to share their culture. Today, New Year's parades
+   take place around the globe.
+
+   Chinese New Year is the main holiday of the year for more than one quarter
+   of the world's population. Although the People's Republic of China uses
+   the Gregorian calendar for civil purposes, a special Chinese calendar is
+   used for determining festivals. Various Chinese communities around the
+   world also use this calendar.
+
+   The beginnings of the Chinese calendar can be traced back to the 14th
+   century B.C.E. Legend has it that the Emperor Huangdi invented the
+   calendar in 2637 B.C.E.
+
+   The Chinese calendar is based on exact astronomical observations of the
+   longitude of the sun and the phases of the moon. This means that
+   principles of modern science have had an impact on the Chinese calendar.
+
+     * What Does the Chinese Year Look Like?
+     * What Years Are Leap Years?
+     * How Does One Count Years?
+     * What Is the Current Year in the Chinese Calendar?
+     * What about the year 2033?
+     * When did the calendar really start?
+     * What was the early Chinese calendar?
+     * Details of early calendars
+     * When were foreign calendars introduced?
+
+ What Does the Chinese Year Look Like?
+
+   The Chinese calendar - like the Hebrew - is a combined solar/lunar
+   calendar in that it strives to have its years coincide with the tropical
+   year and its months coincide with the synodic months. It is not surprising
+   that a few similarities exist between the Chinese and the Hebrew calendar:
+
+     * An ordinary year has 12 months, a leap year has 13 months.
+     * An ordinary year has 353, 354, or 355 days, a leap year has 383, 384,
+       or 385 days.
+
+|  When determining what a Chinese year looks like, one must make a number of
+|  astronomical calculations:
+|
+|  First, determine the dates for the new moons. Here, a new moon is the
+|  completely "black" moon (that is, when the moon is in conjunction with the
+|  sun), not the first visible crescent used in the Islamic and Hebrew
+|  calendars. The date of a new moon is the first day of a new month.
+|
+|  Second, determine the dates when the sun's longitude is a multiple of 30
+|  degrees. (The sun's longitude is 0 at Vernal Equinox, 90 at Summer
+|  Solstice, 180 at Autumnal Equinox, and 270 at Winter Solstice.) These
+|  dates are called the Principal Terms and are used to determine the number
+|  of each month:
+
+     * Principal Term 1 occurs when the sun's longitude is 330 degrees.
+     * Principal Term 2 occurs when the sun's longitude is 0 degrees.
+     * Principal Term 3 occurs when the sun's longitude is 30 degrees. (etc.)
+     * Principal Term 11 occurs when the sun's longitude is 270 degrees.
+     * Principal Term 12 occurs when the sun's longitude is 300 degrees.
+
+   Each month carries the number of the Principal Term that occurs in that
+   month.
+
+   In rare cases, a month may contain two Principal Terms; in this case the
+   months numbers may have to be shifted. Principal Term 11 (Winter Solstice)
+   must always fall in the 11th month.
+
+|  All the astronomical calculations are carried out for the meridian 120
+|  degrees east of Greenwich. This roughly corresponds to the east coast of
+|  China.
+
+   Some variations in these rules are seen in various Chinese communities.
+
+ What Years Are Leap Years?
+
+   Leap years have 13 months. To determine if a year is a leap year,
+   calculate the number of new moons between the 11th month in one year
+   (i.e., the month containing the Winter Solstice) and the 11th month in the
+   following year. If there are 13 new moons from the start of the 11th month
+   in the first year to the start of the 11th month in the second year, a
+   leap month must be inserted.
+
+   In leap years, at least one month does not contain a Principal Term. The
+   first such month is the leap month. It carries the same number as the
+   previous month, with the additional note that it is the leap month.
+
+ How Does One Count Years?
+
+   Unlike most other calendars, the Chinese calendar does not count years in
+   an infinite sequence. Instead years have names that are repeated every 60
+   years.
+
+   (Historically, years used to be counted since the accession of an emperor,
+   but this was abolished after the 1911 revolution.)
+
+   Within each 60-year cycle, each year is assigned name consisting of two
+   components:
+
+   The first component is a Celestial Stemm. These words have no English
+   equivalent:
+
+   1 jia  6  ji
+   2 yi   7  geng
+   3 bing 8  xin
+   4 ding 9  ren
+   5 wu   10 gui
+
+   The second component is a Terrestrial Branch. The names of the
+   corresponding animals in the zodiac cycle of 12 animals are given in
+   parentheses.
+
+   1 zi (rat)           7  wu (horse)
+   2 chou (ox)          8  wei (sheep)
+   3 yin (tiger)        9  shen (monkey)
+   4 mao (hare, rabbit) 10 you (rooster)
+   5 chen (dragon)      11 xu (dog)
+   6 si (snake)         12 hai (pig)
+
+   Each of the two components is used sequentially. Thus, the 1st year of the
+   60-year cycle becomes jia-zi, the 2nd year is yi-chou, the 3rd year is
+   bing-yin, etc. When we reach the end of a component, we start from the
+   beginning: The 10th year is gui-you, the 11th year is jia-xu (restarting
+   the Celestial Stem), the 12th year is yi-hai, and the 13th year is bing-zi
+   (restarting the Terrestrial Branch). Finally, the 60th year becomes
+   gui-hai.
+
+   This way of naming years within a 60-year cycle goes back approximately
+   2000 years. A similar naming of days and months has fallen into disuse,
+   but the date name is still listed in calendars.
+
+   It is customary to number the 60-year cycles since 2637 B.C.E., when the
+   calendar was supposedly invented. In that year the first 60-year cycle
+   started.
+
+ What Is the Current Year in the Chinese Calendar?
+
+|  The current 60-year cycle started on 2 Feb 1984. That date bears the name
+|  bing-yin in the 60-day cycle, and the first month of that first year bears
+|  the name gui-chou in the 60-month cycle.
+
+   This means that the year wu-yin, the 15th year in the 78th cycle, started
+   on 28 Jan 1998. The 20th year in the 78th cycle, started on 1 Feb 2003.
+
+   The following are dates for Chinese/Lunar New Year's day:
+
+   Chinese year Zodiac animal Gregorian calendar
+   4693         Boar          January 31, 1995
+   4694         Rat           February 19, 1996
+   4695         Ox            February 7, 1997
+   4696         Tiger         January 28, 1998
+   4697         Hare/Rabbit   February 16, 1999
+   4698         Dragon        February 5, 2000
+   4699         Snake         January 24, 2001
+   4700         Horse         February 12, 2002
+   4701         Ram/Sheep     February 1, 2003
+   4702         Monkey        January 22, 2004
+   4703         Rooster       February 9, 2005
+   4704         Dog           January 29, 2006
+   4705         Boar          February 18, 2007
+   4706         Rat           February 7, 2008
+   4707         Ox            January 26, 2009
+   4708         Tiger         February 10, 2010
+   4709         Hare/Rabbit   February 3, 2011
+   4710         Dragon        January 23, 2012
+   4711         Snake         February 10, 2013
+   4712         Horse         January 31, 2014
+   4713         Ram/Sheep     February 19, 2015
+   4714         Monkey        February 9, 2016
+   4715         Rooster       January 28, 2017
+   4716         Dog           February 16, 2018
+   4717         Boar          February 5, 2019
+   4718         Rat           January 25, 2020
+
+ What about the year 2033?
+
+   In the early 1990s, Chinese astronomers discovered that there was an error
+   in the Chinese calendar for 2033. The traditional calendar claimed that
+   the leap month would follow the 7th month, while in fact it comes after
+   the 11th month. It is very unusual that the 11th month has a leap month,
+   in fact it hasn't happened since the calendar reform in 1645 (before 1645,
+   all months had the same probability for having a leap month). But many
+   Chinese astronomers still claim that there will never be a leap month
+   after the 12th and 1st month. In addition, there will be a leap month
+   after the 1st month in 2262 (in fact, it should have happened in 1651, but
+   they got the calculations wrong!) and there will be a leap month after the
+   12th month in 3358. Since the Chinese calendar is an astronomical
+   calendar, predictions require delicate astronomical calculations, so my
+   computations for 3358 should probably be taken with a grain of salt.
+
+ When did the calendar really start?
+
+   If the Chinese calendar started in 2637 B.C.E., why is the current year 60
+   years too late? (e.g., in 1999, the current year was 4697? and not 4637)?
+
+   The Chinese calendar does not use a continuous year count! They used a 60
+   year cycle and a system of regional years (starting with each emperor).
+   Before the 1911 revolution, Sun Yat-sen wanted to establish a republican
+   alternative to the imperial reign cycles. According to Chinese tradition,
+   the first year of the Yellow Emperor was 2698 B.C.E., so he introduced a
+   counting system based on this. Under this system, 2000 is year 4698. An
+   alternative system is to start with the first historical record of the
+   60-day cycle from March 8, 2637 B.C.E. Based on this system, 2000 is year
+   4637.
+
+                               shang oracle bones
+
+   Two oracle bones from the Shang Dynasty in China (c. 1800 - 1200 BCE)
+
+   Evidence from the Shang oracle bone inscriptions shows that at least by
+   the 14th century BC the Shang Chinese had established the solar year at
+   365 1/4 days and lunation at 29 1/2 days. In the calendar that the Shang
+   used, the seasons of the year and the phases of the Moon were all
+   supposedly accounted for.
+
+ What was the Early Chinese calendar?
+
+   In China, the calendar was a sacred document, sponsored and promulgated by
+   the reigning monarch. For more than two millennia, a Bureau of Astronomy
+   made astronomical observations, calculated astronomical events such as
+   eclipses, prepared astrological predictions, and maintained the calendar.
+   After all, a successful calendar not only served practical needs, but also
+   confirmed the consonance between Heaven and the imperial court.
+
+   Analysis of surviving astronomical records inscribed on oracle bones
+   reveals a Chinese lunisolar calendar, with intercalation of lunar months,
+   dating back to the Shang dynasty of the fourteenth century B.C.E. Various
+   intercalation schemes were developed for the early calendars, including
+   the nineteen-year and 76-year lunar phase cycles that came to be known in
+   the West as the Metonic cycle and Callipic cycle.
+
+   From the earliest records, the beginning of the year occurred at a New
+   Moon near the winter solstice. The choice of month for beginning the civil
+   year varied with time and place, however. In the late second century
+   B.C.E., a calendar reform established the practice, which continues today,
+   of requiring the winter solstice to occur in month 11. This reform also
+   introduced the intercalation system in which dates of New Moons are
+   compared with the 24 solar terms. However, calculations were based on the
+   mean motions resulting from the cyclic relationships. Inequalities in the
+   Moon's motions were incorporated as early as the seventh century C.E., but
+   the Sun's mean longitude was used for calculating the solar terms until
+   1644.
+
+   Years were counted from a succession of eras established by reigning
+   emperors. Although the accession of an emperor would mark a new era, an
+   emperor might also declare a new era at various times within his reign.
+   The introduction of a new era was an attempt to reestablish a broken
+   connection between Heaven and Earth, as personified by the emperor. The
+   break might be revealed by the death of an emperor, the occurrence of a
+   natural disaster, or the failure of astronomers to predict a celestial
+   event such as an eclipse. In the latter case, a new era might mark the
+   introduction of new astronomical or calendrical models.
+
+   Sexagenary cycles were used to count years, months, days, and fractions of
+   a day using the set of Celestial Stems and Terrestrial Branches. Use of
+   the sixty-day cycle is seen in the earliest astronomical records. By
+   contrast the sixty-year cycle was introduced in the first century C.E. or
+   possibly a century earlier. Although the day count has fallen into disuse
+   in everyday life, it is still tabulated in calendars. The initial year
+   (jia-zi) of the current year cycle began on 1984 February 2, which is the
+   third day (bing-yin) of the day cycle.
+
+ Details of early calendars
+
+   One of the two methods that they used to make this calendar was to add an
+   extra month of 29 or 30 days, which they termed the 13th month, to the end
+   of a regular 12-month year. There is also evidence that suggests that the
+   Chinese developed the Metonic cycle (see above Complex cycles) - i.e., 19
+   years with a total of 235 months-a century ahead of Meton's first
+   calculation (no later than the Spring and Autumn period, 770-476 BC).
+   During this cycle of 19 years there were seven intercalations of months.
+   The other method, which was abandoned soon after the Shang started to
+   adopt it, was to insert an extra month between any two months of a regular
+   year. Possibly, a lack of astronomical and arithmetical knowledge allowed
+   them to do this.
+
+   By the 3rd century BC, the first method of intercalation was gradually
+   falling into disfavour, while the establishment of the meteorological
+   cycle, the erh-shih-ssu chieh-ch'i (Pinyin ershisi jieqi), during this
+   period officially revised the second method. This meteorological cycle
+   contained 24 points, each beginning one of the periods named consecutively
+   the Spring Begins, the Rain Water, the Excited Insects, the Vernal
+   Equinox, the Clear and Bright, the Grain Rains, the Summer Begins, the
+   Grain Fills, the Grain in Ear, the Summer Solstice, the Slight Heat, the
+   Great Heat, the Autumn Begins, the Limit of Heat, the White Dew, the
+   Autumn Equinox, the Cold Dew, the Hoar Frost Descends, the Winter Begins,
+   the Little Snow, the Heavy Snow, the Winter Solstice, the Little Cold, and
+   the Severe Cold. The establishment of this cycle required a fair amount of
+   astronomical understanding of the Earth as a celestial body, and without
+   elaborate equipment it is impossible to collect the necessary information.
+   Modern scholars acknowledge the superiority of pre-Sung Chinese astronomy
+   (at least until about the 13th century AD) over that of other,
+   contemporary nations.
+
+   The 24 points within the meteorological cycle coincide with points 15-o
+   apart on the ecliptic (the plane of the Earth's yearly journey around the
+   Sun or, if it is thought that the Sun turns around the Earth, the apparent
+   journey of the Sun against the stars). It takes about 15.2 days for the
+   Sun to travel from one of these points to another (because the ecliptic is
+   a complete circle of 360-o), and the Sun needs 365  1/4 days to finish its
+   journey in this cycle. Supposedly, each of the 12 months of the year
+   contains two points, but, because a lunar month has only 29  1/2 days and
+   the two points share about 30.4 days, there is always the chance that a
+   lunar month will fail to contain both points, though the distance between
+   any two given points is only 15-o. If such an occasion occurs, the
+   intercalation of an extra month takes place. For instance, one may find a
+   year with two "Julys" or with two "Augusts" in the Chinese calendar. In
+   fact, the exact length of the month in the Chinese calendar is either 30
+   days or 29 days-a phenomenon which reflects its lunar origin. Also, the
+   meteorological cycle means essentially a solar year. The Chinese thus
+   consider their calendar as yin-yang li, or a "lunar-solar calendar."
+
+ When were foreign calendars introduced?
+
+   Although the yin-yang li has been continuously employed by the Chinese,
+   foreign calendars were introduced to the Chinese, the Hindu calendar, for
+   instance, during the T'ang (Tang) dynasty (618-907), and were once used
+   concurrently with the native calendar. This situation also held true for
+   the Muslim calendar, which was introduced during the Yuean dynasty
+   (1206-1368). The Gregorian calendar was taken to China by Jesuit
+   missionaries in 1582, the very year that it was first used by Europeans.
+   Not until 1912, after the general public adopted the Gregorian calendar,
+   did the yin-yang li lose its primary importance.
+
+   Western (pre-Copernican) astronomical theories were introduced to China by
+   Jesuit missionaries in the seventeenth century. Gradually, more modern
+   Western concepts became known. Following the revolution of 1911, the
+   traditional practice of counting years from the accession of an emperor
+   was abolished.
+
+        Made with SpicyNodes| Books | Museum store | Credits & feedback
+
+              Copyright (c) 2008 IDEA -- webexhibits.org/calendars
+
+ References
+
+   Visible links
+   . Calendars exhibit
+	http://www.webexhibits.org/calendars/
+   . Webexhibit
+	http://webexhibits.org/
+   . http://www.webexhibits.org/calendars/index.html
+   . http://www.webexhibits.org/calendars/nodes.html
+   . http://www.webexhibits.org/calendars/year.html
+   . http://www.webexhibits.org/calendars/calendar.html
+   . http://www.webexhibits.org/calendars/week.html
+   . http://www.webexhibits.org/calendars/timeline.html
+   . http://www.webexhibits.org/calendars/introduction.html
+   . http://www.webexhibits.org/calendars/calendar.html
+   . http://www.webexhibits.org/calendars/calendar-chinese.html
+   . http://www.webexhibits.org/calendars/calendar-christian.html
+   . http://www.webexhibits.org/calendars/calendar-indian.html
+   . http://www.webexhibits.org/calendars/calendar-islamic.html
+   . http://www.webexhibits.org/calendars/calendar-jewish.html
+   . http://www.webexhibits.org/calendars/calendar-other.html
+   . http://www.webexhibits.org/calendars/calendar-ancient.html
+   . http://www.webexhibits.org/calendars/calendar-french.html
+   . http://www.webexhibits.org/calendars/calendar-future.html
+   . http://www.webexhibits.org/calendars/calendar-mayan.html
+   . http://www.webexhibits.org/calendars/calendar-roman.html
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-chinese-year
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-leap-years
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-count-years
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-chinese-calendar
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-2033
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-really-start
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-early-chinese
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-details-early
+   . http://www.webexhibits.org/calendars/calendar-chinese.html#anchor-foreign-calendars
+   . Books
+	http://www.webexhibits.org/calendars/books.html
+   . Museum store
+	http://www.webexhibits.org/calendars/museumstore.html
+   . Credits & feedback
+	http://www.webexhibits.org/calendars/credits.html
+   . IDEA
+	http://idea.org/
+   . calendars
+	http://webexhibits.org/calendars

Added: user/edwin/calendar/cny.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/edwin/calendar/cny.c	Fri Jan 29 06:39:57 2010	(r203154)
@@ -0,0 +1,10 @@
+/*
+ * Last new moon before Chinese spring season.
+ * Chinese spring starts when the sun's longitude is 0 at Vernal Equinox.
+ *
+ * All the astronomical calculations are carried out for the meridian 120
+ * degrees east of Greenwich.
+ *
+ * See the file chinesecalendar.txt or the URL
+ * http://www.webexhibits.org/calendars/calendar-chinese.html
+ */

Modified: user/edwin/calendar/io.c
==============================================================================
--- user/edwin/calendar/io.c	Fri Jan 29 05:44:20 2010	(r203153)
+++ user/edwin/calendar/io.c	Fri Jan 29 06:39:57 2010	(r203154)
@@ -70,6 +70,7 @@ const char *calendarNoMail = "nomail";	/
 char	path[MAXPATHLEN];
 
 struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
+struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
 
 struct iovec header[] = {
 	{"From: ", 6},
@@ -82,6 +83,15 @@ struct iovec header[] = {
 };
 
 #define MAXCOUNT	55
+#define	REPLACE(string, slen, struct_) \
+		if (strncasecmp(buf, (string), (slen)) == 0 && buf[(slen)]) { \
+			if (struct_.name != NULL)			      \
+				free(struct_.name);			      \
+			if ((struct_.name = strdup(buf + (slen))) == NULL)    \
+				errx(1, "cannot allocate memory");	      \
+			struct_.len = strlen(buf + (slen));		      \
+			continue;					      \
+		}
 void
 cal(void)
 {
@@ -121,53 +131,22 @@ cal(void)
 		if (buf[0] == '\0')
 			continue;
 
-		/* Parse special definitions: LANG, Easter and Paskha */
+		/* Parse special definitions: LANG, Easter, Paskha etc */
 		if (strncmp(buf, "LANG=", 5) == 0) {
 			(void)setlocale(LC_ALL, buf + 5);
 			d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
 			setnnames();
 			continue;
 		}
-		if (strncasecmp(buf, "Easter=", 7) == 0 && buf[7]) {
-			if (neaster.name != NULL)
-				free(neaster.name);
-			if ((neaster.name = strdup(buf + 7)) == NULL)
-				errx(1, "cannot allocate memory");
-			neaster.len = strlen(buf + 7);
-			continue;
-		}
-		if (strncasecmp(buf, "Paskha=", 7) == 0 && buf[7]) {
-			if (npaskha.name != NULL)
-				free(npaskha.name);
-			if ((npaskha.name = strdup(buf + 7)) == NULL)
-				errx(1, "cannot allocate memory");
-			npaskha.len = strlen(buf + 7);
-			continue;
-		}
-		if (strncasecmp(buf, "ChineseNewYear=", 15) == 0 && buf[15]) {
-			if (ncny.name != NULL)
-				free(ncny.name);
-			if ((ncny.name = strdup(buf + 15)) == NULL)
-				errx(1, "cannot allocate memory");
-			ncny.len = strlen(buf + 15);
-			continue;
-		}
-		if (strncasecmp(buf, "NewMoon=", 8) == 0 && buf[8]) {
-			if (nnewmoon.name != NULL)
-				free(nnewmoon.name);
-			if ((nnewmoon.name = strdup(buf + 8)) == NULL)
-				errx(1, "cannot allocate memory");
-			nnewmoon.len = strlen(buf + 8);
-			continue;
-		}
-		if (strncasecmp(buf, "FullMoon=", 9) == 0 && buf[9]) {
-			if (nfullmoon.name != NULL)
-				free(nfullmoon.name);
-			if ((nfullmoon.name = strdup(buf + 9)) == NULL)
-				errx(1, "cannot allocate memory");
-			nfullmoon.len = strlen(buf + 9);
-			continue;
-		}
+		REPLACE("Easter=", 7, neaster);
+		REPLACE("Paskha=", 7, npaskha);
+		REPLACE("ChineseNewYear=", 15, ncny);
+		REPLACE("NewMoon=", 8, nnewmoon);
+		REPLACE("FullMoon=", 9, nfullmoon);
+		REPLACE("MarEquinox=", 11, nmarequinox);
+		REPLACE("SepEquinox=", 11, nsepequinox);
+		REPLACE("JunSolstice=", 12, njunsolstice);
+		REPLACE("DecSolstice=", 12, ndecsolstice);
 
 		/*
 		 * If the line starts with a tab, the data has to be

Modified: user/edwin/calendar/ostern.c
==============================================================================
--- user/edwin/calendar/ostern.c	Fri Jan 29 05:44:20 2010	(r203153)
+++ user/edwin/calendar/ostern.c	Fri Jan 29 06:39:57 2010	(r203154)
@@ -65,45 +65,3 @@ easter(int year) /* 0 ... abcd, NOT sinc
 	else
 		return 31 + 28 + 21 + L + 7;
 }
-
-/* return year day for  Easter or easter depending days
- * Match: Easter([+-][0-9]+)?
- * e.g: Easter-2 is  Good Friday (2 days before Easter)
- */
-
-int
-geteaster(char *s, int year)
-{
-	int offset = 0;
-
-#define	EASTER "easter"
-#define	EASTERNAMELEN (sizeof(EASTER) - 1)
-
-	if (strncasecmp(s, EASTER, EASTERNAMELEN) == 0)
-		s += EASTERNAMELEN;
-	else if (neaster.name != NULL
-	    && strncasecmp(s, neaster.name, neaster.len) == 0)
-		s += neaster.len;
-	else
-		return (0);
-
-#ifdef DEBUG
-	printf("%s %d %d\n", s, year, EASTERNAMELEN);
-#endif
-
-	/* Easter+1  or Easter-2
-	 *       ^            ^   */
-
-	switch (*s) {
-
-	case '-':
-	case '+':
-		offset = atoi(s);
-		break;
-
-	default:
-		offset = 0;
-	}
-
-	return (easter(year) + offset);
-}

Modified: user/edwin/calendar/parsedata.c
==============================================================================
--- user/edwin/calendar/parsedata.c	Fri Jan 29 05:44:20 2010	(r203153)
+++ user/edwin/calendar/parsedata.c	Fri Jan 29 06:39:57 2010	(r203154)
@@ -79,7 +79,7 @@ static int parseoffset(char *s);
  * SpecialDay		::=	'Easter' | 'Pashka' | 'ChineseNewYear'
  *
  */
-int
+static int
 determinestyle(char *date, int *flags,
     char *month, int *imonth, char *dayofmonth, int *idayofmonth,
     char *dayofweek, int *idayofweek, char *modifieroffset,
@@ -135,6 +135,22 @@ determinestyle(char *date, int *flags,
 			CHECKSPECIAL(date, STRING_EASTER,
 			    strlen(STRING_EASTER), F_EASTER);
 			CHECKSPECIAL(date, neaster.name, neaster.len, F_EASTER);
+			CHECKSPECIAL(date, STRING_MAREQUINOX,
+			    strlen(STRING_MAREQUINOX), F_MAREQUINOX);
+			CHECKSPECIAL(date, nmarequinox.name, nmarequinox.len,
+			    F_SEPEQUINOX);
+			CHECKSPECIAL(date, STRING_SEPEQUINOX,
+			    strlen(STRING_SEPEQUINOX), F_SEPEQUINOX);
+			CHECKSPECIAL(date, nsepequinox.name, nsepequinox.len,
+			    F_SEPEQUINOX);
+			CHECKSPECIAL(date, STRING_JUNSOLSTICE,
+			    strlen(STRING_JUNSOLSTICE), F_JUNSOLSTICE);
+			CHECKSPECIAL(date, njunsolstice.name, njunsolstice.len,
+			    F_JUNSOLSTICE);
+			CHECKSPECIAL(date, STRING_DECSOLSTICE,
+			    strlen(STRING_DECSOLSTICE), F_DECSOLSTICE);
+			CHECKSPECIAL(date, ndecsolstice.name, ndecsolstice.len,
+			    F_DECSOLSTICE);
 			if (checkdayofweek(date, &len, &offset, &dow) != 0) {
 				*flags |= F_DAYOFWEEK;
 				*flags |= F_VARIABLE;
@@ -286,7 +302,7 @@ remember(int index, int *y, int *m, int 
 	d[index] = dd;
 }
 
-void
+static void
 debug_determinestyle(int dateonly, char *date, int flags, char *month,
     int imonth, char *dayofmonth, int idayofmonth, char *dayofweek,
     int idayofweek, char *modifieroffset, char *modifierindex, char *specialday)
@@ -332,6 +348,7 @@ parsedaymonth(char *date, int *yearp, in
 
 	int ieaster, ipaskha;
 	int ifullmoon[MAXMOONS], inewmoon[MAXMOONS];
+	int equinoxdays[2], solsticedays[2];
 
 	int *mondays, d, m, dow, rm, rd, offset;
 
@@ -366,9 +383,11 @@ parsedaymonth(char *date, int *yearp, in
 
 	index = 0;
 	for (year = year1; year <= year2; year++) {
+		/* Get important dates for this year */
 		mondays = mondaytab[isleap(year)];
 		ieaster = easter(year);
 		pom(year, ifullmoon, inewmoon);
+		equinoxsolstice(year, 0.0, equinoxdays, solsticedays);
 
 		/* Same day every year */
 		if (*flags == (F_MONTH | F_DAYOFMONTH)) {
@@ -531,11 +550,58 @@ parsedaymonth(char *date, int *yearp, in
 			continue;
 		}
 
+		/* (Mar|Sep)Equinox */
+		if ((*flags & ~F_MODIFIEROFFSET) ==
+		    (F_SPECIALDAY | F_VARIABLE | F_MAREQUINOX)) {
+			offset = 0;
+			if ((*flags & F_MODIFIEROFFSET) != 0)
+				offset = parseoffset(modifieroffset);
+			if (remember_yd(year, equinoxdays[0] + offset,
+			    &rm, &rd))
+				remember(index++, yearp, monthp, dayp,
+				    year, rm, rd);
+			continue;
+		}
+		if ((*flags & ~F_MODIFIEROFFSET) ==
+		    (F_SPECIALDAY | F_VARIABLE | F_SEPEQUINOX)) {
+			offset = 0;
+			if ((*flags & F_MODIFIEROFFSET) != 0)
+				offset = parseoffset(modifieroffset);
+			if (remember_yd(year, equinoxdays[1] + offset,
+			    &rm, &rd))
+				remember(index++, yearp, monthp, dayp,
+				    year, rm, rd);
+			continue;
+		}
+
+		/* (Jun|Dec)Solstice */
+		if ((*flags & ~F_MODIFIEROFFSET) ==
+		    (F_SPECIALDAY | F_VARIABLE | F_JUNSOLSTICE)) {
+			offset = 0;
+			if ((*flags & F_MODIFIEROFFSET) != 0)
+				offset = parseoffset(modifieroffset);
+			if (remember_yd(year, solsticedays[0] + offset,
+			    &rm, &rd))
+				remember(index++, yearp, monthp, dayp,
+				    year, rm, rd);
+			continue;
+		}
+		if ((*flags & ~F_MODIFIEROFFSET) ==
+		    (F_SPECIALDAY | F_VARIABLE | F_DECSOLSTICE)) {
+			offset = 0;
+			if ((*flags & F_MODIFIEROFFSET) != 0)
+				offset = parseoffset(modifieroffset);
+			if (remember_yd(year, solsticedays[1] + offset,
+			    &rm, &rd))
+				remember(index++, yearp, monthp, dayp,
+				    year, rm, rd);
+			continue;
+		}
+
 		printf("Unprocessed:\n");
 		debug_determinestyle(2, date, *flags, month, imonth,
 		    dayofmonth, idayofmonth, dayofweek, idayofweek,
 		    modifieroffset, modifierindex, specialday);
-
 	}
 
 	return (index);
@@ -575,6 +641,14 @@ showflags(int flags)
 		strcat(s, "fullmoon ");
 	if ((flags & F_NEWMOON) != 0)
 		strcat(s, "newmoon ");
+	if ((flags & F_MAREQUINOX) != 0)
+		strcat(s, "marequinox ");
+	if ((flags & F_SEPEQUINOX) != 0)
+		strcat(s, "sepequinox ");
+	if ((flags & F_JUNSOLSTICE) != 0)
+		strcat(s, "junsolstice ");
+	if ((flags & F_DECSOLSTICE) != 0)
+		strcat(s, "decsolstice ");
 
 	return s;
 }

Modified: user/edwin/calendar/paskha.c
==============================================================================
--- user/edwin/calendar/paskha.c	Fri Jan 29 05:44:20 2010	(r203153)
+++ user/edwin/calendar/paskha.c	Fri Jan 29 06:39:57 2010	(r203154)
@@ -55,36 +55,3 @@ paskha(int R) /*year*/
 	cumday = cumdaytab[isleap(R)];
 	return (((cumday[3] + 1) + 22) + (d + e));
 }
-
-/* return year day for Orthodox Easter depending days */
-
-int
-getpaskha(char *s, int year)
-{
-	int offset;
-
-	if (strncasecmp(s, PASKHA, PASKHALEN) == 0)
-		s += PASKHALEN;
-	else if (npaskha.name != NULL
-	    && strncasecmp(s, npaskha.name, npaskha.len) == 0)
-		s += npaskha.len;
-	else
-		return 0;
-
-	/* Paskha+1  or Paskha-2
-	 *       ^            ^   */
-
-	switch (*s) {
-
-	case '-':
-	case '+':
-		offset = atoi(s);
-		break;
-
-	default:
-		offset = 0;
-		break;
-	}
-
-	return (paskha(year) + offset + 13 /* new style */);
-}

Added: user/edwin/calendar/sunpos.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/edwin/calendar/sunpos.c	Fri Jan 29 06:39:57 2010	(r203154)
@@ -0,0 +1,345 @@
+/*-
+ * Copyright (c) 2009-2010 Edwin Groothuis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ */
+
+/*
+ * This code is created to match the formulas available at:
+ * Formula and examples obtained from "How to Calculate alt/az: SAAO" at
+ * http://www.saao.ac.za/public-info/sun-moon-stars/sun-index/how-to-calculate-altaz/
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <math.h>
+#include <string.h>
+#include <time.h>
+#include "calendar.h"
+
+#define D2R(m)	((m) / 180 * M_PI)
+#define R2D(m)	((m) * 180 / M_PI)
+
+#define	SIN(x)	(sin(D2R(x)))
+#define	COS(x)	(cos(D2R(x)))
+#define	TAN(x)	(tan(D2R(x)))
+#define	ASIN(x)	(R2D(asin(x)))
+#define	ATAN(x)	(R2D(atan(x)))
+
+#ifdef NOTDEF
+static void
+comp(char *s, double v, double c)
+{
+
+	printf("%-*s %*g %*g %*g\n", 15, s, 15, v, 15, c, 15, v - c);
+}
+
+int expY;
+double expZJ = 30.5;
+double expUTHM = 8.5;
+double expD = 34743.854;
+double expT = 0.9512349;
+double expL = 324.885;
+double expM = 42.029;
+double expepsilon = 23.4396;
+double explambda = 326.186;
+double expalpha = 328.428;
+double expDEC = -12.789;
+double expeastlongitude = 17.10;
+double explatitude = -22.57;
+double expHA = -37.673;
+double expALT = 49.822;
+double expAZ = 67.49;
+#endif
+
+static double
+fixup(double *d)
+{
+
+	if (*d < 0) {
+		while (*d < 0)
+			*d += 360;
+	} else {
+		while (*d > 360)
+			*d -= 360;
+	}
+
+	return (*d);
+}
+
+static double ZJtable[] = {
+	0, -0.5, 30.5, 58.5, 89.5, 119.5, 150.5, 180.5, 211.5, 242.5, 272.5, 303.5, 333.5 };
+
+static void
+sunpos(int inYY, int inMM, int inDD, double UTCOFFSET, int inHOUR, int inMIN,
+    double eastlongitude, double latitude, double *DEC, double *ALT, double *AZ)
+{
+	int Y;
+	double ZJ, D, T, L, M, epsilon, lambda, alpha, HA, UTHM;
+
+	/* Not calculated in this code */
+	*ALT = 0;
+	*AZ = 0;
+
+	ZJ = ZJtable[inMM];
+	if (inMM <= 2 && isleap(inYY))
+		ZJ -= 1.0;
+
+	UTHM = inHOUR + inMIN / 60.0 + UTCOFFSET;
+	Y = inYY - 1900;						/*  1 */
+	D = floor(365.25 * Y) + ZJ + inDD + UTHM / 24;			/*  3 */
+	T = D / 36525.0;						/*  4 */
+	L = 279.697 + 36000.769 * T;					/*  5 */
+	fixup(&L);
+	M = 358.476 + 35999.050 * T;					/*  6 */
+	fixup(&M);
+	epsilon = 23.452 - 0.013 * T;					/*  7 */
+	fixup(&epsilon);
+
+	lambda = L + (1.919 - 0.005 * T) * SIN(M) + 0.020 * SIN(2 * M);	/*  8 */
+	fixup(&lambda);
+	alpha = ATAN(TAN(lambda) * COS(epsilon));			/*  9 */
+
+	/* Alpha should be in the same quadrant as lamba */
+	if (1) {
+		int lssign = sin(D2R(lambda)) < 0 ? -1 : 1;
+		int lcsign = cos(D2R(lambda)) < 0 ? -1 : 1;
+		while (((sin(D2R(alpha)) < 0) ? -1 : 1) != lssign
+		    || ((cos(D2R(alpha)) < 0) ? -1 : 1) != lcsign)
+			alpha += 90.0;
+	}
+	fixup(&alpha);
+
+	*DEC = ASIN(SIN(lambda) * SIN(epsilon));			/* 10 */
+	fixup(DEC);
+	fixup(&eastlongitude);
+	HA = L - alpha + 180 + 15 * UTHM + eastlongitude;		/* 12 */
+	fixup(&HA);
+	fixup(&latitude);
+#ifdef NOTDEF
+	printf("%02d/%02d %02d: l:%g d:%g h:%g\n",
+	    inMM, inDD, inHOUR, latitude, *DEC, HA);
+#endif
+	return;
+
+	/*
+	 * The following calculations are not used, so to save time
+	 * they are not calculated.
+	 */
+#ifdef NOTDEF
+	*ALT = ASIN(SIN(latitude) * SIN(*DEC) +
+	    COS(latitude) * COS(*DEC) * COS(HA));			/* 13 */
+	fixup(ALT);
+	*AZ = ATAN(SIN(HA) /
+	    (COS(HA) * SIN(latitude) - TAN(*DEC) * COS(latitude)));	/* 14 */
+
+	if (*ALT > 180)
+		*ALT -= 360;
+	if (*ALT < -180)
+		*ALT += 360;
+	printf("a:%g a:%g\n", *ALT, *AZ);
+#endif
+
+#ifdef NOTDEF
+	printf("Y:\t\t\t     %d\t\t     %d\t\t      %d\n", Y, expY, Y - expY);
+	comp("ZJ", ZJ, expZJ);
+	comp("UTHM", UTHM, expUTHM);
+	comp("D", D, expD);
+	comp("T", T, expT);
+	comp("L", L, fixup(&expL));
+	comp("M", M, fixup(&expM));
+	comp("epsilon", epsilon, fixup(&expepsilon));
+	comp("lambda", lambda, fixup(&explambda));
+	comp("alpha", alpha, fixup(&expalpha));
+	comp("DEC", DEC, fixup(&expDEC));
+	comp("eastlongitude", eastlongitude, fixup(&expeastlongitude));
+	comp("latitude", latitude, fixup(&explatitude));
+	comp("HA", HA, fixup(&expHA));
+	comp("ALT", ALT, fixup(&expALT));
+	comp("AZ", AZ, fixup(&expAZ));
+#endif
+}
+
+
+#define	SIGN(a)	(((a) > 180) ? -1 : 1)
+#define ANGLE(a, b) (((a) < (b)) ? 1 : -1)
+#define HOUR(h) ((h) / 4)
+#define MIN(h) (15 * ((h) % 4))
+#define	DEBUG1(y, m, d, hh, mm, pdec, dec) \
+	printf("%4d-%02d-%02d %02d:%02d:00 - %7.7g -> %7.7g\n", \
+	    y, m, d, hh, mm, pdec, dec)
+#define	DEBUG2(y, m, d, hh, mm, pdec, dec, pang, ang) \
+	printf("%4d-%02d-%02d %02d:%02d:00 - %7.7g -> %7.7g - %d -> %d\n", \
+	    y, m, d, hh, mm, pdec, dec, pang, ang)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list