1 // vim:ts=4:sw=4:expandtab
6 #include <yajl/yajl_gen.h>
7 #include <yajl/yajl_version.h>
11 /* define fixed output-Strings */
12 char *season_long[5] = {
19 char *season_short[5] = {
33 char *day_short[5] = {
40 char *holidays[10] = {
52 /* A helper-struct, taking the discordian date */
61 /* Print the date *dt in format *format */
62 static int format_output(char *outwalk, char *format, struct disc_time *dt) {
63 char *orig_outwalk = outwalk;
67 for (i = format; *i != '\0'; i++) {
73 /* Weekday in long and abbreviation */
75 outwalk += sprintf(outwalk, "%s", day_long[dt->week_day]);
78 outwalk += sprintf(outwalk, "%s", day_short[dt->week_day]);
80 /* Season in long and abbreviation */
82 outwalk += sprintf(outwalk, "%s", season_long[dt->season]);
85 outwalk += sprintf(outwalk, "%s", season_short[dt->season]);
87 /* Day of the season (ordinal and cardinal) */
89 outwalk += sprintf(outwalk, "%d", dt->season_day + 1);
92 outwalk += sprintf(outwalk, "%d", dt->season_day + 1);
93 if (dt->season_day > 9 && dt->season_day < 13) {
94 outwalk += sprintf(outwalk, "th");
98 switch (dt->season_day % 10) {
100 outwalk += sprintf(outwalk, "st");
103 outwalk += sprintf(outwalk, "nd");
106 outwalk += sprintf(outwalk, "rd");
109 outwalk += sprintf(outwalk, "th");
115 outwalk += sprintf(outwalk, "%d", dt->year);
119 if (dt->season_day == 4) {
120 outwalk += sprintf(outwalk, "%s", holidays[dt->season]);
122 if (dt->season_day == 49) {
123 outwalk += sprintf(outwalk, "%s", holidays[dt->season + 5]);
126 /* Stop parsing the format string, except on Holidays */
128 if (dt->season_day != 4 && dt->season_day != 49) {
129 return (outwalk - orig_outwalk);
132 /* Newline- and Tabbing-characters */
134 outwalk += sprintf(outwalk, "\n");
137 outwalk += sprintf(outwalk, "\t");
139 /* The St. Tib's Day replacement */
141 tibs_end = strstr(i, "%}");
142 if (tibs_end == NULL) {
146 if (dt->st_tibs_day) {
147 /* We outpt "St. Tib's Day... */
148 outwalk += sprintf(outwalk, "St. Tib's Day");
150 /* ...or parse the substring between %{ and %} ... */
152 outwalk += format_output(outwalk, i + 2, dt);
155 /* ...and continue with the rest */
162 /* No escape-sequence, so we just skip */
163 outwalk += sprintf(outwalk, "%%%c", *(i + 1));
168 return (outwalk - orig_outwalk);
171 /* Get the current date and convert it to discordian */
172 struct disc_time *get_ddate(struct tm *current_tm) {
173 static struct disc_time dt;
175 if (current_tm == NULL)
178 /* We have to know, whether we have to insert St. Tib's Day, so whether it's a leap
179 * year in gregorian calendar */
180 int is_leap_year = !(current_tm->tm_year % 4) &&
181 (!(current_tm->tm_year % 400) || current_tm->tm_year % 100);
183 /* If St. Tib's Day has passed, it will be necessary to skip a day. */
184 int yday = current_tm->tm_yday;
186 if (is_leap_year && yday == 59) {
187 /* On St. Tibs Day we don't have to define a date */
191 if (is_leap_year && yday > 59)
194 dt.season_day = yday % 73;
195 dt.week_day = yday % 5;
197 dt.year = current_tm->tm_year + 3066;
198 dt.season = yday / 73;
202 void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t) {
203 char *outwalk = buffer;
204 static char *form = NULL;
205 struct tm current_tm;
206 struct disc_time *dt;
207 set_timezone(NULL); /* Use local time. */
208 localtime_r(&t, ¤t_tm);
209 if ((dt = get_ddate(¤t_tm)) == NULL)
212 if ((form = malloc(strlen(format) + 1)) == NULL)
214 strcpy(form, format);
215 outwalk += format_output(outwalk, form, dt);
216 OUTPUT_FULL_TEXT(buffer);