diff options
Diffstat (limited to 'nuttx/lib/time/lib_strftime.c')
-rw-r--r-- | nuttx/lib/time/lib_strftime.c | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/nuttx/lib/time/lib_strftime.c b/nuttx/lib/time/lib_strftime.c new file mode 100644 index 000000000..c1ac345ee --- /dev/null +++ b/nuttx/lib/time/lib_strftime.c @@ -0,0 +1,398 @@ +/**************************************************************************** + * lib/time/lib_strftime.c + * + * Copyright (C) 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <sys/types.h> + +#include <stdio.h> +#include <time.h> +#include <debug.h> + +#include <nuttx/time.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Constant Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char * const g_abbrevmonthname[12] = +{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const char * const g_monthname[12] = +{ + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: strftime + * + * Description: + * The strftime() function formats the broken-down time tm according to + * the format specification format and places the result in the character + * array s of size max. + * + * Ordinary characters placed in the format string are copied to s without + * conversion. Conversion specifications are introduced by a '%' charac- + * ter, and terminated by a conversion specifier character, and are + * replaced in s as follows: + * + * %b The abbreviated month name according to the current locale. + * %B The full month name according to the current locale. + * %C The century number (year/100) as a 2-digit integer. (SU) + * %d The day of the month as a decimal number (range 01 to 31). + * %e Like %d, the day of the month as a decimal number, but a leading + * zero is replaced by a space. + * %h Equivalent to %b. (SU) + * %H The hour as a decimal number using a 24-hour clock (range 00 to 23). + * %I The hour as a decimal number using a 12-hour clock (range 01 to 12). + * %j The day of the year as a decimal number (range 001 to 366). + * %k The hour (24-hour clock) as a decimal number (range 0 to 23); + * single digits are preceded by a blank. (See also %H.) (TZ) + * %l The hour (12-hour clock) as a decimal number (range 1 to 12); + * single digits are preceded by a blank. (See also %I.) (TZ) + * %m The month as a decimal number (range 01 to 12). + * %M The minute as a decimal number (range 00 to 59). + * %n A newline character. (SU) + * %p Either "AM" or "PM" according to the given time value, or the + * corresponding strings for the current locale. Noon is treated + * as "PM" and midnight as "AM". + * %P Like %p but in lowercase: "am" or "pm" or a corresponding string + * for the current locale. (GNU) + * %s The number of seconds since the Epoch, that is, since 1970-01-01 + * 00:00:00 UTC. (TZ) + * %S The second as a decimal number (range 00 to 60). (The range is + * up to 60 to allow for occasional leap seconds.) + * %t A tab character. (SU) + * %y The year as a decimal number without a century (range 00 to 99). + * %Y The year as a decimal number including the century. + * %% A literal '%' character. + * + * Returned Value: + * The strftime() function returns the number of characters placed in the + * array s, not including the terminating null byte, provided the string, + * including the terminating null byte, fits. Otherwise, it returns 0, + * and the contents of the array is undefined. + * + ****************************************************************************/ + +size_t strftime(char *s, size_t max, const char *format, const struct tm *tm) +{ + const char *str; + char *dest = s; + int chleft = max; + int value; + int len; + + while (*format && chleft > 0) + { + /* Just copy regular characters */ + + if (*format != '%') + { + *dest++ = *format++; + chleft--; + continue; + } + + /* Handle the format character */ + + format++; + len = 0; + + switch (*format++) + { + /* %a: A three-letter abbreviation for the day of the week. */ + /* %A: The full name for the day of the week. */ + + case 'a': + case 'A': + { + len = snprintf(dest, chleft, "Day"); /* Not supported */ + } + break; + + /* %h: Equivalent to %b */ + + case 'h': + + /* %b: The abbreviated month name according to the current locale. */ + + case 'b': + { + if (tm->tm_mon < 12) + { + str = g_abbrevmonthname[tm->tm_mon]; + 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; + + /* %y: The year as a decimal number without a century (range 00 to 99). */ + + case 'y': + + /* %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). */ + + case 'd': + { + len = snprintf(dest, chleft, "%02d", tm->tm_mday); + } + break; + + /* %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; + + /* %H: The hour as a decimal number using a 24-hour clock (range 00 to 23). */ + + case 'H': + { + len = snprintf(dest, chleft, "%02d", tm->tm_hour); + } + break; + + /* %I: The hour as a decimal number using a 12-hour clock (range 01 to 12). */ + + case 'I': + { + len = snprintf(dest, chleft, "%02d", tm->tm_hour % 12); + } + break; + + /* %j: The day of the year as a decimal number (range 001 to 366). */ + + case 'j': + { + if (tm->tm_mon < 12) + { + value = clock_daysbeforemonth(tm->tm_mon, clock_isleapyear(tm->tm_year)) + tm->tm_mday; + len = snprintf(dest, chleft, "%03d", value); + } + } + 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); + } + 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. */ + + case 'p': + { + if (tm->tm_hour >= 12) + { + str = "PM"; + } + else + { + str = "AM"; + } + len = snprintf(dest, chleft, "%s", str); + } + 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. + */ + + case 's': + { + len = snprintf(dest, chleft, "%d", mktime(tm)); + } + 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; + + /* %Y: The year as a decimal number including the century. */ + + case 'Y': + { + len = snprintf(dest, chleft, "%04d", tm->tm_year + 1900); + } + break; + + /* %%: A literal '%' character. */ + + case '%': + { + *dest = '%'; + len = 1; + } + break; + } + + /* Update counts and pointers */ + + dest += len; + chleft -= len; + } + + return max - chleft; +} |