--- /dev/null
+/*****************************************************************************/
+/* */
+/* strftime.c */
+/* */
+/* Convert broken down time to a string in a user specified format */
+/* */
+/* */
+/* */
+/* (C) 2002 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* This software is provided 'as-is', without any expressed or implied */
+/* warranty. In no event will the authors be held liable for any damages */
+/* arising from the use of this software. */
+/* */
+/* Permission is granted to anyone to use this software for any purpose, */
+/* including commercial applications, and to alter it and redistribute it */
+/* freely, subject to the following restrictions: */
+/* */
+/* 1. The origin of this software must not be misrepresented; you must not */
+/* claim that you wrote the original software. If you use this software */
+/* in a product, an acknowledgment in the product documentation would be */
+/* appreciated but is not required. */
+/* 2. Altered source versions must be plainly marked as such, and must not */
+/* be misrepresented as being the original software. */
+/* 3. This notice may not be removed or altered from any source */
+/* distribution. */
+/* */
+/*****************************************************************************/
+
+
+
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+
+
+
+/* Use static local variables for speed */
+#pragma staticlocals (on);
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+size_t __fastcall__ strftime (char* buf, size_t bufsize, const char* format,
+ const struct tm* tm)
+{
+ static const char* days[7] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"
+ };
+ static const char* months[12] = {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+ };
+
+ unsigned count;
+ unsigned len;
+ char c;
+ char arg[40];
+ const char* argptr;
+ unsigned week;
+
+ /* Copy until we reach the end of the format string or a format specifier */
+ count = 0;
+ while (1) {
+ if (count >= bufsize) {
+ /* Not enough buffer space available */
+ return 0;
+ }
+ if ((c = *format++) == '\0') {
+ /* End of format string reached */
+ *buf = '\0';
+ return count;
+ }
+ if (c == '%') {
+ /* Format specifier */
+ argptr = arg;
+ switch (*format++) {
+
+ case '%':
+ arg[0] = '%';
+ arg[1] = '\0';
+ break;
+
+ case 'A':
+ argptr = days[tm->tm_wday];
+ break;
+
+ case 'B':
+ argptr = months[tm->tm_mon];
+ break;
+
+ case 'D':
+ sprintf (arg, "%02d/%02d/%02d", tm->tm_mon + 1,
+ tm->tm_mday, tm->tm_year % 100);
+ break;
+
+ case 'F':
+ /* C99 */
+ sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday);
+ break;
+
+ case 'H':
+ sprintf (arg, "%02d", tm->tm_hour);
+ break;
+
+ case 'I':
+ sprintf (arg, "%02d", tm->tm_hour % 12);
+ break;
+
+ case 'M':
+ sprintf (arg, "%02d", tm->tm_min);
+ break;
+
+ case 'P':
+ /* GNU extension */
+ argptr = (tm->tm_hour >= 12)? "pm" : "am";
+ break;
+
+ case 'S':
+ sprintf (arg, "%02d", tm->tm_sec);
+ break;
+
+ case 'U':
+ week = tm->tm_yday / 7;
+ if (tm->tm_mday % 7 > tm->tm_wday) {
+ ++week;
+ }
+ sprintf (arg, "%02u", week);
+ break;
+
+ case 'W':
+ /* ### This one is buggy */
+ week = tm->tm_yday / 7;
+ if (tm->tm_mday % 7 > tm->tm_wday) {
+ ++week;
+ }
+ sprintf (arg, "%2u", week);
+ break;
+
+ case 'X':
+ sprintf (arg, "%02d:%02d:%02d", tm->tm_hour,
+ tm->tm_min, tm->tm_sec);
+ break;
+
+ case 'Y':
+ sprintf (arg, "%4d", tm->tm_year + 1900);
+ break;
+
+ case 'Z':
+ argptr = tm->tm_isdst? _tz.dstname : _tz.tzname;
+ break;
+
+ case 'a':
+ sprintf (arg, "%.3s", days[tm->tm_wday]);
+ break;
+
+ case 'b':
+ sprintf (arg, "%.3s", months[tm->tm_mday]);
+ break;
+
+ case 'c':
+ sprintf (arg, "%.3s %.3s%3d %02d:%02d:%02d %d",
+ days[tm->tm_wday], months[tm->tm_mon],
+ tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec, tm->tm_year + 1900);
+ break;
+
+ case 'd':
+ sprintf (arg, "%02d", tm->tm_mday);
+ break;
+
+ case 'j':
+ sprintf (arg, "%03d", tm->tm_yday + 1);
+ break;
+
+ case 'm':
+ sprintf (arg, "%02d", tm->tm_mon + 1);
+ break;
+
+ case 'p':
+ argptr = (tm->tm_hour >= 12)? "PM" : "AM";
+ break;
+
+ case 'w':
+ sprintf (arg, "%d", tm->tm_wday);
+ break;
+
+ case 'x':
+ sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday);
+ break;
+
+ case 'y':
+ sprintf (arg, "%02d", tm->tm_year % 100);
+ break;
+
+ default:
+ /* Unknown format specifier, convert to empty string */
+ arg[0] = '\0';
+ break;
+ }
+
+ /* Check if we have enough space to copy the argument string */
+ len = strlen (argptr);
+ count += len;
+ if (count < bufsize) {
+ memcpy (buf, argptr, len);
+ buf += len;
+ }
+
+ } else {
+
+ /* No format character, just copy */
+ *buf++ = c;
+ ++count;
+
+ }
+ }
+}
+
+
+