Mercurial > hg > xemacs-beta
annotate src/strftime.c @ 5462:97ac18bd1fa3
Make sure distinct symbol macros with identical names expand distinctly.
lisp/ChangeLog addition:
2011-04-24 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (symbol-macrolet):
* cl-macs.el (lexical-let):
* cl.el:
* cl.el (cl-macroexpand):
Distinct symbol macros with identical string names should
nonetheless expand to different things; implement this, storing
the symbol's eq-hash in the macro environment, rather than its
string name.
tests/ChangeLog addition:
2011-04-24 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Check that distinct symbol macros with identical string names
expand to different things.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sun, 24 Apr 2011 09:52:45 +0100 |
parents | 1537701f08a1 |
children | 308d34e9f07d |
rev | line source |
---|---|
428 | 1 /* strftime - custom formatting of date and/or time |
2 Copyright (C) 1989, 1991, 1992 Free Software Foundation, Inc. | |
3 | |
4 This program is free software; you can redistribute it and/or modify | |
5 it under the terms of the GNU General Public License as published by | |
6 the Free Software Foundation; either version 2, or (at your option) | |
7 any later version. | |
8 | |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
15 along with this program; see the file COPYING. If not, write to | |
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 Boston, MA 02111-1307, USA. */ | |
18 | |
19 /* Synched up with: FSF 19.30. */ | |
20 | |
771 | 21 /* This file has been ... uhhhhh ... Mule-ized. Yeah. |
22 | |
23 (Everything here is external format. This is DANGEROUS and | |
24 data-lossy, but fixing it is too much of a bother now.) --ben */ | |
25 | |
428 | 26 /* Note: this version of strftime lacks locale support, |
27 but it is standalone. | |
28 | |
29 Performs `%' substitutions similar to those in printf. Except | |
30 where noted, substituted fields have a fixed size; numeric fields are | |
31 padded if necessary. Padding is with zeros by default; for fields | |
32 that display a single number, padding can be changed or inhibited by | |
33 following the `%' with one of the modifiers described below. Unknown | |
34 field specifiers are copied as normal characters. All other | |
35 characters are copied to the output without change. | |
36 | |
37 Supports a superset of the ANSI C field specifiers. | |
38 | |
39 Literal character fields: | |
40 % % | |
41 n newline | |
42 t tab | |
43 | |
44 Numeric modifiers (a nonstandard extension): | |
45 - do not pad the field | |
46 _ pad the field with spaces | |
47 | |
48 Time fields: | |
49 %H hour (00..23) | |
50 %I hour (01..12) | |
51 %k hour ( 0..23) | |
52 %l hour ( 1..12) | |
53 %M minute (00..59) | |
54 %p locale's AM or PM | |
55 %r time, 12-hour (hh:mm:ss [AP]M) | |
56 %R time, 24-hour (hh:mm) | |
57 %s time in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension) | |
58 %S second (00..61) | |
59 %T time, 24-hour (hh:mm:ss) | |
60 %X locale's time representation (%H:%M:%S) | |
4203 | 61 %z time zone offset (e.g. +0530, -0800 etc) |
428 | 62 %Z time zone (EDT), or nothing if no time zone is determinable |
63 | |
64 Date fields: | |
65 %a locale's abbreviated weekday name (Sun..Sat) | |
66 %A locale's full weekday name, variable length (Sunday..Saturday) | |
67 %b locale's abbreviated month name (Jan..Dec) | |
68 %B locale's full month name, variable length (January..December) | |
69 %c locale's date and time (Sat Nov 04 12:02:33 EST 1989) | |
70 %C century (00..99) | |
71 %d day of month (01..31) | |
72 %e day of month ( 1..31) | |
73 %D date (mm/dd/yy) | |
4203 | 74 %G year corresponding to the ISO 8601 week |
75 %g Year of the ISO 8601 week within century (00 - 99) | |
428 | 76 %h same as %b |
77 %j day of year (001..366) | |
78 %m month (01..12) | |
79 %U week number of year with Sunday as first day of week (00..53) | |
4203 | 80 %V ISO 8601 week number (first week is the earliest one with Thu) |
428 | 81 %w day of week (0..6) |
82 %W week number of year with Monday as first day of week (00..53) | |
83 %x locale's date representation (mm/dd/yy) | |
84 %y last two digits of year (00..99) | |
85 %Y year (1970...) | |
86 | |
87 David MacKenzie <djm@gnu.ai.mit.edu> */ | |
88 | |
89 #ifdef HAVE_CONFIG_H | |
90 #include <config.h> | |
91 #include "lisp.h" | |
92 #endif | |
93 | |
94 #include <stdio.h> | |
95 #include <sys/types.h> | |
96 #if defined(TM_IN_SYS_TIME) || (!defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME)) | |
97 #include <sys/time.h> | |
98 #else | |
99 #include <time.h> | |
100 #endif | |
101 | |
102 #ifndef STDC_HEADERS | |
103 time_t mktime (); | |
104 #endif | |
105 | |
442 | 106 #if defined(WIN32_NATIVE) || defined(CYGWIN) |
428 | 107 #include <time.h> |
108 #else | |
109 #if defined(HAVE_TZNAME) | |
110 extern char *tzname[2]; | |
111 #endif | |
442 | 112 #endif /* WIN32_NATIVE */ |
428 | 113 |
114 #ifdef emacs | |
115 #define strftime emacs_strftime | |
116 #endif | |
117 | |
118 /* Types of padding for numbers in date and time. */ | |
119 enum padding | |
120 { | |
121 none, blank, zero | |
122 }; | |
123 | |
442 | 124 static char const* const days[] = |
428 | 125 { |
126 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" | |
127 }; | |
128 | |
442 | 129 static char const * const months[] = |
428 | 130 { |
131 "January", "February", "March", "April", "May", "June", | |
132 "July", "August", "September", "October", "November", "December" | |
133 }; | |
134 | |
5254
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
135 static char const * const roman_upper[] = |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
136 { |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
137 "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII" |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
138 }; |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
139 |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
140 static char const * const roman_lower[] = |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
141 { |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
142 "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii" |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
143 }; |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
144 |
428 | 145 /* Add character C to STRING and increment LENGTH, |
146 unless LENGTH would exceed MAX. */ | |
147 | |
148 #define add_char(c) do \ | |
149 { \ | |
150 if (length + 1 <= max) \ | |
151 string[length++] = (c); \ | |
152 } while (0) | |
153 | |
154 /* Add a 2 digit number to STRING, padding if specified. | |
155 Return the number of characters added, up to MAX. */ | |
156 | |
157 static int | |
158 add_num2 (char *string, int num, int max, enum padding pad) | |
159 { | |
160 int top = num / 10; | |
161 int length = 0; | |
162 | |
163 if (top == 0 && pad == blank) | |
164 add_char (' '); | |
165 else if (top != 0 || pad == zero) | |
166 add_char (top + '0'); | |
167 add_char (num % 10 + '0'); | |
168 return length; | |
169 } | |
170 | |
171 /* Add a 3 digit number to STRING, padding if specified. | |
172 Return the number of characters added, up to MAX. */ | |
173 | |
174 static int | |
175 add_num3 (char *string, int num, int max, enum padding pad) | |
176 { | |
177 int top = num / 100; | |
178 int mid = (num - top * 100) / 10; | |
179 int length = 0; | |
180 | |
181 if (top == 0 && pad == blank) | |
182 add_char (' '); | |
183 else if (top != 0 || pad == zero) | |
184 add_char (top + '0'); | |
185 if (mid == 0 && top == 0 && pad == blank) | |
186 add_char (' '); | |
187 else if (mid != 0 || top != 0 || pad == zero) | |
188 add_char (mid + '0'); | |
189 add_char (num % 10 + '0'); | |
190 return length; | |
191 } | |
192 | |
193 /* Like strncpy except return the number of characters copied. */ | |
194 | |
195 static int | |
442 | 196 add_str (char *to, const char *from, int max) |
428 | 197 { |
198 int i; | |
199 | |
200 for (i = 0; from[i] && i <= max; ++i) | |
201 to[i] = from[i]; | |
202 return i; | |
203 } | |
204 | |
205 static int | |
206 add_num_time_t (char *string, int max, time_t num) | |
207 { | |
208 /* This buffer is large enough to hold the character representation | |
209 (including the trailing NUL) of any unsigned decimal quantity | |
210 whose binary representation fits in 128 bits. */ | |
211 char buf[40]; | |
212 | |
213 if (sizeof (num) > 16) | |
2500 | 214 ABORT (); |
428 | 215 sprintf (buf, "%lu", (unsigned long) num); |
793 | 216 return add_str (string, buf, max); |
428 | 217 } |
218 | |
219 /* Return the week in the year of the time in TM, with the weeks | |
220 starting on Sundays. */ | |
221 | |
222 static int | |
442 | 223 sun_week (const struct tm *tm) |
428 | 224 { |
225 int dl; | |
226 | |
227 /* Set `dl' to the day in the year of the last day of the week previous | |
228 to the one containing the day specified in TM. If the day specified | |
229 in TM is in the first week of the year, `dl' will be negative or 0. | |
230 Otherwise, calculate the number of complete weeks before our week | |
231 (dl / 7) and add any partial week at the start of the year (dl % 7). */ | |
232 dl = tm->tm_yday - tm->tm_wday; | |
233 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); | |
234 } | |
235 | |
236 /* Return the week in the year of the time in TM, with the weeks | |
237 starting on Mondays. */ | |
238 | |
239 static int | |
442 | 240 mon_week (const struct tm *tm) |
428 | 241 { |
242 int dl, wday; | |
243 | |
244 if (tm->tm_wday == 0) | |
245 wday = 6; | |
246 else | |
247 wday = tm->tm_wday - 1; | |
248 dl = tm->tm_yday - wday; | |
249 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); | |
250 } | |
251 | |
4203 | 252 #ifndef __isleap |
253 /* Nonzero if YEAR is a leap year (every 4 years, | |
254 except every 100th isn't, and every 400th is). */ | |
255 # define __isleap(year) \ | |
256 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | |
257 #endif | |
258 | |
259 /* The number of days from the first day of the first ISO week of this | |
260 year to the year day YDAY with week day WDAY. ISO weeks start on | |
261 Monday; the first ISO week has the year's first Thursday. YDAY may | |
262 be as small as YDAY_MINIMUM. */ | |
263 #define ISO_WEEK_START_WDAY 1 /* Monday */ | |
264 #define ISO_WEEK1_WDAY 4 /* Thursday */ | |
265 #define YDAY_MINIMUM (-366) | |
266 static int | |
267 iso_week_days (int yday, int wday) | |
268 { | |
269 /* Add enough to the first operand of % to make it nonnegative. */ | |
270 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; | |
271 return (yday | |
272 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 | |
273 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); | |
274 } | |
275 | |
428 | 276 #if !defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME) |
442 | 277 char *zone_name (const struct tm *tp); |
428 | 278 char * |
442 | 279 zone_name (const struct tm *tp) |
428 | 280 { |
281 char *timezone (); | |
282 struct timeval tv; | |
283 struct timezone tz; | |
284 | |
285 gettimeofday (&tv, &tz); | |
286 return timezone (tz.tz_minuteswest, tp->tm_isdst); | |
287 } | |
288 #endif | |
289 | |
290 /* Format the time given in TM according to FORMAT, and put the | |
291 results in STRING. | |
292 Return the number of characters (not including terminating null) | |
293 that were put into STRING, or 0 if the length would have | |
294 exceeded MAX. */ | |
295 | |
442 | 296 size_t strftime (char *string, size_t max, const char *format, |
297 const struct tm *tm); | |
428 | 298 |
299 size_t | |
442 | 300 strftime (char *string, size_t max, const char *format, const struct tm *tm) |
428 | 301 { |
302 enum padding pad; /* Type of padding to apply. */ | |
303 size_t length = 0; /* Characters put in STRING so far. */ | |
304 | |
305 for (; *format && length < max; ++format) | |
306 { | |
307 if (*format != '%') | |
308 add_char (*format); | |
309 else | |
310 { | |
311 ++format; | |
312 /* Modifiers: */ | |
313 if (*format == '-') | |
314 { | |
315 pad = none; | |
316 ++format; | |
317 } | |
318 else if (*format == '_') | |
319 { | |
320 pad = blank; | |
321 ++format; | |
322 } | |
323 else | |
324 pad = zero; | |
325 | |
326 switch (*format) | |
327 { | |
328 /* Literal character fields: */ | |
329 case 0: | |
330 case '%': | |
331 add_char ('%'); | |
332 break; | |
333 case 'n': | |
334 add_char ('\n'); | |
335 break; | |
336 case 't': | |
337 add_char ('\t'); | |
338 break; | |
339 default: | |
340 add_char (*format); | |
341 break; | |
342 | |
343 /* Time fields: */ | |
344 case 'H': | |
345 case 'k': | |
346 length += | |
347 add_num2 (&string[length], tm->tm_hour, max - length, | |
348 *format == 'H' ? pad : blank); | |
349 break; | |
350 case 'I': | |
351 case 'l': | |
352 { | |
353 int hour12; | |
354 | |
355 if (tm->tm_hour == 0) | |
356 hour12 = 12; | |
357 else if (tm->tm_hour > 12) | |
358 hour12 = tm->tm_hour - 12; | |
359 else | |
360 hour12 = tm->tm_hour; | |
361 length += | |
362 add_num2 (&string[length], hour12, max - length, | |
363 *format == 'I' ? pad : blank); | |
364 } | |
365 break; | |
366 case 'M': | |
367 length += | |
368 add_num2 (&string[length], tm->tm_min, max - length, pad); | |
369 break; | |
370 case 'p': | |
371 if (tm->tm_hour < 12) | |
372 add_char ('A'); | |
373 else | |
374 add_char ('P'); | |
375 add_char ('M'); | |
376 break; | |
377 case 'r': | |
378 length += | |
379 strftime (&string[length], max - length, "%I:%M:%S %p", tm); | |
380 break; | |
381 case 'R': | |
382 length += | |
383 strftime (&string[length], max - length, "%H:%M", tm); | |
384 break; | |
385 | |
386 case 's': | |
387 { | |
388 struct tm writable_tm; | |
389 writable_tm = *tm; | |
390 length += add_num_time_t (&string[length], max - length, | |
391 mktime (&writable_tm)); | |
392 } | |
393 break; | |
394 | |
395 case 'S': | |
396 length += | |
397 add_num2 (&string[length], tm->tm_sec, max - length, pad); | |
398 break; | |
399 case 'T': | |
400 length += | |
401 strftime (&string[length], max - length, "%H:%M:%S", tm); | |
402 break; | |
4203 | 403 |
404 case 'V': | |
405 case 'g': | |
406 case 'G': | |
407 { | |
408 int year = tm->tm_year + 1900; | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
409 int ndays = iso_week_days (tm->tm_yday, tm->tm_wday); |
4203 | 410 |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
411 if (ndays < 0) |
4203 | 412 { |
413 /* This ISO week belongs to the previous year. */ | |
414 year--; | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
415 ndays = |
4203 | 416 iso_week_days (tm->tm_yday + (365 + __isleap (year)), |
417 tm->tm_wday); | |
418 } | |
419 else | |
420 { | |
421 int d = | |
422 iso_week_days (tm->tm_yday - (365 + __isleap (year)), | |
423 tm->tm_wday); | |
424 if (0 <= d) | |
425 { | |
426 /* This ISO week belongs to the next year. */ | |
427 year++; | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
428 ndays = d; |
4203 | 429 } |
430 } | |
431 | |
432 switch (*format) | |
433 { | |
434 /* | |
435 #### FIXME | |
436 We really can't assume 1000 <= year <= 9999 | |
437 once time_t gets beyond 32 bits, but it's true | |
438 of the rest of the code here so get with the | |
439 program | |
440 */ | |
441 case 'g': | |
442 length += | |
443 add_num2 (&string[length], year % 100, | |
444 max - length, pad); | |
445 break; | |
446 | |
447 case 'G': | |
448 add_char (year / 1000 + '0'); | |
449 length += add_num3 (&string[length], year % 1000, | |
450 max - length, zero); | |
451 break; | |
452 | |
453 default: | |
454 length += | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
455 add_num2 (&string[length], ndays / 7 + 1, |
4203 | 456 max - length, pad); |
457 break; | |
458 } | |
459 } | |
460 break; | |
428 | 461 case 'X': |
462 length += | |
463 strftime (&string[length], max - length, "%H:%M:%S", tm); | |
464 break; | |
4203 | 465 case 'z': |
466 { | |
467 /* | |
468 #### FIXME: could use tm->tm_gmtoff if present. Since | |
469 the other code in xemacs does not do so we follow the | |
470 leaders (and don't add a autoconf macro to detect | |
471 its presence). | |
472 */ | |
473 long int offset; | |
474 long int minutes; | |
475 struct tm lt, *ut; | |
476 time_t utc; | |
477 | |
478 lt = *tm; | |
479 utc = mktime(<); | |
480 ut = gmtime(&utc); | |
481 /* assume that tm is valid so the others will be too! */ | |
482 assert( utc != (time_t) -1 && ut != NULL ); | |
483 | |
484 /* tm diff code below is based on mktime.c, glibc 2.3.2 */ | |
485 { | |
486 int lt4, ut4, lt100, ut100, lt400, ut400; | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
487 int intervening_leap_days, years, ndays; |
4203 | 488 |
489 lt4 = (lt.tm_year >> 2) + (1900 >> 2) - | |
490 ! (lt.tm_year & 3); | |
491 ut4 = (ut->tm_year >> 2) + (1900 >> 2) - | |
492 ! (ut->tm_year & 3); | |
493 lt100 = lt4 / 25 - (lt4 % 25 < 0); | |
494 ut100 = ut4 / 25 - (ut4 % 25 < 0); | |
495 lt400 = lt100 >> 2; | |
496 ut400 = ut100 >> 2; | |
497 intervening_leap_days = | |
498 (lt4 - ut4) - (lt100 - ut100) + (lt400 - ut400); | |
499 years = lt.tm_year - ut->tm_year; | |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
500 ndays = (365 * years + intervening_leap_days |
4203 | 501 + (lt.tm_yday - ut->tm_yday)); |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
502 offset = (60 * (60 * (24 * ndays |
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4203
diff
changeset
|
503 + (lt.tm_hour - ut->tm_hour)) |
4203 | 504 + (lt.tm_min - ut->tm_min)) |
505 + (lt.tm_sec - ut->tm_sec)); | |
506 } | |
507 | |
508 minutes = offset / ( offset < 0 ? -60 : 60 ); | |
509 | |
510 add_char ((offset < 0 ? '-' : '+')); | |
511 | |
512 if ( minutes / 600 != 0 ) | |
513 add_char (minutes / 600 + '0'); | |
514 else if ( pad != none ) | |
515 add_char ((pad == zero ? '0' : ' ')); | |
516 | |
517 length += | |
518 add_num3 (&string[length], | |
519 ((minutes / 60 ) % 10) * 100 + (minutes % 60), | |
520 max - length, pad); | |
521 break; | |
522 } | |
428 | 523 case 'Z': |
524 #ifdef HAVE_TM_ZONE | |
525 length += add_str (&string[length], tm->tm_zone, max - length); | |
526 #else | |
527 #ifdef HAVE_TZNAME | |
528 if (tm->tm_isdst && tzname[1] && *tzname[1]) | |
529 length += add_str (&string[length], tzname[1], max - length); | |
530 else | |
531 length += add_str (&string[length], tzname[0], max - length); | |
532 #else | |
533 length += add_str (&string[length], zone_name (tm), max - length); | |
534 #endif | |
535 #endif | |
536 break; | |
537 | |
538 /* Date fields: */ | |
539 case 'a': | |
540 add_char (days[tm->tm_wday][0]); | |
541 add_char (days[tm->tm_wday][1]); | |
542 add_char (days[tm->tm_wday][2]); | |
543 break; | |
544 case 'A': | |
545 length += | |
546 add_str (&string[length], days[tm->tm_wday], max - length); | |
547 break; | |
548 case 'b': | |
549 case 'h': | |
550 add_char (months[tm->tm_mon][0]); | |
551 add_char (months[tm->tm_mon][1]); | |
552 add_char (months[tm->tm_mon][2]); | |
553 break; | |
554 case 'B': | |
555 length += | |
556 add_str (&string[length], months[tm->tm_mon], max - length); | |
557 break; | |
558 case 'c': | |
559 length += | |
560 strftime (&string[length], max - length, | |
561 "%a %b %d %H:%M:%S %Z %Y", tm); | |
562 break; | |
563 case 'C': | |
564 length += | |
565 add_num2 (&string[length], (tm->tm_year + 1900) / 100, | |
566 max - length, pad); | |
567 break; | |
568 case 'd': | |
569 length += | |
570 add_num2 (&string[length], tm->tm_mday, max - length, pad); | |
571 break; | |
572 case 'e': | |
573 length += | |
574 add_num2 (&string[length], tm->tm_mday, max - length, blank); | |
575 break; | |
576 case 'D': | |
577 length += | |
578 strftime (&string[length], max - length, "%m/%d/%y", tm); | |
579 break; | |
580 case 'j': | |
581 length += | |
582 add_num3 (&string[length], tm->tm_yday + 1, max - length, pad); | |
583 break; | |
584 case 'm': | |
585 length += | |
586 add_num2 (&string[length], tm->tm_mon + 1, max - length, pad); | |
587 break; | |
588 case 'U': | |
589 length += | |
590 add_num2 (&string[length], sun_week (tm), max - length, pad); | |
591 break; | |
592 case 'w': | |
593 add_char (tm->tm_wday + '0'); | |
594 break; | |
595 case 'W': | |
596 length += | |
597 add_num2 (&string[length], mon_week (tm), max - length, pad); | |
598 break; | |
599 case 'x': | |
600 length += | |
601 strftime (&string[length], max - length, "%m/%d/%y", tm); | |
602 break; | |
603 case 'y': | |
604 length += | |
605 add_num2 (&string[length], tm->tm_year % 100, | |
606 max - length, pad); | |
607 break; | |
608 case 'Y': | |
609 add_char ((tm->tm_year + 1900) / 1000 + '0'); | |
610 length += | |
611 add_num3 (&string[length], | |
612 (1900 + tm->tm_year) % 1000, max - length, zero); | |
613 break; | |
5254
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
614 case '\xe6': |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
615 length += |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
616 add_str (&string[length], roman_lower[tm->tm_mon], |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
617 max - length); |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
618 break; |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
619 case '\xC6': |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
620 length += |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
621 add_str (&string[length], roman_upper[tm->tm_mon], |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
622 max - length); |
1537701f08a1
Support Roman month numbers, #'format-time-string
Aidan Kehoe <kehoea@parhasard.net>
parents:
5016
diff
changeset
|
623 break; |
428 | 624 } |
625 } | |
626 } | |
627 add_char (0); | |
628 return length - 1; | |
629 } |