*** savedir/strftime.c.save1 2011-01-16 15:23:14.000000000 -0500 --- strftime.c 2012-04-20 10:16:28.000000000 -0400 *************** *** 39,42 **** --- 39,43 ---- * Updated December, 2001 * Updated January, 2011 + * Updated April, 2012 * * Fixes from ado@elsie.nci.nih.gov, *************** *** 76,79 **** --- 77,81 ---- #define HPUX_EXT 1 /* non-conflicting stuff in HP-UX date */ #define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */ + #define POSIX_2008 1 /* flag and fw for C, F, G, Y formats */ #undef strchr /* avoid AIX weirdness */ *************** *** 97,101 **** #define range(low, item, hi) max(low, min(item, hi)) ! #if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME) extern char *tzname[2]; extern int daylight; --- 99,104 ---- #define range(low, item, hi) max(low, min(item, hi)) ! /* Whew! This stuff is a mess. */ ! #if !defined(OS2) && !defined(MSDOS) && !defined(__CYGWIN__) && defined(HAVE_TZNAME) extern char *tzname[2]; extern int daylight; *************** *** 103,121 **** extern long int timezone, altzone; #else ! # if defined (HPUX) extern long int timezone; # else extern int timezone, altzone; ! # endif /* !HPUX */ ! #endif /* !SOLARIS && !mips && !M_UNIX */ #endif #undef min /* just in case */ - /* format for %+ -- currently unused */ - #ifndef NATIONAL_FORMAT - #define NATIONAL_FORMAT "%a %b %e %H:%M:%S %Z %Y" - #endif - /* min --- return minimum of two numbers */ --- 106,121 ---- extern long int timezone, altzone; #else ! # if defined (HPUX) || defined(__hpux) extern long int timezone; # else + # if !defined(__CYGWIN__) extern int timezone, altzone; ! # endif ! # endif ! #endif #endif #undef min /* just in case */ /* min --- return minimum of two numbers */ *************** *** 136,139 **** --- 136,167 ---- } + #ifdef POSIX_2008 + /* iso_8601_2000_year --- format a year per ISO 8601:2000 as in 1003.1 */ + + static void + iso_8601_2000_year(char *buf, int year, size_t fw) + { + int extra; + char sign = '\0'; + + if (year >= -9999 && year <= 9999) { + sprintf(buf, "%0*d", fw, year); + return; + } + + /* now things get weird */ + if (year > 9999) { + sign = '+'; + } else { + sign = '-'; + year = -year; + } + + extra = year / 10000; + year %= 10000; + sprintf(buf, "%c_%04d_%d", sign, extra, year); + } + #endif /* POSIX_2008 */ + /* strftime --- produce formatted time */ *************** *** 156,165 **** --- 184,200 ---- #ifndef HAVE_TM_NAME #ifndef HAVE_TZNAME + #ifndef __CYGWIN__ extern char *timezone(); struct timeval tv; struct timezone zone; + #endif /* __CYGWIN__ */ #endif /* HAVE_TZNAME */ #endif /* HAVE_TM_NAME */ #endif /* HAVE_TM_ZONE */ + #ifdef POSIX_2008 + int pad; + size_t fw; + char flag; + #endif /* POSIX_2008 */ /* various tables, useful in North America */ *************** *** 235,238 **** --- 270,307 ---- continue; } + #ifdef POSIX_2008 + pad = '\0'; + fw = 0; + flag = '\0'; + switch (*++format) { + case '+': + flag = '+'; + /* fall through */ + case '0': + pad = '0'; + format++; + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + break; + + default: + format--; + goto again; + } + for (; isdigit(*format); format++) { + fw = fw * 10 + (*format - '0'); + } + format--; + #endif /* POSIX_2008 */ + again: switch (*++format) { *************** *** 286,291 **** case 'C': century: ! sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100); break; --- 355,371 ---- case 'C': + #ifdef POSIX_2008 + if (pad != '\0' && fw > 0) { + size_t min_fw = (flag ? 3 : 2); + + fw = max(fw, min_fw); + sprintf(tbuf, flag + ? "%+0*ld" + : "%0*ld", fw, + (timeptr->tm_year + 1900L) / 100); + } else + #endif /* POSIX_2008 */ century: ! sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100); break; *************** *** 308,312 **** --- 388,415 ---- case 'F': /* ISO 8601 date representation */ + { + #ifdef POSIX_2008 + /* + * Field width for %F is for the whole thing. + * It must be at least 10. + */ + char m_d[10]; + strftime(m_d, sizeof m_d, "-%m-%d", timeptr); + size_t min_fw = 10; + + if (pad != '\0' && fw > 0) { + fw = max(fw, min_fw); + } else { + fw = min_fw; + } + + fw -= 6; /* -XX-XX at end are invariant */ + + iso_8601_2000_year(tbuf, timeptr->tm_year + 1900, fw); + strcat(tbuf, m_d); + #else strftime(tbuf, sizeof tbuf, "%Y-%m-%d", timeptr); + #endif /* POSIX_2008 */ + } break; *************** *** 330,335 **** y = 1900L + timeptr->tm_year; ! if (*format == 'G') ! sprintf(tbuf, "%ld", y); else sprintf(tbuf, "%02ld", y % 100); --- 433,450 ---- y = 1900L + timeptr->tm_year; ! if (*format == 'G') { ! #ifdef POSIX_2008 ! if (pad != '\0' && fw > 0) { ! size_t min_fw = 4; ! ! fw = max(fw, min_fw); ! sprintf(tbuf, flag ! ? "%+0*ld" ! : "%0*ld", fw, ! y); ! } else ! #endif /* POSIX_2008 */ ! sprintf(tbuf, "%ld", y); ! } else sprintf(tbuf, "%02ld", y % 100); *************** *** 456,460 **** case 'Y': /* year with century */ ! fullyear: sprintf(tbuf, "%ld", 1900L + timeptr->tm_year); break; --- 571,585 ---- case 'Y': /* year with century */ ! #ifdef POSIX_2008 ! if (pad != '\0' && fw > 0) { ! size_t min_fw = 4; ! ! fw = max(fw, min_fw); ! sprintf(tbuf, flag ! ? "%+0*ld" ! : "%0*ld", fw, ! 1900L + timeptr->tm_year); ! } else ! #endif /* POSIX_2008 */ sprintf(tbuf, "%ld", 1900L + timeptr->tm_year); break; *************** *** 497,506 **** * secs west of GMT. Convert to mins east of GMT. */ ! # ifdef HPUX off = -timezone / 60; # else /* ADR: 4 August 2001, fixed this per gazelle@interaccess.com */ off = -(daylight ? altzone : timezone) / 60; ! # endif /* !HPUX */ #else /* !HAVE_TZNAME */ gettimeofday(& tv, & zone); --- 622,631 ---- * secs west of GMT. Convert to mins east of GMT. */ ! # if defined(__hpux) || defined (HPUX) || defined(__CYGWIN__) off = -timezone / 60; # else /* ADR: 4 August 2001, fixed this per gazelle@interaccess.com */ off = -(daylight ? altzone : timezone) / 60; ! # endif #else /* !HAVE_TZNAME */ gettimeofday(& tv, & zone);