mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
libs/libc/time: Add configuration options for the strftime
This adds 3 configuration options for the lib_strftime, which can be used to save flash memory when all the formatters are not needed by an embedded application. There is always a minimal set of formatters supported: "%a, %b/%h, %d, %H, %m, %M, %S, %Y, %%". To add on top of that one can specify: - LIBC_STRFTIME_C_STANDARD_FORMATS : All ISO-C conversion specifiers - LIBC_STRFTIME_POSIX_FORMATS : Additional posix formats - LIBC_STRFTIME_NONSTANDARD_FORMATS : Additional GNU nonstandard formats All of these are enabled by default unless building for CONFIG_DEFAULT_SMALL. Disabling these options can save over 3KB of flash on an 32-bit ARM system, when all the format specifiers are not needed. Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit is contained in:
parent
75a12b1258
commit
116a325763
2 changed files with 310 additions and 248 deletions
|
|
@ -5,6 +5,41 @@
|
|||
|
||||
menu "Time/Time Zone Support"
|
||||
|
||||
config LIBC_STRFTIME_C_STANDARD_FORMATS
|
||||
bool "strftime ISO C conversion specifiers"
|
||||
default !DEFAULT_SMALL
|
||||
---help---
|
||||
Enable ISO C strftime conversion specifiers that are not part of
|
||||
the small always-enabled subset. Disabling this option
|
||||
removes support for %A, %B, %I, %j, %p, %U, %w, %W, %x, %X, and
|
||||
%y. The always-enabled subset is %a, %b/%h, %d, %H, %m, %M,
|
||||
%S, %Y, and %%.
|
||||
|
||||
Disabling this option makes strftime smaller, but the implementation
|
||||
no longer supports all conversion specifiers required by ISO C.
|
||||
|
||||
config LIBC_STRFTIME_POSIX_FORMATS
|
||||
bool "strftime POSIX conversion specifiers"
|
||||
default !DEFAULT_SMALL
|
||||
depends on LIBC_STRFTIME_C_STANDARD_FORMATS
|
||||
---help---
|
||||
Enable POSIX strftime conversion specifiers beyond ISO C that are
|
||||
implemented by NuttX. Disabling this option removes support for
|
||||
%C, %e, %F, %g, %G, %n, %r, %R, %t, %T, %u, %V, and %z.
|
||||
Enabling this option also enables the ISO C conversion specifiers.
|
||||
|
||||
Note that %h is kept in the always-enabled subset as an alias for
|
||||
%b because it shares the same implementation. Some POSIX
|
||||
specifiers may be controlled by other options.
|
||||
|
||||
config LIBC_STRFTIME_NONSTANDARD_FORMATS
|
||||
bool "strftime non-standard conversion specifiers"
|
||||
default !DEFAULT_SMALL
|
||||
---help---
|
||||
Enable NuttX/GNU-style strftime conversion specifiers that are not
|
||||
required by ISO C or POSIX. Disabling this option removes support
|
||||
for %k, %l, %P, and %s.
|
||||
|
||||
config LIBC_LOCALTIME
|
||||
bool "localtime API call support"
|
||||
default "n"
|
||||
|
|
|
|||
|
|
@ -62,11 +62,13 @@ static const char * const g_abbrev_wdayname[7] =
|
|||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LIBC_STRFTIME_C_STANDARD_FORMATS
|
||||
static const char * const g_wdayname[7] =
|
||||
{
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
|
||||
"Saturday"
|
||||
};
|
||||
#endif
|
||||
|
||||
static const char * const g_abbrev_monthname[12] =
|
||||
{
|
||||
|
|
@ -74,11 +76,13 @@ static const char * const g_abbrev_monthname[12] =
|
|||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LIBC_STRFTIME_C_STANDARD_FORMATS
|
||||
static const char * const g_monthname[12] =
|
||||
{
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
|
|
@ -97,10 +101,12 @@ static const char * const g_monthname[12] =
|
|||
* true if current is leap year, false is not a leap year
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_LIBC_STRFTIME_POSIX_FORMATS
|
||||
static bool is_leap(int year)
|
||||
{
|
||||
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: get_week_num
|
||||
|
|
@ -115,6 +121,7 @@ static bool is_leap(int year)
|
|||
* the week number in a year
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_LIBC_STRFTIME_POSIX_FORMATS
|
||||
static int get_week_num(FAR const struct tm *time)
|
||||
{
|
||||
/* calculate the total week number in a year */
|
||||
|
|
@ -163,6 +170,7 @@ static int get_week_num(FAR const struct tm *time)
|
|||
|
||||
return week;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: get_week_year
|
||||
|
|
@ -177,6 +185,7 @@ static int get_week_num(FAR const struct tm *time)
|
|||
* the year that calculated based on week number
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_LIBC_STRFTIME_POSIX_FORMATS
|
||||
static int get_week_year(FAR const struct tm *time)
|
||||
{
|
||||
int week_num = get_week_num(time);
|
||||
|
|
@ -192,6 +201,7 @@ static int get_week_year(FAR const struct tm *time)
|
|||
|
||||
return week_year;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
|
|
@ -275,7 +285,10 @@ size_t strftime(FAR char *s, size_t max, FAR const char *format,
|
|||
FAR const char *str;
|
||||
FAR char *dest = s;
|
||||
int chleft = max;
|
||||
#if defined(CONFIG_LIBC_STRFTIME_C_STANDARD_FORMATS) || \
|
||||
defined(CONFIG_LIBC_STRFTIME_POSIX_FORMATS)
|
||||
int value;
|
||||
#endif
|
||||
int len;
|
||||
|
||||
while (*format && chleft > 0)
|
||||
|
|
@ -297,6 +310,8 @@ size_t strftime(FAR char *s, size_t max, FAR const char *format,
|
|||
process_next:
|
||||
switch (*format++)
|
||||
{
|
||||
/* Always-enabled conversion specifiers. */
|
||||
|
||||
/* %a: A three-letter abbreviation for the day of the week. */
|
||||
|
||||
case 'a':
|
||||
|
|
@ -309,18 +324,6 @@ process_next:
|
|||
}
|
||||
break;
|
||||
|
||||
/* %A: The full name for the day of the week. */
|
||||
|
||||
case 'A':
|
||||
{
|
||||
if (tm->tm_wday < 7)
|
||||
{
|
||||
str = g_wdayname[tm->tm_wday];
|
||||
len = snprintf(dest, chleft, "%s", str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* %h: Equivalent to %b */
|
||||
|
||||
case 'h':
|
||||
|
|
@ -339,26 +342,6 @@ process_next:
|
|||
}
|
||||
break;
|
||||
|
||||
/* %B: The full month name according to the current locale. */
|
||||
|
||||
case 'B':
|
||||
{
|
||||
if (tm->tm_mon < 12)
|
||||
{
|
||||
str = g_monthname[tm->tm_mon];
|
||||
len = snprintf(dest, chleft, "%s", str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* %C: The century number (year/100) as a 2-digit integer. */
|
||||
|
||||
case 'C':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_year / 100);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %d: The day of the month as a decimal number
|
||||
* (range 01 to 31).
|
||||
*/
|
||||
|
|
@ -387,43 +370,6 @@ process_next:
|
|||
goto process_next;
|
||||
}
|
||||
|
||||
/* %e: Like %d, the day of the month as a decimal number, but
|
||||
* a leading zero is replaced by a space.
|
||||
*/
|
||||
|
||||
case 'e':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%2d", tm->tm_mday);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %F: ISO 8601 date format: "%Y-%m-%d" */
|
||||
|
||||
case 'F':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%04d-%02d-%02d",
|
||||
tm->tm_year + TM_YEAR_BASE, tm->tm_mon + 1,
|
||||
tm->tm_mday);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %g: 2-digit year version of %G, (00-99) */
|
||||
|
||||
case 'g':
|
||||
{
|
||||
value = get_week_year(tm) % 100;
|
||||
len = snprintf(dest, chleft, "%02d", value);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %G: ISO 8601 week based year */
|
||||
|
||||
case 'G':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%04d", get_week_year(tm));
|
||||
}
|
||||
break;
|
||||
|
||||
/* %H: The hour as a decimal number using a 24-hour clock
|
||||
* (range 00 to 23).
|
||||
*/
|
||||
|
|
@ -434,7 +380,78 @@ process_next:
|
|||
}
|
||||
break;
|
||||
|
||||
/* %I: The hour as a decimal number using a 12-hour clock
|
||||
/* %m: The month as a decimal number (range 01 to 12). */
|
||||
|
||||
case 'm':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_mon + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %M: The minute as a decimal number (range 00 to 59). */
|
||||
|
||||
case 'M':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_min);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %S: The second as a decimal number (range 00 to 60).
|
||||
* (The range is up to 60 to allow for occasional leap seconds.)
|
||||
*/
|
||||
|
||||
case 'S':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_sec);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %Y: The year as a decimal number including the century. */
|
||||
|
||||
case 'Y':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%04d",
|
||||
tm->tm_year + TM_YEAR_BASE);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %%: A literal '%' character. */
|
||||
|
||||
case '%':
|
||||
{
|
||||
*dest = '%';
|
||||
len = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_LIBC_STRFTIME_C_STANDARD_FORMATS
|
||||
/* ISO C conversion specifiers. */
|
||||
|
||||
/* %A: The full name for the day of the week. */
|
||||
|
||||
case 'A':
|
||||
{
|
||||
if (tm->tm_wday < 7)
|
||||
{
|
||||
str = g_wdayname[tm->tm_wday];
|
||||
len = snprintf(dest, chleft, "%s", str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* %B: The full month name according to the current locale. */
|
||||
|
||||
case 'B':
|
||||
{
|
||||
if (tm->tm_mon < 12)
|
||||
{
|
||||
str = g_monthname[tm->tm_mon];
|
||||
len = snprintf(dest, chleft, "%s", str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* %I: The hour as a decimal number using a 12-hour clock
|
||||
* (range 01 to 12).
|
||||
*/
|
||||
|
||||
|
|
@ -460,55 +477,7 @@ process_next:
|
|||
}
|
||||
break;
|
||||
|
||||
/* %k: The hour (24-hour clock) as a decimal number
|
||||
* (range 0 to 23);
|
||||
* single digits are preceded by a blank.
|
||||
*/
|
||||
|
||||
case 'k':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%2d", tm->tm_hour);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %l: The hour (12-hour clock) as a decimal number
|
||||
* (range 1 to 12);
|
||||
* single digits are preceded by a blank.
|
||||
*/
|
||||
|
||||
case 'l':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%2d", (tm->tm_hour % 12) != 0 ?
|
||||
(tm->tm_hour % 12) : 12);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %m: The month as a decimal number (range 01 to 12). */
|
||||
|
||||
case 'm':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_mon + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %M: The minute as a decimal number (range 00 to 59). */
|
||||
|
||||
case 'M':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_min);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %n: A newline character. */
|
||||
|
||||
case 'n':
|
||||
{
|
||||
*dest = '\n';
|
||||
len = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* %p: Either "AM" or "PM" according to the given time value. */
|
||||
/* %p: Either "AM" or "PM" according to the given time value. */
|
||||
|
||||
case 'p':
|
||||
{
|
||||
|
|
@ -525,106 +494,7 @@ process_next:
|
|||
}
|
||||
break;
|
||||
|
||||
/* %P: Like %p but in lowercase: "am" or "pm" */
|
||||
|
||||
case 'P':
|
||||
{
|
||||
if (tm->tm_hour >= 12)
|
||||
{
|
||||
str = "pm";
|
||||
}
|
||||
else
|
||||
{
|
||||
str = "am";
|
||||
}
|
||||
|
||||
len = snprintf(dest, chleft, "%s", str);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %r: 12-hour clock time */
|
||||
|
||||
case 'r':
|
||||
{
|
||||
if (tm->tm_hour >= 12)
|
||||
{
|
||||
str = "pm";
|
||||
}
|
||||
else
|
||||
{
|
||||
str = "am";
|
||||
}
|
||||
|
||||
value = tm->tm_hour == 12 ?
|
||||
tm->tm_hour == 12 :
|
||||
tm->tm_hour % (HOURSPERDAY / 2);
|
||||
|
||||
len = snprintf(dest, chleft, "%02d:%02d:%02d %s",
|
||||
value, tm->tm_min, tm->tm_sec, str);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %R: Shortcut for %H:%M. */
|
||||
|
||||
case 'R':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d:%02d",
|
||||
tm->tm_hour, tm->tm_min);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %s: The number of seconds since the Epoch, that is,
|
||||
* since 1970-01-01 00:00:00 UTC.
|
||||
* Hmmm... mktime argume is not 'const'.
|
||||
*/
|
||||
|
||||
case 's':
|
||||
{
|
||||
struct tm tmp = *tm;
|
||||
len = snprintf(dest, chleft, "%ju", (uintmax_t)mktime(&tmp));
|
||||
}
|
||||
break;
|
||||
|
||||
/* %S: The second as a decimal number (range 00 to 60).
|
||||
* (The range is up to 60 to allow for occasional leap seconds.)
|
||||
*/
|
||||
|
||||
case 'S':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_sec);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %t: A tab character. */
|
||||
|
||||
case 't':
|
||||
{
|
||||
*dest = '\t';
|
||||
len = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* %T: Shortcut for %H:%M:%S. */
|
||||
|
||||
case 'T':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d:%02d:%02d",
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %u: The day of the week as a decimal, (1-7). Monday being 1,
|
||||
* Sunday being 0.
|
||||
*/
|
||||
|
||||
case 'u':
|
||||
{
|
||||
value = tm->tm_wday == 0 ? 7 : tm->tm_wday;
|
||||
len = snprintf(dest, chleft, "%d", value);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %U: week number of the current year as a decimal number,
|
||||
/* %U: Week number of the current year as a decimal number,
|
||||
* (00-53). Starting with the first Sunday as the first day
|
||||
* of week 01.
|
||||
*/
|
||||
|
|
@ -637,15 +507,6 @@ process_next:
|
|||
}
|
||||
break;
|
||||
|
||||
/* %V: ISO 8601 week number */
|
||||
|
||||
case 'V':
|
||||
{
|
||||
value = get_week_num(tm);
|
||||
len = snprintf(dest, chleft, "%02d", value);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %w: The weekday as a decimal number (range 0 to 6). */
|
||||
|
||||
case 'w':
|
||||
|
|
@ -696,37 +557,203 @@ process_next:
|
|||
len = snprintf(dest, chleft, "%02d", tm->tm_year % 100);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* %Y: The year as a decimal number including the century. */
|
||||
#ifdef CONFIG_LIBC_STRFTIME_POSIX_FORMATS
|
||||
/* POSIX conversion specifiers beyond ISO C. */
|
||||
|
||||
case 'Y':
|
||||
/* %C: The century number (year/100) as a 2-digit integer. */
|
||||
|
||||
case 'C':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%04d",
|
||||
tm->tm_year + TM_YEAR_BASE);
|
||||
len = snprintf(dest, chleft, "%02d", tm->tm_year / 100);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %z: Numeric timezone as hour and minute offset from UTC
|
||||
* "+hhmm" or "-hhmm"
|
||||
*/
|
||||
/* %e: Like %d, the day of the month as a decimal number, but
|
||||
* a leading zero is replaced by a space.
|
||||
*/
|
||||
|
||||
case 'z':
|
||||
{
|
||||
int hour = tm->tm_gmtoff / 3600;
|
||||
int min = tm->tm_gmtoff % 3600 / 60;
|
||||
int utc_val = hour * 100 + min;
|
||||
len = snprintf(dest, chleft, "+%04d", utc_val);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %%: A literal '%' character. */
|
||||
|
||||
case '%':
|
||||
case 'e':
|
||||
{
|
||||
*dest = '%';
|
||||
len = snprintf(dest, chleft, "%2d", tm->tm_mday);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %F: ISO 8601 date format: "%Y-%m-%d" */
|
||||
|
||||
case 'F':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%04d-%02d-%02d",
|
||||
tm->tm_year + TM_YEAR_BASE, tm->tm_mon + 1,
|
||||
tm->tm_mday);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %g: 2-digit year version of %G, (00-99) */
|
||||
|
||||
case 'g':
|
||||
{
|
||||
value = get_week_year(tm) % 100;
|
||||
len = snprintf(dest, chleft, "%02d", value);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %G: ISO 8601 week based year */
|
||||
|
||||
case 'G':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%04d", get_week_year(tm));
|
||||
}
|
||||
break;
|
||||
|
||||
/* %n: A newline character. */
|
||||
|
||||
case 'n':
|
||||
{
|
||||
*dest = '\n';
|
||||
len = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* %r: 12-hour clock time */
|
||||
|
||||
case 'r':
|
||||
{
|
||||
if (tm->tm_hour >= 12)
|
||||
{
|
||||
str = "pm";
|
||||
}
|
||||
else
|
||||
{
|
||||
str = "am";
|
||||
}
|
||||
|
||||
value = tm->tm_hour == 12 ?
|
||||
tm->tm_hour == 12 :
|
||||
tm->tm_hour % (HOURSPERDAY / 2);
|
||||
|
||||
len = snprintf(dest, chleft, "%02d:%02d:%02d %s",
|
||||
value, tm->tm_min, tm->tm_sec, str);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %R: Shortcut for %H:%M. */
|
||||
|
||||
case 'R':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d:%02d",
|
||||
tm->tm_hour, tm->tm_min);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %t: A tab character. */
|
||||
|
||||
case 't':
|
||||
{
|
||||
*dest = '\t';
|
||||
len = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
/* %T: Shortcut for %H:%M:%S. */
|
||||
|
||||
case 'T':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%02d:%02d:%02d",
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %u: The day of the week as a decimal, (1-7). Monday being 1,
|
||||
* Sunday being 0.
|
||||
*/
|
||||
|
||||
case 'u':
|
||||
{
|
||||
value = tm->tm_wday == 0 ? 7 : tm->tm_wday;
|
||||
len = snprintf(dest, chleft, "%d", value);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %V: ISO 8601 week number */
|
||||
|
||||
case 'V':
|
||||
{
|
||||
value = get_week_num(tm);
|
||||
len = snprintf(dest, chleft, "%02d", value);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %z: Numeric timezone as hour and minute offset from UTC
|
||||
* "+hhmm" or "-hhmm"
|
||||
*/
|
||||
|
||||
case 'z':
|
||||
{
|
||||
int hour = tm->tm_gmtoff / 3600;
|
||||
int min = tm->tm_gmtoff % 3600 / 60;
|
||||
int utc_val = hour * 100 + min;
|
||||
len = snprintf(dest, chleft, "+%04d", utc_val);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIBC_STRFTIME_NONSTANDARD_FORMATS
|
||||
/* Non-standard conversion specifiers. */
|
||||
|
||||
/* %k: The hour (24-hour clock) as a decimal number
|
||||
* (range 0 to 23);
|
||||
* single digits are preceded by a blank.
|
||||
*/
|
||||
|
||||
case 'k':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%2d", tm->tm_hour);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %l: The hour (12-hour clock) as a decimal number
|
||||
* (range 1 to 12);
|
||||
* single digits are preceded by a blank.
|
||||
*/
|
||||
|
||||
case 'l':
|
||||
{
|
||||
len = snprintf(dest, chleft, "%2d", (tm->tm_hour % 12) != 0 ?
|
||||
(tm->tm_hour % 12) : 12);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %P: Like %p but in lowercase: "am" or "pm" */
|
||||
|
||||
case 'P':
|
||||
{
|
||||
if (tm->tm_hour >= 12)
|
||||
{
|
||||
str = "pm";
|
||||
}
|
||||
else
|
||||
{
|
||||
str = "am";
|
||||
}
|
||||
|
||||
len = snprintf(dest, chleft, "%s", str);
|
||||
}
|
||||
break;
|
||||
|
||||
/* %s: The number of seconds since the Epoch, that is,
|
||||
* since 1970-01-01 00:00:00 UTC.
|
||||
* Hmmm... mktime argume is not 'const'.
|
||||
*/
|
||||
|
||||
case 's':
|
||||
{
|
||||
struct tm tmp = *tm;
|
||||
len = snprintf(dest, chleft, "%ju", (uintmax_t)mktime(&tmp));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Update counts and pointers */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue