2010-06-17 23:53:27 +00:00
|
|
|
// vim:ts=8:expandtab
|
|
|
|
#include <time.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/* define fixed output-Strings */
|
|
|
|
char *season_long[5] = {
|
|
|
|
"Chaos",
|
|
|
|
"Discord",
|
|
|
|
"Confusion",
|
|
|
|
"Bureaucracy",
|
|
|
|
"The Aftermath"
|
|
|
|
};
|
|
|
|
|
|
|
|
char *season_short[5] = {
|
|
|
|
"Chs",
|
|
|
|
"Dsc",
|
|
|
|
"Cfn",
|
|
|
|
"Bcy",
|
|
|
|
"Afm"
|
|
|
|
};
|
|
|
|
|
|
|
|
char *day_long[5] = {
|
|
|
|
"Sweetmorn",
|
|
|
|
"Boomtime",
|
|
|
|
"Pungenday",
|
|
|
|
"Prickle-Prickle",
|
|
|
|
"Setting Orange"
|
|
|
|
};
|
|
|
|
|
|
|
|
char *day_short[5] = {
|
|
|
|
"SM",
|
|
|
|
"BT",
|
|
|
|
"PD",
|
|
|
|
"PP",
|
|
|
|
"SO"
|
|
|
|
};
|
|
|
|
|
|
|
|
char *holidays[10] = {
|
|
|
|
"Mungday",
|
|
|
|
"Mojoday",
|
|
|
|
"Syaday",
|
|
|
|
"Zaraday",
|
|
|
|
"Maladay",
|
|
|
|
"Chaoflux",
|
|
|
|
"Discoflux",
|
|
|
|
"Confuflux",
|
|
|
|
"Bureflux",
|
|
|
|
"Afflux"
|
|
|
|
};
|
|
|
|
|
|
|
|
/* A helper-struct, taking the discordian date */
|
|
|
|
struct disc_time {
|
|
|
|
int year;
|
|
|
|
int season;
|
|
|
|
int week_day;
|
|
|
|
int season_day;
|
|
|
|
int st_tibs_day;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Print the date *dt in format *format */
|
|
|
|
int format_output(char *format, struct disc_time *dt) {
|
|
|
|
char *i;
|
|
|
|
char *tibs_end = 0;
|
|
|
|
|
|
|
|
for (i = format; *i != '\0'; i++) {
|
|
|
|
if (*i != '%') {
|
|
|
|
putchar(*i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
switch (*(i+1)) {
|
|
|
|
/* Weekday in long and abbreviation */
|
|
|
|
case 'A':
|
|
|
|
printf("%s", day_long[dt->week_day]);
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
printf("%s", day_short[dt->week_day]);
|
|
|
|
break;
|
|
|
|
/* Season in long and abbreviation */
|
|
|
|
case 'B':
|
|
|
|
printf("%s", season_long[dt->season]);
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
printf("%s", season_short[dt->season]);
|
|
|
|
break;
|
|
|
|
/* Day of the season (ordinal and cardinal) */
|
|
|
|
case 'd':
|
|
|
|
printf("%d", dt->season_day + 1);
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
printf("%d", dt->season_day + 1);
|
|
|
|
switch (dt->season_day) {
|
|
|
|
case 0:
|
|
|
|
printf("st");
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
printf("nd");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
printf("rd");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("th");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/* YOLD */
|
|
|
|
case 'Y':
|
|
|
|
printf("%d", dt->year);
|
|
|
|
break;
|
|
|
|
/* Holidays */
|
|
|
|
case 'H':
|
|
|
|
if (dt->season_day == 4) {
|
|
|
|
printf(holidays[dt->season]);
|
|
|
|
}
|
|
|
|
if (dt->season_day == 49) {
|
|
|
|
printf(holidays[dt->season + 5]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/* Stop parsing the format string, except on Holidays */
|
|
|
|
case 'N':
|
|
|
|
if (dt->season_day != 4 && dt->season_day != 49) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/* Newline- and Tabbing-characters */
|
|
|
|
case 'n':
|
|
|
|
printf("\n");
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
printf("\t");
|
|
|
|
break;
|
|
|
|
/* The St. Tib's Day replacement */
|
|
|
|
case '{':
|
|
|
|
tibs_end = strstr(i, "%}");
|
|
|
|
if (tibs_end == NULL) {
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (dt->st_tibs_day) {
|
|
|
|
/* We outpt "St. Tib's Day... */
|
|
|
|
printf("St. Tib's Day");
|
|
|
|
} else {
|
|
|
|
/* ...or parse the substring between %{ and %} ... */
|
2010-07-15 12:13:25 +00:00
|
|
|
*tibs_end = '\0';
|
2010-06-17 23:53:27 +00:00
|
|
|
if (!format_output(i + 2, dt)) return 0;
|
2010-07-15 12:13:25 +00:00
|
|
|
*tibs_end = '%';
|
2010-06-17 23:53:27 +00:00
|
|
|
}
|
|
|
|
/* ...and continue with the rest */
|
2010-07-15 12:13:25 +00:00
|
|
|
i = tibs_end;
|
2010-06-17 23:53:27 +00:00
|
|
|
break;
|
|
|
|
case '}':
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* No escape-sequence, so we just skip */
|
|
|
|
printf("%%%c",*(i+1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the current date and convert it to discordian */
|
|
|
|
struct disc_time *get_ddate() {
|
2010-06-19 10:50:03 +00:00
|
|
|
time_t current_time;
|
|
|
|
struct tm *current_tm;
|
|
|
|
static struct disc_time dt;
|
2010-06-17 23:53:27 +00:00
|
|
|
|
2010-06-19 10:50:03 +00:00
|
|
|
if ((current_time = time(NULL)) == (time_t)-1)
|
2010-06-17 23:53:27 +00:00
|
|
|
return NULL;
|
|
|
|
|
2010-06-19 10:50:03 +00:00
|
|
|
if ((current_tm = localtime(¤t_time)) == NULL)
|
2010-06-17 23:53:27 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* We have to know, whether we have to insert St. Tib's Day, so whether it's a leap
|
|
|
|
year in gregorian calendar */
|
|
|
|
int is_leap_year = !(current_tm->tm_year % 4) &&
|
|
|
|
(!(current_tm->tm_year % 400) || current_tm->tm_year % 100);
|
|
|
|
|
|
|
|
if (is_leap_year && current_tm->tm_yday == 59) {
|
|
|
|
/* On St. Tibs Day we don't have to define a date */
|
2010-06-19 10:50:03 +00:00
|
|
|
dt.st_tibs_day = 1;
|
2010-06-17 23:53:27 +00:00
|
|
|
} else {
|
2010-06-19 10:50:03 +00:00
|
|
|
dt.st_tibs_day = 0;
|
|
|
|
dt.season_day = current_tm->tm_yday % 73;
|
2010-06-17 23:53:27 +00:00
|
|
|
if (is_leap_year && current_tm->tm_yday > 59) {
|
2010-06-19 10:50:03 +00:00
|
|
|
dt.week_day = (current_tm->tm_yday - 1) % 5;
|
2010-06-17 23:53:27 +00:00
|
|
|
} else {
|
2010-06-19 10:50:03 +00:00
|
|
|
dt.week_day = current_tm->tm_yday % 5;
|
2010-06-17 23:53:27 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-19 10:50:03 +00:00
|
|
|
dt.year = current_tm->tm_year + 3066;
|
|
|
|
dt.season = current_tm->tm_yday / 73;
|
|
|
|
return &dt;
|
2010-06-17 23:53:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_ddate(const char *format) {
|
2010-06-19 10:50:03 +00:00
|
|
|
static char *form = NULL;
|
|
|
|
struct disc_time *dt;
|
|
|
|
if ((dt = get_ddate()) == NULL)
|
2010-06-17 23:53:27 +00:00
|
|
|
return;
|
2010-06-19 10:50:03 +00:00
|
|
|
if (form == NULL)
|
|
|
|
if ((form = malloc(strlen(format) + 1)) == NULL)
|
|
|
|
return;
|
|
|
|
strcpy(form, format);
|
2010-06-17 23:53:27 +00:00
|
|
|
format_output(form, dt);
|
|
|
|
}
|