aboutsummaryrefslogtreecommitdiff
path: root/nuttx/lib/time/lib_strftime.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/lib/time/lib_strftime.c')
-rw-r--r--nuttx/lib/time/lib_strftime.c398
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;
+}