1 /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 #include <config.h> 3 4 #include <glib.h> 5 #include <glib/gi18n.h> 6 7 #include <string.h> 8 9 #include "e_date.h" 10 11 /* 12 all this code comes from evolution 13 - e-util.c 14 - message-list.c 15 */ 16 17 18 static size_t e_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) 19 { 20 #ifdef HAVE_LKSTRFTIME 21 return strftime(s, max, fmt, tm); 22 #else 23 char *c, *ffmt, *ff; 24 size_t ret; 25 26 ffmt = g_strdup(fmt); 27 ff = ffmt; 28 while ((c = strstr(ff, "%l")) != NULL) { 29 c[1] = 'I'; 30 ff = c; 31 } 32 33 ff = ffmt; 34 while ((c = strstr(ff, "%k")) != NULL) { 35 c[1] = 'H'; 36 ff = c; 37 } 38 39 ret = strftime(s, max, ffmt, tm); 40 g_free(ffmt); 41 return ret; 42 #endif 43 } 44 45 46 /** 47 * Function to do a last minute fixup of the AM/PM stuff if the locale 48 * and gettext haven't done it right. Most English speaking countries 49 * except the USA use the 24 hour clock (UK, Australia etc). However 50 * since they are English nobody bothers to write a language 51 * translation (gettext) file. So the locale turns off the AM/PM, but 52 * gettext does not turn on the 24 hour clock. Leaving a mess. 53 * 54 * This routine checks if AM/PM are defined in the locale, if not it 55 * forces the use of the 24 hour clock. 56 * 57 * The function itself is a front end on strftime and takes exactly 58 * the same arguments. 59 * 60 * TODO: Actually remove the '%p' from the fixed up string so that 61 * there isn't a stray space. 62 **/ 63 64 static size_t e_strftime_fix_am_pm(char *s, size_t max, const char *fmt, const struct tm *tm) 65 { 66 char buf[10]; 67 char *sp; 68 char *ffmt; 69 size_t ret; 70 71 if (strstr(fmt, "%p")==NULL && strstr(fmt, "%P")==NULL) { 72 /* No AM/PM involved - can use the fmt string directly */ 73 ret=e_strftime(s, max, fmt, tm); 74 } else { 75 /* Get the AM/PM symbol from the locale */ 76 e_strftime (buf, 10, "%p", tm); 77 78 if (buf[0]) { 79 /** 80 * AM/PM have been defined in the locale 81 * so we can use the fmt string directly 82 **/ 83 ret=e_strftime(s, max, fmt, tm); 84 } else { 85 /** 86 * No AM/PM defined by locale 87 * must change to 24 hour clock 88 **/ 89 ffmt=g_strdup(fmt); 90 for (sp=ffmt; (sp=strstr(sp, "%l")); sp++) { 91 /** 92 * Maybe this should be 'k', but I have never 93 * seen a 24 clock actually use that format 94 **/ 95 sp[1]='H'; 96 } 97 for (sp=ffmt; (sp=strstr(sp, "%I")); sp++) { 98 sp[1]='H'; 99 } 100 ret=e_strftime(s, max, ffmt, tm); 101 g_free(ffmt); 102 } 103 } 104 return(ret); 105 } 106 107 static size_t 108 e_utf8_strftime_fix_am_pm(char *s, size_t max, const char *fmt, const struct tm *tm) 109 { 110 size_t sz, ret; 111 char *locale_fmt, *buf; 112 113 locale_fmt = g_locale_from_utf8(fmt, -1, NULL, &sz, NULL); 114 if (!locale_fmt) 115 return 0; 116 117 ret = e_strftime_fix_am_pm(s, max, locale_fmt, tm); 118 if (!ret) { 119 g_free (locale_fmt); 120 return 0; 121 } 122 123 buf = g_locale_to_utf8(s, ret, NULL, &sz, NULL); 124 if (!buf) { 125 g_free (locale_fmt); 126 return 0; 127 } 128 129 if (sz >= max) { 130 char *tmp = buf + max - 1; 131 tmp = g_utf8_find_prev_char(buf, tmp); 132 if (tmp) 133 sz = tmp - buf; 134 else 135 sz = 0; 136 } 137 memcpy(s, buf, sz); 138 s[sz] = '\0'; 139 g_free(locale_fmt); 140 g_free(buf); 141 return sz; 142 } 143 144 145 static char * 146 filter_date (time_t date) 147 { 148 time_t nowdate = time(NULL); 149 time_t yesdate; 150 struct tm then, now, yesterday; 151 char buf[26]; 152 gboolean done = FALSE; 153 154 if (date == 0) 155 // xgettext: ? stands for unknown 156 return g_strdup (_("?")); 157 158 localtime_r (&date, &then); 159 localtime_r (&nowdate, &now); 160 if (then.tm_mday == now.tm_mday && 161 then.tm_mon == now.tm_mon && 162 then.tm_year == now.tm_year) { 163 e_utf8_strftime_fix_am_pm (buf, 26, _("Today %l∶%M %p"), &then); 164 done = TRUE; 165 } 166 if (!done) { 167 yesdate = nowdate - 60 * 60 * 24; 168 localtime_r (&yesdate, &yesterday); 169 if (then.tm_mday == yesterday.tm_mday && 170 then.tm_mon == yesterday.tm_mon && 171 then.tm_year == yesterday.tm_year) { 172 e_utf8_strftime_fix_am_pm (buf, 26, _("Yesterday %l∶%M %p"), &then); 173 done = TRUE; 174 } 175 } 176 if (!done) { 177 int i; 178 for (i = 2; i < 7; i++) { 179 yesdate = nowdate - 60 * 60 * 24 * i; 180 localtime_r (&yesdate, &yesterday); 181 if (then.tm_mday == yesterday.tm_mday && 182 then.tm_mon == yesterday.tm_mon && 183 then.tm_year == yesterday.tm_year) { 184 e_utf8_strftime_fix_am_pm (buf, 26, _("%a %l∶%M %p"), &then); 185 done = TRUE; 186 break; 187 } 188 } 189 } 190 if (!done) { 191 if (then.tm_year == now.tm_year) { 192 e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %l∶%M %p"), &then); 193 } else { 194 e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %Y"), &then); 195 } 196 } 197 #if 0 198 #ifdef CTIME_R_THREE_ARGS 199 ctime_r (&date, buf, 26); 200 #else 201 ctime_r (&date, buf); 202 #endif 203 #endif 204 205 return g_strdup (buf); 206 } 207 208 209 210 211 char * 212 procman_format_date_for_display(time_t d) 213 { 214 return filter_date(d); 215 } 216