From 5cccbf6783c73f0be5c0218014c2d000e33d9eec Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 22 Nov 2012 18:58:01 +0100 Subject: [PATCH] initial commit --- AUTHORS | 1 + ChangeLog | 0 INSTALL | 1 + Makefile.am | 3 + NEWS | 0 README | 1 + configure.ac | 29 +++++++ src/Makefile.am | 4 + src/astro.c | 48 ++++++++++++ src/calendar.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++ src/calendar.h | 176 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 466 insertions(+) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 120000 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 configure.ac create mode 100644 src/Makefile.am create mode 100644 src/astro.c create mode 100644 src/calendar.c create mode 100644 src/calendar.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..c451cdc --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Steffen Vogel diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/INSTALL b/INSTALL new file mode 120000 index 0000000..cbd1c80 --- /dev/null +++ b/INSTALL @@ -0,0 +1 @@ +/usr/share/automake-1.11/INSTALL \ No newline at end of file diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..4eb56c1 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +dist_doc_DATA = README diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..2805968 --- /dev/null +++ b/README @@ -0,0 +1 @@ +libastro is a collection of functions for time, date and ephemeris calculus diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..d99e2f7 --- /dev/null +++ b/configure.ac @@ -0,0 +1,29 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.69]) +AC_INIT(astro, 0.1, stv0g@0l.de) +AC_CONFIG_SRCDIR([include/sun.h]) +AC_CONFIG_HEADERS([config.h]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. + +# Checks for header files. + +# Checks for typedefs, structures, and compiler characteristics. + +# Checks for library functions. + +# Automake +AM_INIT_AUTOMAKE +AM_PROG_CC_C_O + +AC_CONFIG_FILES([ + Makefile + src/Makefile +]) + +AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..93ae07e --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,4 @@ +bin_PROGRAMS = astro + +astro_SOURCES = calendar.c astro.c +astro_LDADD = -lm diff --git a/src/astro.c b/src/astro.c new file mode 100644 index 0000000..93eadb0 --- /dev/null +++ b/src/astro.c @@ -0,0 +1,48 @@ +#include +#include + +#include "calendar.h" + +extern const char* weekdays[]; +extern const char* months[]; + +int main(int argc, char *argv[]) { + time_t u = time(NULL); + struct tm *n = localtime(&u); /* current time and date */ + + struct date d; + struct time t; + + if (argc == 2) { + sscanf(argv[1], "%d.%d.%d", &d.day, &d.month, &d.year); + } + else { + d.day = n->tm_mday; + d.month = n->tm_mon+1; + d.year = n->tm_year+1900; + } + + t.hour = n->tm_hour; + t.minute = n->tm_min; + t.second = n->tm_sec; + + + printf("Berechne für %d.%d.%d %d:%0d\n", d.day, d.month, d.year, t.hour, t.minute); + + struct date e = eastern(d.year); + enum weekday wday = weekday(d); + bool leap = leapyear(d.year); + double dec = hms2decimal(t); + int day = daynumber(d); + int week = weeknumber(d); // TODO fix + + printf("In year %d, eastern is on %s the %d. %s\n", e.year, weekdays[weekday(e)], e.day, months[e.month-1]); + printf("The year %d %s a leapyear\n", d.year, (leap) ? "is" : "is not"); + printf("Daynumber: %d\n", day); + printf("Today is a %s\n", weekdays[wday]); + printf("%.1f %% of the day are over :-%c\n", dec*1e2, (dec > 0.5) ? '(' : ')'); + printf("Weeknumber: %d\n", week); + + + return 0; +} diff --git a/src/calendar.c b/src/calendar.c new file mode 100644 index 0000000..f7f89f6 --- /dev/null +++ b/src/calendar.c @@ -0,0 +1,203 @@ +#include + +#include "calendar.h" + +/** Constants */ +const double DELTA_T = 66.7; /* seconds */ + +const char *weekdays[] = { "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday", "Sunday" }; + +const char *holidays[] = { }; + +const char *months[] = { "January", "February", "March", + "April", "May", "June", "July", "August", + "October", "November", "December" }; + +const char *signs[] = { "Aries", "Taurus", "Gemini", "Cancer", + "Leo", "Virgo", "Libra", "Scorpio", + "Ophiuchus", "Sagittarius", "Capricorn", + "Aquarius", "Pisces" }; + +double frac(double x) { + return x - floor(x); +} + +struct date eastern(int year) { + int k = year / 100; /* Säkularzahl */ + int m = 15 + (3*k + 3) / 4 - (8*k + 13) / 25; /* säkulare Mondschaltung */ + int s = 2 - (3*k + 3) / 4; /* säkulare Sonnenschaltung */ + int a = year % 19; /* den Mondparameter */ + int d = (19*a + m) % 30; /* Keim für den ersten Vollmond im Frühling */ + int r = (d + a/11) / 29; /* kalendarische Korrekturgröße */ + int og = 21 + d - r; /* Ostergrenze */ + int sz = 7 - (year + year/4 + s) % 7; /* erster Sonntag im März */ + int oe = 7 - (og - sz) % 7; /* Osterentfernung in Tagen */ + int os = os = og + oe; /* Datum des Ostersonntags als Märzdatum */ + + struct date eastern = { + .year = year, + .month = (os > 31) ? 4 : 3, + .day = (os > 31) ? os - 31 : os + }; + + return eastern; +} + +struct date holiday(struct date date, enum holiday type) { + switch (type) { + case EASTER_SUNDAY: + return eastern(date.year); + break; + + case NEWYEAR: { + struct date ny; + ny.year = date.year; + ny.month = 1; + ny.day = 1; + return ny; + } + + case SILVESTER: { + struct date sv; + sv.year = date.year; + sv.month = 12; + sv.day = 31; + return sv; + } + } +} + +int weekday(struct date date) { + const int century_code[] = { 6, 4, 2, 0 }; + const int month_code[] = { 6, 2, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; + + int l = (leapyear(date.year) && date.month <= 2) ? 1 : 0; + int x = date.year % 100; + int y = date.year / 100; + int a = century_code[(y - 16) % 4]; + int b = month_code[(date.month-1) % 12] - l; + int c = x + x/4; + int d = date.day; + + return (a + b + c + d) % 7; +} + +bool leapyear(int year) { + if ((year % 400) == 0) + return true; + else if ((year % 100) == 0) + return false; + else if ((year % 4) == 0) + return true; + else + return false; +} + +int daynumber(struct date date) { + int days = date.month; + + if (date.month <= 2) { + days--; + days *= leapyear(date.year) ? 62 : 63; + days /= 2; + } + else { + days++; + days *= 30.6; + days -= leapyear(date.year)? 62 : 63; + } + + return days + date.day; +} + +int weeknumber(struct date date) { + int dn = daynumber(date); + + struct date ny = { /* new year */ + .year = date.year, + .month = 1, .day = 1 + }; + int wdny = weekday(ny); + + // Sonderfälle Freitag und Samstag + if (wdny >= 5) { + wdny -= 7; + } + + // Sonderfälle "Jahresanfang mit KW-Nummer aus dem Vorjahr" + if (dn + wdny <= 1) { + struct date sv = { /* silvester last year */ + .year = date.year - 1, + .month = 12, .day = 31 + }; + return weeknumber(sv); + } + + int wn = (dn + wdny + 5) / 7; + + /* 53 Kalenderwochen hat grundsätzlich nur ein Jahr, + welches mit einem Donnerstag anfängt ! + In Schaltjahren ist es auch mit einem Mittwoch möglich, z.B. 1992 + Andernfalls ist diese KW schon die KW1 des Folgejahres. */ + if (wn == 53) { + bool ly = leapyear(date.year); + + if ( (wdny + 7 ) % 7 == 4 || ((wdny + 7) % 7 == 3 && ly)) { + return wn; + } + else { + return 1; // Korrektur des Wertes + } + } + else { + return wn; + } +} + +double hms2decimal(struct time t) { + return (((t.second / 60.0) + t.minute) / 60.0 + t.hour) / 24.0; +} + +struct time decimal2hms(double decimal) { + double hours = decimal * 24; + double minutes = frac(hours) * 60; + double seconds = frac(minutes) * 60; + + struct time time = { hours, minutes, seconds }; + return time; +} + +int gregorian2julian(struct date d) { + if (d.month <= 2) { + d.year--; + d.month += 12; + } + + struct date x = { .day = 15, .month = 10, .year = 1582 }; + if (datecmp(d, x) > 0) { + int a = d.year / 100; + int b = 2 - a + + } + + return b + c + d + d.day + 1720994.5 +} + +struct date julian2gregorian(int jd) { + +} + +struct time utc2et(struct time d) { + +} + +int datecmp(struct date a, struct date b) { + if (a.year == b.year) { + if (a.month == b.month) { + if (a.day == b.day) return 0; + else return a.day - b.day; + } + else return a.month - b.month; + } + else return a.year - b.year; +} diff --git a/src/calendar.h b/src/calendar.h new file mode 100644 index 0000000..dd24cc1 --- /dev/null +++ b/src/calendar.h @@ -0,0 +1,176 @@ +/** + * Time and Calender calculus + * + * based on Practical astronomy with your calculator or spreadsheet + * from Peter Duffett-Smith, Jonathan Zwart. – 4th ed. (Cambridge University Press, 2011) + * + * @copyright 2012 Steffen Vogel + * @license http://www.gnu.org/licenses/gpl.txt GNU Public License + * @author Steffen Vogel + * @author Arnold Barmettler + * @link http://www.steffenvogel.de + */ +/* + * This file is part of libastro + * + * libastro is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * libastro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libastro. If not, see . + */ + + +/* TODO +christliche Feiertage +Advent +Sommer/Frühlings/Herbstanfang +Längster/Kürzester Tag +Vollmond +*/ + +#ifndef _TIME_H_ +#define _TIME_H_ + +#include +#include + +/** Types */ +struct date { + int day; + int month; + int year; +}; + +struct time { + int second; + int minute; + int hour; +}; + +/* helper to convert libastro types to struct tm */ +struct tma { + struct time time; + struct date date; + int wday; /* day of the week */ + int yday; /* day in the year */ + int isdst; /* daylight saving time */ +}; + +union datetime { + struct tma libastro; + struct tm posix; +}; + +enum weekday { + MONDAY, TUESDAY, WEDNESDAY, + THURSDAY, FRIDAY, SATURDAY, SUNDAY +}; + +enum holiday { + EASTER_SUNDAY, + CHRISTMAS, + ADVENT_1, ADVENT_2, ADVENT_3, ADVENT_4, + SILVESTER, NEWYEAR +}; + +/** Prototypes */ + +/** Helper functions */ +double frac(double x); + +/** + * Compare to dates like strcmp() + */ +int datecmp(struct date a, struct date b); + +struct date dateadd(struct date a, struct date b); + + +struct date holiday(struct date d, enum holiday type); + +/** + * Calculate the date of eastern + * + * @see http://de.wikipedia.org/wiki/Gau%C3%9Fsche_Osterformel + */ +struct date eastern(int year); + +/** + * Checks if year is a leapyear + */ +bool leapyear(int year); + +/** + * Calculate the daynumber of a gregorian date + * e.g the number of days after 1.1. of the current year + */ +int daynumber(struct date d); + +/** + * Calculate the weeknumber of a gregorian date + * + * according to DIN1355 + */ +int weeknumber(struct date d); + +/** + * Return english weekday name + */ +int weekday(struct date d); + +/** + * Return sign + */ +const char * sign(struct date d, int mode); + +/** + * Convert a gregorian date to a julian date + */ +int gregorian2julian(struct date d); +struct date julian2gregorian(int jd); + +/** + * Convert HH:MM:SS to decimal day + */ +double hms2decimal(struct time t); +struct time decimal2hms(double decimal); + +/** + * Universial to Local Time + */ +//utc2local(struct date, int zone); + +/** + * Universal to Greenwich Sidereal Time + */ +//utc2gmst(); + +/** + * Greenwich Sidereal to Universal Time + */ +//gmst2utc(); + +/** + * Local Sidereal to Univeral Time + */ +//lmst2utc(); + +/** + * Universal to Terrestrial (dynamic) Time + */ +//utc2tdt(utc); + +/** + * Ephimeris Time + */ +//struct time utc2et(struct time d); + +#endif /* _TIME_H_ */