diff -rup nginx-0.7.61/src/http/modules/ngx_http_log_module.c ./src/http/modules/ngx_http_log_module.c
--- nginx-0.7.61/src/http/modules/ngx_http_log_module.c	2009-04-27 09:55:53.000000000 +0000
+++ ./src/http/modules/ngx_http_log_module.c	2009-08-24 23:25:18.000000000 +0000
@@ -30,6 +30,11 @@ typedef struct {
     ngx_str_t                   name;
     ngx_array_t                *flushes;
     ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
+
+    ngx_str_t                   time_custom_buf;
+    u_char                     *time_custom_fmt;
+    time_t                      time_custom_sec;
+    int                         time_custom_msec_pos;
 } ngx_http_log_fmt_t;
 
 
@@ -69,6 +74,7 @@ typedef struct {
     ngx_str_t                   name;
     size_t                      len;
     ngx_http_log_op_run_pt      run;
+    ngx_http_log_op_getlen_pt   getlen;
 } ngx_http_log_var_t;
 
 
@@ -83,6 +89,9 @@ static u_char *ngx_http_log_pipe(ngx_htt
     ngx_http_log_op_t *op);
 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
+static size_t ngx_http_log_time_custom_getlen(ngx_http_request_t *r, uintptr_t data);
+static u_char *ngx_http_log_time_custom(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
 static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
 static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
@@ -105,6 +114,7 @@ static u_char *ngx_http_log_variable(ngx
 static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
 
 
+static char *ngx_http_log_set_time_custom_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
 static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
 static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
@@ -114,7 +124,7 @@ static char *ngx_http_log_set_log(ngx_co
 static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 static char *ngx_http_log_compile_format(ngx_conf_t *cf,
-    ngx_array_t *flushes, ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);
+    ngx_http_log_fmt_t *fmt, int skip_flushes, ngx_array_t *args, ngx_uint_t s);
 static char *ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
@@ -129,6 +139,13 @@ static ngx_command_t  ngx_http_log_comma
       0,
       NULL },
 
+    { ngx_string("time_custom_format"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      ngx_http_log_set_time_custom_format,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
     { ngx_string("access_log"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
                         |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123,
@@ -189,26 +206,77 @@ static ngx_str_t  ngx_http_combined_fmt 
 
 
 static ngx_http_log_var_t  ngx_http_log_vars[] = {
-    { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection },
-    { ngx_string("pipe"), 1, ngx_http_log_pipe },
+    { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection, NULL },
+    { ngx_string("pipe"), 1, ngx_http_log_pipe, NULL },
     { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
-                          ngx_http_log_time },
-    { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec },
+                          ngx_http_log_time, NULL },
+    { ngx_string("time_custom"), 0,
+                          ngx_http_log_time_custom, ngx_http_log_time_custom_getlen },
+    { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec, NULL },
     { ngx_string("request_time"), NGX_TIME_T_LEN + 4,
-                          ngx_http_log_request_time },
-    { ngx_string("status"), 3, ngx_http_log_status },
-    { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent },
+                          ngx_http_log_request_time, NULL },
+    { ngx_string("status"), 3, ngx_http_log_status, NULL },
+    { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent, NULL },
     { ngx_string("body_bytes_sent"), NGX_OFF_T_LEN,
-                          ngx_http_log_body_bytes_sent },
+                          ngx_http_log_body_bytes_sent, NULL },
     { ngx_string("apache_bytes_sent"), NGX_OFF_T_LEN,
-                          ngx_http_log_body_bytes_sent },
+                          ngx_http_log_body_bytes_sent, NULL },
     { ngx_string("request_length"), NGX_SIZE_T_LEN,
-                          ngx_http_log_request_length },
+                          ngx_http_log_request_length, NULL },
 
-    { ngx_null_string, 0, NULL }
+    { ngx_null_string, 0, NULL, NULL }
 };
 
 
+static void
+cache_time_custom(ngx_http_log_fmt_t *log_fmt)
+{
+    ngx_time_t *tp = ngx_timeofday();
+
+    if (tp->sec != log_fmt->time_custom_sec) {
+        char timebuf[1024];
+        int len;
+        struct tm tm;
+
+        ngx_libc_localtime(tp->sec, &tm);
+        len = strftime(timebuf, sizeof timebuf, (char *) log_fmt->time_custom_fmt, &tm);
+        if (len <= 0) {
+            ngx_str_t fail = ngx_string("strftime() failed");
+            ngx_memcpy(timebuf, fail.data, fail.len+1);
+            len = fail.len;
+        }
+
+        if ((size_t) len != log_fmt->time_custom_buf.len) {
+            if (log_fmt->time_custom_buf.len)
+                free(log_fmt->time_custom_buf.data);
+            log_fmt->time_custom_buf.data = malloc(len+1);
+            if (!log_fmt->time_custom_buf.data) {
+                log_fmt->time_custom_buf.len = 0;
+                return;
+            }
+            log_fmt->time_custom_buf.data[len] = '\0';
+            log_fmt->time_custom_buf.len = len;
+        }
+
+        ngx_memcpy(log_fmt->time_custom_buf.data, timebuf, len);
+        log_fmt->time_custom_sec = tp->sec;
+
+        if (log_fmt->time_custom_msec_pos >= 0
+         && ((size_t) log_fmt->time_custom_msec_pos >= log_fmt->time_custom_buf.len
+          || log_fmt->time_custom_buf.data[log_fmt->time_custom_msec_pos] != '$')) {
+            u_char *cp = (u_char *) ngx_strchr(log_fmt->time_custom_buf.data, '$');
+            if (cp == NULL)
+                log_fmt->time_custom_msec_pos = -1;
+            else
+                log_fmt->time_custom_msec_pos = cp - log_fmt->time_custom_buf.data;
+        }
+    }
+
+    if (log_fmt->time_custom_msec_pos >= 0)
+        ngx_sprintf(log_fmt->time_custom_buf.data + log_fmt->time_custom_msec_pos, "%03M", tp->msec);
+}
+
+
 ngx_int_t
 ngx_http_log_handler(ngx_http_request_t *r)
 {
@@ -245,6 +313,10 @@ ngx_http_log_handler(ngx_http_request_t 
 
         ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);
 
+        /* Make sure the time is up-to-date. */
+        if (log[l].format->time_custom_fmt)
+            cache_time_custom(log[l].format);
+
         len = 0;
         op = log[l].format->ops->elts;
         for (i = 0; i < log[l].format->ops->nelts; i++) {
@@ -511,6 +583,33 @@ ngx_http_log_time(ngx_http_request_t *r,
 }
 
 
+static size_t
+ngx_http_log_time_custom_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_http_log_fmt_t *fmt;
+    
+    fmt = (ngx_http_log_fmt_t *) data;
+
+    return fmt->time_custom_buf.len;
+}
+
+
+static u_char *
+ngx_http_log_time_custom(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    ngx_http_log_fmt_t *fmt;
+    
+    fmt = (ngx_http_log_fmt_t *) op->data;
+
+    if (!fmt->time_custom_buf.len)
+        return buf;
+
+    ngx_memcpy(buf, fmt->time_custom_buf.data, fmt->time_custom_buf.len);
+
+    return buf + fmt->time_custom_buf.len;
+}
+
+
 static u_char *
 ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
 {
@@ -705,6 +804,57 @@ ngx_http_log_escape(u_char *dst, u_char 
 }
 
 
+static char *
+ngx_http_log_set_time_custom_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_uint_t                  i;
+    ngx_str_t                  *value, name;
+    ngx_http_log_fmt_t         *log_fmt;
+    ngx_http_log_main_conf_t   *lmcf;
+    u_char                     *time_fmt, *dollar;
+    
+    value = cf->args->elts;
+
+    lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
+
+    name = value[1];
+    log_fmt = lmcf->formats.elts;
+    for (i = 0; i < lmcf->formats.nelts; i++, log_fmt++) {
+        if (log_fmt->name.len == name.len && ngx_strcasecmp(log_fmt->name.data, name.data) == 0)
+            goto buffer;
+    }
+
+    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unknown log format \"%V\"", &name);
+    return NGX_CONF_ERROR;
+
+buffer:
+
+    if (!value[2].len)
+        time_fmt = NULL;
+    else {
+        value[2].len++; /* duplicate the trailing null too */
+        time_fmt = ngx_pstrdup(cf->pool, &value[2]); /* TODO: is this needed? */
+        if (time_fmt == NULL)
+            return NGX_CONF_ERROR;
+    }
+
+    log_fmt->time_custom_fmt = time_fmt;
+
+    log_fmt->time_custom_sec = (time_t)-1;
+
+    if ((dollar = (u_char *) ngx_strchr(time_fmt, '$')) != NULL) {
+        if (dollar[1] != 'm' || dollar[2] != 's' || ngx_strchr(dollar+1, '$') != NULL) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "The only $ in a time_custom_format must be a $ms reference");
+            return NGX_CONF_ERROR;
+        }
+        log_fmt->time_custom_msec_pos = 0; /* This is adjusted later. */
+    } else
+        log_fmt->time_custom_msec_pos = -1;
+
+    return NGX_CONF_OK;
+}
+
+
 static void *
 ngx_http_log_create_main_conf(ngx_conf_t *cf)
 {
@@ -1002,13 +1152,13 @@ ngx_http_log_set_format(ngx_conf_t *cf, 
         return NGX_CONF_ERROR;
     }
 
-    return ngx_http_log_compile_format(cf, fmt->flushes, fmt->ops, cf->args, 2);
+    return ngx_http_log_compile_format(cf, fmt, 0, cf->args, 2);
 }
 
 
 static char *
-ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
-    ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s)
+ngx_http_log_compile_format(ngx_conf_t *cf, ngx_http_log_fmt_t *fmt,
+    int skip_flushes, ngx_array_t *args, ngx_uint_t s)
 {
     u_char              *data, *p, ch;
     size_t               i, len;
@@ -1045,7 +1195,7 @@ ngx_http_log_compile_format(ngx_conf_t *
 
         while (i < value[s].len) {
 
-            op = ngx_array_push(ops);
+            op = ngx_array_push(fmt->ops);
             if (op == NULL) {
                 return NGX_CONF_ERROR;
             }
@@ -1115,9 +1265,9 @@ ngx_http_log_compile_format(ngx_conf_t *
                         && ngx_strncmp(v->name.data, var.data, var.len) == 0)
                     {
                         op->len = v->len;
-                        op->getlen = NULL;
+                        op->getlen = v->getlen;
                         op->run = v->run;
-                        op->data = 0;
+                        op->data = v->getlen ? (uintptr_t) fmt : 0;
 
                         goto found;
                     }
@@ -1127,9 +1277,9 @@ ngx_http_log_compile_format(ngx_conf_t *
                     return NGX_CONF_ERROR;
                 }
 
-                if (flushes) {
+                if (fmt->flushes && !skip_flushes) {
 
-                    flush = ngx_array_push(flushes);
+                    flush = ngx_array_push(fmt->flushes);
                     if (flush == NULL) {
                         return NGX_CONF_ERROR;
                     }
@@ -1322,9 +1472,7 @@ ngx_http_log_init(ngx_conf_t *cf)
         *value = ngx_http_combined_fmt;
         fmt = lmcf->formats.elts;
 
-        if (ngx_http_log_compile_format(cf, NULL, fmt->ops, &a, 0)
-            != NGX_CONF_OK)
-        {
+        if (ngx_http_log_compile_format(cf, fmt, 1, &a, 0) != NGX_CONF_OK) {
             return NGX_ERROR;
         }
     }
