Date: Fri, 29 Jan 2010 06:39:57 +0000 (UTC) From: Edwin Groothuis <edwin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r203154 - user/edwin/calendar Message-ID: <201001290639.o0T6dvj4080133@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001290639.o0T6dvj4080133>