comparison src/strftime.c @ 5118:e0db3c197671 ben-lisp-object

merge up to latest default branch, doesn't compile yet
author Ben Wing <ben@xemacs.org>
date Sat, 26 Dec 2009 21:18:49 -0600
parents 0a63e5de7bdc
children 2ade80e8c640
comparison
equal deleted inserted replaced
5117:3742ea8250b5 5118:e0db3c197671
56 %R time, 24-hour (hh:mm) 56 %R time, 24-hour (hh:mm)
57 %s time in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension) 57 %s time in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension)
58 %S second (00..61) 58 %S second (00..61)
59 %T time, 24-hour (hh:mm:ss) 59 %T time, 24-hour (hh:mm:ss)
60 %X locale's time representation (%H:%M:%S) 60 %X locale's time representation (%H:%M:%S)
61 %z time zone offset (e.g. +0530, -0800 etc)
61 %Z time zone (EDT), or nothing if no time zone is determinable 62 %Z time zone (EDT), or nothing if no time zone is determinable
62 63
63 Date fields: 64 Date fields:
64 %a locale's abbreviated weekday name (Sun..Sat) 65 %a locale's abbreviated weekday name (Sun..Sat)
65 %A locale's full weekday name, variable length (Sunday..Saturday) 66 %A locale's full weekday name, variable length (Sunday..Saturday)
68 %c locale's date and time (Sat Nov 04 12:02:33 EST 1989) 69 %c locale's date and time (Sat Nov 04 12:02:33 EST 1989)
69 %C century (00..99) 70 %C century (00..99)
70 %d day of month (01..31) 71 %d day of month (01..31)
71 %e day of month ( 1..31) 72 %e day of month ( 1..31)
72 %D date (mm/dd/yy) 73 %D date (mm/dd/yy)
74 %G year corresponding to the ISO 8601 week
75 %g Year of the ISO 8601 week within century (00 - 99)
73 %h same as %b 76 %h same as %b
74 %j day of year (001..366) 77 %j day of year (001..366)
75 %m month (01..12) 78 %m month (01..12)
76 %U week number of year with Sunday as first day of week (00..53) 79 %U week number of year with Sunday as first day of week (00..53)
80 %V ISO 8601 week number (first week is the earliest one with Thu)
77 %w day of week (0..6) 81 %w day of week (0..6)
78 %W week number of year with Monday as first day of week (00..53) 82 %W week number of year with Monday as first day of week (00..53)
79 %x locale's date representation (mm/dd/yy) 83 %x locale's date representation (mm/dd/yy)
80 %y last two digits of year (00..99) 84 %y last two digits of year (00..99)
81 %Y year (1970...) 85 %Y year (1970...)
231 wday = 6; 235 wday = 6;
232 else 236 else
233 wday = tm->tm_wday - 1; 237 wday = tm->tm_wday - 1;
234 dl = tm->tm_yday - wday; 238 dl = tm->tm_yday - wday;
235 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0); 239 return dl <= 0 ? 0 : dl / 7 + (dl % 7 != 0);
240 }
241
242 #ifndef __isleap
243 /* Nonzero if YEAR is a leap year (every 4 years,
244 except every 100th isn't, and every 400th is). */
245 # define __isleap(year) \
246 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
247 #endif
248
249 /* The number of days from the first day of the first ISO week of this
250 year to the year day YDAY with week day WDAY. ISO weeks start on
251 Monday; the first ISO week has the year's first Thursday. YDAY may
252 be as small as YDAY_MINIMUM. */
253 #define ISO_WEEK_START_WDAY 1 /* Monday */
254 #define ISO_WEEK1_WDAY 4 /* Thursday */
255 #define YDAY_MINIMUM (-366)
256 static int
257 iso_week_days (int yday, int wday)
258 {
259 /* Add enough to the first operand of % to make it nonnegative. */
260 int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
261 return (yday
262 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
263 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
236 } 264 }
237 265
238 #if !defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME) 266 #if !defined(HAVE_TM_ZONE) && !defined(HAVE_TZNAME)
239 char *zone_name (const struct tm *tp); 267 char *zone_name (const struct tm *tp);
240 char * 268 char *
360 break; 388 break;
361 case 'T': 389 case 'T':
362 length += 390 length +=
363 strftime (&string[length], max - length, "%H:%M:%S", tm); 391 strftime (&string[length], max - length, "%H:%M:%S", tm);
364 break; 392 break;
393
394 case 'V':
395 case 'g':
396 case 'G':
397 {
398 int year = tm->tm_year + 1900;
399 int days = iso_week_days (tm->tm_yday, tm->tm_wday);
400
401 if (days < 0)
402 {
403 /* This ISO week belongs to the previous year. */
404 year--;
405 days =
406 iso_week_days (tm->tm_yday + (365 + __isleap (year)),
407 tm->tm_wday);
408 }
409 else
410 {
411 int d =
412 iso_week_days (tm->tm_yday - (365 + __isleap (year)),
413 tm->tm_wday);
414 if (0 <= d)
415 {
416 /* This ISO week belongs to the next year. */
417 year++;
418 days = d;
419 }
420 }
421
422 switch (*format)
423 {
424 /*
425 #### FIXME
426 We really can't assume 1000 <= year <= 9999
427 once time_t gets beyond 32 bits, but it's true
428 of the rest of the code here so get with the
429 program
430 */
431 case 'g':
432 length +=
433 add_num2 (&string[length], year % 100,
434 max - length, pad);
435 break;
436
437 case 'G':
438 add_char (year / 1000 + '0');
439 length += add_num3 (&string[length], year % 1000,
440 max - length, zero);
441 break;
442
443 default:
444 length +=
445 add_num2 (&string[length], days / 7 + 1,
446 max - length, pad);
447 break;
448 }
449 }
450 break;
365 case 'X': 451 case 'X':
366 length += 452 length +=
367 strftime (&string[length], max - length, "%H:%M:%S", tm); 453 strftime (&string[length], max - length, "%H:%M:%S", tm);
368 break; 454 break;
455 case 'z':
456 {
457 /*
458 #### FIXME: could use tm->tm_gmtoff if present. Since
459 the other code in xemacs does not do so we follow the
460 leaders (and don't add a autoconf macro to detect
461 its presence).
462 */
463 long int offset;
464 long int minutes;
465 struct tm lt, *ut;
466 time_t utc;
467
468 lt = *tm;
469 utc = mktime(&lt);
470 ut = gmtime(&utc);
471 /* assume that tm is valid so the others will be too! */
472 assert( utc != (time_t) -1 && ut != NULL );
473
474 /* tm diff code below is based on mktime.c, glibc 2.3.2 */
475 {
476 int lt4, ut4, lt100, ut100, lt400, ut400;
477 int intervening_leap_days, years, days;
478
479 lt4 = (lt.tm_year >> 2) + (1900 >> 2) -
480 ! (lt.tm_year & 3);
481 ut4 = (ut->tm_year >> 2) + (1900 >> 2) -
482 ! (ut->tm_year & 3);
483 lt100 = lt4 / 25 - (lt4 % 25 < 0);
484 ut100 = ut4 / 25 - (ut4 % 25 < 0);
485 lt400 = lt100 >> 2;
486 ut400 = ut100 >> 2;
487 intervening_leap_days =
488 (lt4 - ut4) - (lt100 - ut100) + (lt400 - ut400);
489 years = lt.tm_year - ut->tm_year;
490 days = (365 * years + intervening_leap_days
491 + (lt.tm_yday - ut->tm_yday));
492 offset = (60 * (60 * (24 * days + (lt.tm_hour - ut->tm_hour))
493 + (lt.tm_min - ut->tm_min))
494 + (lt.tm_sec - ut->tm_sec));
495 }
496
497 minutes = offset / ( offset < 0 ? -60 : 60 );
498
499 add_char ((offset < 0 ? '-' : '+'));
500
501 if ( minutes / 600 != 0 )
502 add_char (minutes / 600 + '0');
503 else if ( pad != none )
504 add_char ((pad == zero ? '0' : ' '));
505
506 length +=
507 add_num3 (&string[length],
508 ((minutes / 60 ) % 10) * 100 + (minutes % 60),
509 max - length, pad);
510 break;
511 }
369 case 'Z': 512 case 'Z':
370 #ifdef HAVE_TM_ZONE 513 #ifdef HAVE_TM_ZONE
371 length += add_str (&string[length], tm->tm_zone, max - length); 514 length += add_str (&string[length], tm->tm_zone, max - length);
372 #else 515 #else
373 #ifdef HAVE_TZNAME 516 #ifdef HAVE_TZNAME