]> git.sur5r.net Git - i3/i3status/blob - src/print_ddate.c
print_ddate(): Correctly seperate the St. Tibs String from the rest
[i3/i3status] / src / print_ddate.c
1 // vim:ts=8:expandtab
2 #include <time.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 /* define fixed output-Strings */
8 char *season_long[5] = {
9         "Chaos",
10         "Discord",
11         "Confusion",
12         "Bureaucracy",
13         "The Aftermath"
14 };
15
16 char *season_short[5] = {
17         "Chs",
18         "Dsc",
19         "Cfn",
20         "Bcy",
21         "Afm"
22 };
23
24 char *day_long[5] = {
25         "Sweetmorn",
26         "Boomtime",
27         "Pungenday",
28         "Prickle-Prickle",
29         "Setting Orange"
30 };
31
32 char *day_short[5] = {
33         "SM",
34         "BT",
35         "PD",
36         "PP",
37         "SO"
38 };
39
40 char *holidays[10] = {
41         "Mungday",
42         "Mojoday",
43         "Syaday",
44         "Zaraday",
45         "Maladay",
46         "Chaoflux",
47         "Discoflux",
48         "Confuflux",
49         "Bureflux",
50         "Afflux"
51 };
52
53 /* A helper-struct, taking the discordian date */
54 struct disc_time {
55         int year;
56         int season;
57         int week_day;
58         int season_day;
59         int st_tibs_day;
60 };
61
62 /* Print the date *dt in format *format */
63 int format_output(char *format, struct disc_time *dt) {
64         char *i;
65         char *tibs_end = 0;
66
67         for (i = format; *i != '\0'; i++) {
68                 if (*i != '%') {
69                         putchar(*i);
70                         continue;
71                 }
72                 switch (*(i+1)) {
73                         /* Weekday in long and abbreviation */
74                         case 'A':
75                                 printf("%s", day_long[dt->week_day]);
76                                 break;
77                         case 'a':
78                                 printf("%s", day_short[dt->week_day]);
79                                 break;
80                         /* Season in long and abbreviation */
81                         case 'B':
82                                 printf("%s", season_long[dt->season]);
83                                 break;
84                         case 'b':
85                                 printf("%s", season_short[dt->season]);
86                                 break;
87                         /* Day of the season (ordinal and cardinal) */
88                         case 'd':
89                                 printf("%d", dt->season_day + 1);
90                                 break;
91                         case 'e':
92                                 printf("%d", dt->season_day + 1);
93                                 switch (dt->season_day) {
94                                         case 0:
95                                                 printf("st");
96                                                 break;
97                                         case 1:
98                                                 printf("nd");
99                                                 break;
100                                         case 2:
101                                                 printf("rd");
102                                                 break;
103                                         default:
104                                                 printf("th");
105                                                 break;
106                                 }
107                                 break;
108                         /* YOLD */
109                         case 'Y':
110                                 printf("%d", dt->year);
111                                 break;
112                         /* Holidays */
113                         case 'H':
114                                 if (dt->season_day == 4) {
115                                         printf(holidays[dt->season]);
116                                 }
117                                 if (dt->season_day == 49) {
118                                         printf(holidays[dt->season + 5]);
119                                 }
120                                 break;
121                         /* Stop parsing the format string, except on Holidays */
122                         case 'N':
123                                 if (dt->season_day != 4 && dt->season_day != 49) {
124                                         return 0;
125                                 }
126                                 break;
127                         /* Newline- and Tabbing-characters */
128                         case 'n':
129                                 printf("\n");
130                                 break;
131                         case 't':
132                                 printf("\t");
133                                 break;
134                         /* The St. Tib's Day replacement */
135                         case '{':
136                                 tibs_end = strstr(i, "%}");
137                                 if (tibs_end == NULL) {
138                                         i++;
139                                         break;
140                                 }
141                                 if (dt->st_tibs_day) {
142                                         /* We outpt "St. Tib's Day... */
143                                         printf("St. Tib's Day");
144                                 } else {
145                                         /* ...or parse the substring between %{ and %} ... */
146                                         *tibs_end = '\0';
147                                         if (!format_output(i + 2, dt)) return 0;
148                                         *tibs_end = '%';
149                                 }
150                                 /* ...and continue with the rest */
151                                 i = tibs_end;
152                                 break;
153                         case '}':
154                                 i++;
155                                 break;
156                         default:
157                                 /* No escape-sequence, so we just skip */
158                                 printf("%%%c",*(i+1));
159                                 break;
160                 }
161                 i++;
162         }
163         return 1;
164 }
165
166 /* Get the current date and convert it to discordian */
167 struct disc_time *get_ddate() {
168         time_t current_time;
169         struct tm *current_tm;
170         static struct disc_time dt;
171
172         if ((current_time = time(NULL)) == (time_t)-1)
173                 return NULL;
174
175         if ((current_tm = localtime(&current_time)) == NULL)
176                 return NULL;
177
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);
182
183         if (is_leap_year && current_tm->tm_yday == 59) {
184                 /* On St. Tibs Day we don't have to define a date */
185                 dt.st_tibs_day = 1;
186         } else {
187                 dt.st_tibs_day = 0;
188                 dt.season_day = current_tm->tm_yday % 73;
189                 if (is_leap_year && current_tm->tm_yday > 59) {
190                         dt.week_day = (current_tm->tm_yday - 1) % 5;
191                 } else {
192                         dt.week_day = current_tm->tm_yday % 5;
193                 }
194         }
195         dt.year = current_tm->tm_year + 3066;
196         dt.season = current_tm->tm_yday / 73;
197         return &dt;
198 }
199
200 void print_ddate(const char *format) {
201         static char *form = NULL;
202         struct disc_time *dt;
203         if ((dt = get_ddate()) == NULL)
204                 return;
205         if (form == NULL)
206                 if ((form = malloc(strlen(format) + 1)) == NULL)
207                         return;
208         strcpy(form, format);
209         format_output(form, dt);
210 }