#include "util_time.h"
+
+/* Number of characters needed to format the microsecond part of a timestamp.
+ * Microseconds have 6 digits plus one separator character makes 7.
+ * */
+#define AP_CTIME_USEC_LENGTH 7
+
+/* Length of ISO 8601 date/time */
+#define AP_CTIME_COMPACT_LEN 20
+
+
/* Cache for exploded values of recent timestamps
*/
}
AP_DECLARE(apr_status_t) ap_recent_ctime(char *date_str, apr_time_t t)
+{
+ int len = APR_CTIME_LEN;
+ return ap_recent_ctime_ex(date_str, t, AP_CTIME_OPTION_NONE, &len);
+}
+
+AP_DECLARE(apr_status_t) ap_recent_ctime_ex(char *date_str, apr_time_t t,
+ int option, int *len)
{
/* ### This code is a clone of apr_ctime(), except that it
* uses ap_explode_recent_localtime() instead of apr_time_exp_lt().
apr_time_exp_t xt;
const char *s;
int real_year;
+ int needed;
+
+
+ /* Calculate the needed buffer length */
+ if (option & AP_CTIME_OPTION_COMPACT)
+ needed = AP_CTIME_COMPACT_LEN;
+ else
+ needed = APR_CTIME_LEN;
+
+ if (option & AP_CTIME_OPTION_USEC) {
+ needed += AP_CTIME_USEC_LENGTH;
+ }
+
+ /* Check the provided buffer length */
+ if (len && *len >= needed) {
+ *len = needed;
+ }
+ else {
+ if (len != NULL) {
+ *len = 0;
+ }
+ return APR_ENOMEM;
+ }
- /* example: "Wed Jun 30 21:49:08 1993" */
- /* 123456789012345678901234 */
+ /* example without options: "Wed Jun 30 21:49:08 1993" */
+ /* 123456789012345678901234 */
+ /* example for compact format: "1993-06-30 21:49:08" */
+ /* 1234567890123456789 */
ap_explode_recent_localtime(&xt, t);
- s = &apr_day_snames[xt.tm_wday][0];
- *date_str++ = *s++;
- *date_str++ = *s++;
- *date_str++ = *s++;
- *date_str++ = ' ';
- s = &apr_month_snames[xt.tm_mon][0];
- *date_str++ = *s++;
- *date_str++ = *s++;
- *date_str++ = *s++;
- *date_str++ = ' ';
+ real_year = 1900 + xt.tm_year;
+ if (option & AP_CTIME_OPTION_COMPACT) {
+ int real_month = xt.tm_mon + 1;
+ *date_str++ = real_year / 1000 + '0';
+ *date_str++ = real_year % 1000 / 100 + '0';
+ *date_str++ = real_year % 100 / 10 + '0';
+ *date_str++ = real_year % 10 + '0';
+ *date_str++ = '-';
+ *date_str++ = real_month / 10 + '0';
+ *date_str++ = real_month % 10 + '0';
+ *date_str++ = '-';
+ }
+ else {
+ s = &apr_day_snames[xt.tm_wday][0];
+ *date_str++ = *s++;
+ *date_str++ = *s++;
+ *date_str++ = *s++;
+ *date_str++ = ' ';
+ s = &apr_month_snames[xt.tm_mon][0];
+ *date_str++ = *s++;
+ *date_str++ = *s++;
+ *date_str++ = *s++;
+ *date_str++ = ' ';
+ }
*date_str++ = xt.tm_mday / 10 + '0';
*date_str++ = xt.tm_mday % 10 + '0';
*date_str++ = ' ';
*date_str++ = ':';
*date_str++ = xt.tm_sec / 10 + '0';
*date_str++ = xt.tm_sec % 10 + '0';
- *date_str++ = ' ';
- real_year = 1900 + xt.tm_year;
- *date_str++ = real_year / 1000 + '0';
- *date_str++ = real_year % 1000 / 100 + '0';
- *date_str++ = real_year % 100 / 10 + '0';
- *date_str++ = real_year % 10 + '0';
+ if (option & AP_CTIME_OPTION_USEC) {
+ int div;
+ int usec = (int)xt.tm_usec;
+ *date_str++ = '.';
+ for (div=100000; div>0; div=div/10) {
+ *date_str++ = usec / div + '0';
+ usec = usec % div;
+ }
+ }
+ if (!(option & AP_CTIME_OPTION_COMPACT)) {
+ *date_str++ = ' ';
+ *date_str++ = real_year / 1000 + '0';
+ *date_str++ = real_year % 1000 / 100 + '0';
+ *date_str++ = real_year % 100 / 10 + '0';
+ *date_str++ = real_year % 10 + '0';
+ }
*date_str++ = 0;
return APR_SUCCESS;