aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/calcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/calcs.c')
-rw-r--r--calendar/calcs.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/calendar/calcs.c b/calendar/calcs.c
new file mode 100644
index 0000000000..002ffbf28b
--- /dev/null
+++ b/calendar/calcs.c
@@ -0,0 +1,273 @@
+/*
+ * calc.c Calculations to work out what day it is etc for the Calendar
+ *
+ * Most of this stuff was taken from the gcal source by Thomas Esken.
+ * <esken@uni-muenster.de>
+ * gcal is a text-based calendar program
+ */
+
+#include <time.h>
+#include <glib.h>
+#include <ctype.h>
+#include "calcs.h"
+
+/* Number of days in a month */
+static const int dvec[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+/* Number of past days of a month */
+static const int mvec[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+Greg_struct greg_reform_date[6] = {
+/* {int year, int month, int f_day, int l_day} */
+ { 1582, 10, 5, 14 },
+ { 1700, 2, 19, 28 },
+ { 1752, 9, 3, 13 },
+ { 1753, 2, 18, 28 },
+/* must be left with all zeroes */
+ { 0,0,0,0 }
+};
+Greg_struct *greg=greg_reform_date;
+
+
+
+/*
+ * Computes the number of days in February and returns them,
+ */
+int days_of_february(const int year)
+{
+ return((year&3) ? 28 : (!(year%100)&&(year%400)) ? 28 : 29);
+}
+
+int is_leap_year(const int year)
+{
+ return (days_of_february(year) == 29);
+}
+
+/*
+ * Check wether a given date is calid.
+ */
+int valid_date(const int day, const int month, const int year)
+{
+ if ( day < 1
+ || month < MONTH_MIN
+ || month > MONTH_MAX
+ || ( (month != 2)
+ && (day > dvec[month-1]))
+ || ( (month == 2)
+ && (day > days_of_february (year))))
+ return(FALSE);
+
+ return(TRUE);
+}
+
+/*
+ * Set a date back one day (to yesterday's date)
+ */
+void prev_date(int *day, int *month, int *year)
+{
+ (*day)--;
+ if ( !*day || !valid_date(*day, *month, *year)) {
+ (*month)--;
+ if (*month < MONTH_MIN) {
+ *month = MONTH_MAX;
+ (*year)--;
+ }
+ if (*month ==2)
+ *day = days_of_february(*year);
+ else
+ *day = dvec[*month-1];
+ }
+} /* prev_date */
+
+/*
+ * Set a date forward one day (to tomorrow's date)
+ */
+void next_date(int *day, int *month, int *year)
+{
+ (*day)++;
+ if (!valid_date(*day, *month, *year)) {
+ *day = DAY_MIN;
+ if (*month == MONTH_MAX) {
+ *month = MONTH_MIN;
+ (*year)++;
+ } else
+ (*month)++;
+ }
+} /* next_date */
+
+/*
+ * Get date from the system
+ */
+void get_system_date(int *day, int *month, int *year)
+{
+ auto struct tm *sys_date;
+ auto time_t sys_time;
+
+
+ sys_time = time((time_t *)NULL);
+ sys_date = localtime(&sys_time);
+ *day = sys_date->tm_mday;
+ *month = sys_date->tm_mon + 1;
+ *year = sys_date->tm_year;
+ if (*year < CENTURY)
+ *year += CENTURY;
+} /* get_system_date */
+
+
+/*
+ * Given a string with the name of a month, return 1..12 or 0 if not found
+ */
+int month_atoi(const char *string)
+{
+ int i, j;
+ int len;
+ char *ptr;
+
+ len = strlen(string);
+
+ for(i= MONTH_MIN; i <= MONTH_MAX; i++) {
+ ptr = (char*)month_name(i);
+ j = 0;
+ while ( *(ptr + j) && string[j])
+ if (tolower((ptr+j)) == tolower(string[j]))
+ j++;
+ else
+ break;
+ if (j == len || !*(ptr + j))
+ return(i);
+ }
+ return 0;
+} /* month_atoi */
+
+int day_atoi(const char *string)
+{
+ int i, j;
+ int len;
+ char *ptr;
+
+ len = strlen(string);
+
+ for(i= DAY_MIN; i <= DAY_MAX; i++) {
+ ptr = (char*)day_name(i);
+ j = 0;
+ while ( *(ptr + j) && string[j])
+ if (tolower((ptr+j)) == tolower(string[j]))
+ j++;
+ else
+ break;
+ if (j == len || !*(ptr + j))
+ return(i);
+ }
+ return 0;
+} /* day_atoi */
+
+/*
+ * Returns ordinal suffix (st, nd, rd, th) for a day
+ */
+const char *day_suffix(int day)
+{
+ static const char *suffix[]={"th", "st", "nd", "rd"};
+ register int i;
+
+ i = 0;
+
+ if (day > 100)
+ day %= 100;
+ if (day < 11 || day > 13)
+ i = day % 10;
+ if (i > 3)
+ i = 0;
+
+ return(suffix[i]);
+} /* day_suffix */
+
+/*
+ * Returns the short name of the day of week, format "%-3s"
+ */
+const char *short3_day_name(const int day)
+{
+ static const char *name[]={"invalid day", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+
+ return(((day<DAY_MIN)||(day>DAY_MAX)) ? name[0] : name[day]);
+} /* short3_day_name */
+
+/*
+ * Returns the short name of day of week
+ */
+const char *short_day_name(const int day)
+{
+ static const char *name[]={"invalid day", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"};
+
+ return(((day<DAY_MIN)||(day>DAY_MAX)) ? name[0] : name[day]);
+} /* short_day_name */
+
+/*
+ * Returns the complete name of the day
+ */
+const char *day_name(const int day)
+{
+ static const char *name[]={"invalid day", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
+
+ return(((day<DAY_MIN)||(day>DAY_MAX)) ? name[0] : name[day]);
+} /* day_name */
+
+/*
+ * Returns the short name of the month
+ */
+const char *short_month_name(const int month)
+{
+ static const char *name[]={ "invalid month", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+ return(((month<MONTH_MIN)||(month>MONTH_MAX)) ? name[0] : name[month]);
+} /* short_month_name() */
+
+/*
+ * Returns the name of the month
+ */
+const char *month_name(const int month)
+{
+ static const char *name[]={ "invalid month", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
+
+ return(((month<MONTH_MIN)||(month>MONTH_MAX)) ? name[0] : name[month]);
+} /* month_name() */
+
+/*
+ * Compute the absolute number of days of the given date since 1 Jan 0001
+ * respecting the missing period of the Gregorian Reformation
+ * I am glad someone else worked this one out!! - cs
+ */
+unsigned long int date2num(const int day, const int month, const int year)
+{
+ auto unsigned long int julian_days;
+
+ julian_days = (unsigned long int)((year-1)*(unsigned long int)(DAY_LAST)+((year-1)>>2));
+
+ if (year > greg->year
+ || ( (year == greg->year)
+ && ( month > greg->month
+ || ( (month == greg->month)
+ && (day > greg->last_day)))))
+ julian_days -= (unsigned long int)(greg->last_day - greg->first_day + 1);
+ if (year > greg->year) {
+ julian_days += (((year-1) / 400) - (greg->year / 400));
+ julian_days -= (((year-1) / 100) - (greg->year / 100));
+ if (!(greg->year % 100) && (greg->year % 400))
+ julian_days--;
+ }
+ julian_days += (unsigned long int)mvec[month-1];
+ julian_days += day;
+ if ( (days_of_february(year) == 29) && (month > 2))
+ julian_days++;
+
+ return(julian_days);
+} /* date2num */
+
+/*
+ * Computes the weekday of a Gregorian/Julian calendar date
+ * (month must be 1..12) returns 1..7 (mo..su)
+ */
+int weekday_of_date(const int day, const int month, const int year)
+{
+ auto unsigned long int julian_days=date2num(day, month,year)%DAY_MAX;
+
+ return((julian_days>2) ? (int)julian_days-2 : (int)julian_days+5);
+} /* weekday_of_date() */
+