?? strftime.c
字號:
/* strftime - formatted time and date to a string *//* * Modified slightly by Chet Ramey for inclusion in Bash *//* * strftime.c * * Public-domain implementation of ISO C library routine. * * If you can't do prototypes, get GCC. * * The C99 standard now specifies just about all of the formats * that were additional in the earlier versions of this file. * * For extensions from SunOS, add SUNOS_EXT. * For extensions from HP/UX, add HPUX_EXT. * For VMS dates, add VMS_EXT. * For complete POSIX semantics, add POSIX_SEMANTICS. * * The code for %c, %x, and %X follows the C99 specification for * the "C" locale. * * This version ignores LOCALE information. * It also doesn't worry about multi-byte characters. * So there. * * Arnold Robbins * January, February, March, 1991 * Updated March, April 1992 * Updated April, 1993 * Updated February, 1994 * Updated May, 1994 * Updated January, 1995 * Updated September, 1995 * Updated January, 1996 * Updated July, 1997 * Updated October, 1999 * Updated September, 2000 * Updated December, 2001 * Updated January, 2011 * * Fixes from ado@elsie.nci.nih.gov, * February 1991, May 1992 * Fixes from Tor Lillqvist tml@tik.vtt.fi, * May 1993 * Further fixes from ado@elsie.nci.nih.gov, * February 1994 * %z code from chip@chinacat.unicom.com, * Applied September 1995 * %V code fixed (again) and %G, %g added, * January 1996 * %v code fixed, better configuration, * July 1997 * Moved to C99 specification. * September 2000 * Fixes from Tanaka Akira <akr@m17n.org> * December 2001 */#include <config.h>#include <stdio.h>#include <ctype.h>#include <time.h>#if defined(TM_IN_SYS_TIME)#include <sys/types.h>#include <sys/time.h>#endif#include <stdlib.h>#include <string.h>/* defaults: season to taste */#define SUNOS_EXT 1 /* stuff in SunOS strftime routine */#define VMS_EXT 1 /* include %v for VMS date format */#define HPUX_EXT 1 /* non-conflicting stuff in HP-UX date */#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */#undef strchr /* avoid AIX weirdness */#if defined (SHELL)extern char *get_string_value (const char *);#endifextern void tzset(void);static int weeknumber(const struct tm *timeptr, int firstweekday);static int iso8601wknum(const struct tm *timeptr);#ifndef inline#ifdef __GNUC__#define inline __inline__#else#define inline /**/#endif#endif#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;#if defined(SOLARIS) || defined(mips) || defined (M_UNIX)extern long int timezone, altzone;#else# if defined (HPUX)extern long int timezone;# elseextern 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 */static inline intmin(int a, int b){ return (a < b ? a : b);}#undef max /* also, just in case *//* max --- return maximum of two numbers */static inline intmax(int a, int b){ return (a > b ? a : b);}/* strftime --- produce formatted time */size_tstrftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr){ char *endp = s + maxsize; char *start = s; auto char tbuf[100]; long off; int i, w; long y; static short first = 1;#ifdef POSIX_SEMANTICS static char *savetz = NULL; static int savetzlen = 0; char *tz;#endif /* POSIX_SEMANTICS */#ifndef HAVE_TM_ZONE#ifndef HAVE_TM_NAME#ifndef HAVE_TZNAME extern char *timezone(); struct timeval tv; struct timezone zone;#endif /* HAVE_TZNAME */#endif /* HAVE_TM_NAME */#endif /* HAVE_TM_ZONE */ /* various tables, useful in North America */ static const char *days_a[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", }; static const char *days_l[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", }; static const char *months_a[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; static const char *months_l[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }; static const char *ampm[] = { "AM", "PM", }; if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0) return 0; /* quick check if we even need to bother */ if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize) return 0;#ifndef POSIX_SEMANTICS if (first) { tzset(); first = 0; }#else /* POSIX_SEMANTICS */#if defined (SHELL) tz = get_string_value ("TZ");#else tz = getenv("TZ");#endif if (first) { if (tz != NULL) { int tzlen = strlen(tz); savetz = (char *) malloc(tzlen + 1); if (savetz != NULL) { savetzlen = tzlen + 1; strcpy(savetz, tz); } } tzset(); first = 0; } /* if we have a saved TZ, and it is different, recapture and reset */ if (tz && savetz && (tz[0] != savetz[0] || strcmp(tz, savetz) != 0)) { i = strlen(tz) + 1; if (i > savetzlen) { savetz = (char *) realloc(savetz, i); if (savetz) { savetzlen = i; strcpy(savetz, tz); } } else strcpy(savetz, tz); tzset(); }#endif /* POSIX_SEMANTICS */ for (; *format && s < endp - 1; format++) { tbuf[0] = '\0'; if (*format != '%') { *s++ = *format; continue; } again: switch (*++format) { case '\0': *s++ = '%'; goto out; case '%': *s++ = '%'; continue; case 'a': /* abbreviated weekday name */ if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) strcpy(tbuf, "?"); else strcpy(tbuf, days_a[timeptr->tm_wday]); break; case 'A': /* full weekday name */ if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6) strcpy(tbuf, "?"); else strcpy(tbuf, days_l[timeptr->tm_wday]); break; case 'b': /* abbreviated month name */ short_month: if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) strcpy(tbuf, "?"); else strcpy(tbuf, months_a[timeptr->tm_mon]); break; case 'B': /* full month name */ if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11) strcpy(tbuf, "?"); else strcpy(tbuf, months_l[timeptr->tm_mon]); break; case 'c': /* appropriate date and time representation */ /* * This used to be: * * strftime(tbuf, sizeof tbuf, "%a %b %e %H:%M:%S %Y", timeptr); * * Now, per the ISO 1999 C standard, it this: */ strftime(tbuf, sizeof tbuf, "%A %B %d %T %Y", timeptr); break; case 'C': century: sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100); break; case 'd': /* day of the month, 01 - 31 */ i = range(1, timeptr->tm_mday, 31); sprintf(tbuf, "%02d", i); break; case 'D': /* date as %m/%d/%y */ strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr); break; case 'e': /* day of month, blank padded */ sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31)); break; case 'E': /* POSIX (now C99) locale extensions, ignored for now */ goto again; case 'F': /* ISO 8601 date representation */ strftime(tbuf, sizeof tbuf, "%Y-%m-%d", timeptr); break; case 'g': case 'G': /* * Year of ISO week. * * If it's December but the ISO week number is one, * that week is in next year. * If it's January but the ISO week number is 52 or * 53, that week is in last year. * Otherwise, it's this year. */ w = iso8601wknum(timeptr); if (timeptr->tm_mon == 11 && w == 1) y = 1900L + timeptr->tm_year + 1; else if (timeptr->tm_mon == 0 && w >= 52) y = 1900L + timeptr->tm_year - 1; else y = 1900L + timeptr->tm_year; if (*format == 'G') sprintf(tbuf, "%ld", y); else sprintf(tbuf, "%02ld", y % 100); break; case 'h': /* abbreviated month name */ goto short_month; case 'H': /* hour, 24-hour clock, 00 - 23 */ i = range(0, timeptr->tm_hour, 23); sprintf(tbuf, "%02d", i); break; case 'I': /* hour, 12-hour clock, 01 - 12 */ i = range(0, timeptr->tm_hour, 23); if (i == 0) i = 12; else if (i > 12) i -= 12; sprintf(tbuf, "%02d", i); break; case 'j': /* day of the year, 001 - 366 */ sprintf(tbuf, "%03d", timeptr->tm_yday + 1); break; case 'm': /* month, 01 - 12 */ i = range(0, timeptr->tm_mon, 11); sprintf(tbuf, "%02d", i + 1); break; case 'M': /* minute, 00 - 59 */ i = range(0, timeptr->tm_min, 59); sprintf(tbuf, "%02d", i); break; case 'n': /* same as \n */ tbuf[0] = '\n'; tbuf[1] = '\0'; break; case 'O': /* POSIX (now C99) locale extensions, ignored for now */ goto again; case 'p': /* am or pm based on 12-hour clock */ i = range(0, timeptr->tm_hour, 23); if (i < 12) strcpy(tbuf, ampm[0]); else strcpy(tbuf, ampm[1]); break; case 'r': /* time as %I:%M:%S %p */ strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr); break; case 'R': /* time as %H:%M */ strftime(tbuf, sizeof tbuf, "%H:%M", timeptr); break;#if defined(HAVE_MKTIME) case 's': /* time as seconds since the Epoch */ { struct tm non_const_timeptr; non_const_timeptr = *timeptr; sprintf(tbuf, "%ld", mktime(& non_const_timeptr)); break; }#endif /* defined(HAVE_MKTIME) */ case 'S': /* second, 00 - 60 */ i = range(0, timeptr->tm_sec, 60); sprintf(tbuf, "%02d", i); break; case 't': /* same as \t */ tbuf[0] = '\t'; tbuf[1] = '\0'; break; case 'T': /* time as %H:%M:%S */ the_time: strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr); break; case 'u': /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */ sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 : timeptr->tm_wday); break; case 'U': /* week of year, Sunday is first day of week */ sprintf(tbuf, "%02d", weeknumber(timeptr, 0)); break; case 'V': /* week of year according ISO 8601 */ sprintf(tbuf, "%02d", iso8601wknum(timeptr)); break; case 'w': /* weekday, Sunday == 0, 0 - 6 */ i = range(0, timeptr->tm_wday, 6); sprintf(tbuf, "%d", i); break; case 'W': /* week of year, Monday is first day of week */ sprintf(tbuf, "%02d", weeknumber(timeptr, 1)); break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -