MINOR: log: add '%Tl' to log-format

The '%Tl' is similar to '%T', but using local timezone.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index acf3099..949a383 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -10056,6 +10056,7 @@
   |   | %Sp  | server_port                                   | numeric     |
   |   | %T   | gmt_date_time                                 | date        |
   |   | %Tc  | Tc                                            | numeric     |
+  |   | %Tl  | local_date_time                               | date        |
   | H | %Tq  | Tq                                            | numeric     |
   | H | %Tr  | Tr                                            | numeric     |
   |   | %Ts  | timestamp                                     | numeric     |
diff --git a/include/common/standard.h b/include/common/standard.h
index ff87cd1..4813065 100644
--- a/include/common/standard.h
+++ b/include/common/standard.h
@@ -676,6 +676,9 @@
 
 extern const char *monthname[];
 
+/* numeric timezone (that is, the hour and minute offset from UTC) */
+char localtimezone[6];
+
 /* date2str_log: write a date in the format :
  * 	sprintf(str, "%02d/%s/%04d:%02d:%02d:%02d.%03d",
  *		tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
@@ -693,6 +696,13 @@
  */
 char *gmt2str_log(char *dst, struct tm *tm, size_t size);
 
+/* localdate2str_log: write a date in the format :
+ * "%02d/%s/%04d:%02d:%02d:%02d +0000(local timezone)" without using snprintf
+ * return a pointer to the last char written (\0) or
+ * NULL if there isn't enough space.
+ */
+char *localdate2str_log(char *dst, struct tm *tm, size_t size);
+
 /* Dynamically allocates a string of the proper length to hold the formatted
  * output. NULL is returned on error. The caller is responsible for freeing the
  * memory area using free(). The resulting string is returned in <out> if the
diff --git a/include/types/log.h b/include/types/log.h
index 8c28310..ce0c717 100644
--- a/include/types/log.h
+++ b/include/types/log.h
@@ -57,6 +57,7 @@
 	LOG_FMT_PID,
 	LOG_FMT_DATE,
 	LOG_FMT_DATEGMT,
+	LOG_FMT_DATELOCAL,
 	LOG_FMT_TS,
 	LOG_FMT_MS,
 	LOG_FMT_FRONTEND,
diff --git a/src/haproxy.c b/src/haproxy.c
index bfbcb32..e252032 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -402,6 +402,7 @@
 	struct wordlist *wl;
 	char *progname;
 	char *change_dir = NULL;
+	struct tm curtime;
 
 	trash = malloc(global.tune.bufsize);
 
@@ -428,6 +429,10 @@
 	tv_update_date(-1,-1);
 	start_date = now;
 
+	/* Get the numeric timezone. */
+	get_localtime(start_date.tv_sec, &curtime);
+	strftime(localtimezone, 6, "%z", &curtime);
+
 	signal_init();
 	init_task();
 	init_session();
diff --git a/src/log.c b/src/log.c
index 752f275..79158e0 100644
--- a/src/log.c
+++ b/src/log.c
@@ -80,6 +80,7 @@
 	{ "Si", LOG_FMT_SERVERIP, PR_MODE_TCP, LW_SVIP, NULL }, /* server destination ip */
 	{ "t", LOG_FMT_DATE, PR_MODE_TCP, LW_INIT, NULL },      /* date */
 	{ "T", LOG_FMT_DATEGMT, PR_MODE_TCP, LW_INIT, NULL },   /* date GMT */
+	{ "Tl", LOG_FMT_DATELOCAL, PR_MODE_TCP, LW_INIT, NULL },   /* date local timezone */
 	{ "Ts", LOG_FMT_TS, PR_MODE_TCP, LW_INIT, NULL },   /* timestamp GMT */
 	{ "ms", LOG_FMT_MS, PR_MODE_TCP, LW_INIT, NULL },       /* accept date millisecond */
 	{ "f", LOG_FMT_FRONTEND, PR_MODE_TCP, LW_INIT, NULL },  /* frontend */
@@ -943,6 +944,15 @@
 				last_isspace = 0;
 				break;
 
+			case LOG_FMT_DATELOCAL: // %Tl
+				get_localtime(s->logs.accept_date.tv_sec, &tm);
+				ret = localdate2str_log(tmplog, &tm, dst + maxsize - tmplog);
+				if (ret == NULL)
+					goto out;
+				tmplog = ret;
+				last_isspace = 0;
+				break;
+
 			case LOG_FMT_TS: // %Ts
 				get_gmtime(s->logs.accept_date.tv_sec, &tm);
 				if (tmp->options & LOG_OPT_HEXA) {
diff --git a/src/standard.c b/src/standard.c
index c26d7a0..10c25a3 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -1730,7 +1730,7 @@
  */
 char *gmt2str_log(char *dst, struct tm *tm, size_t size)
 {
-	if (size < 27) /* the size is fixed: 24 chars + \0 */
+	if (size < 27) /* the size is fixed: 26 chars + \0 */
 		return NULL;
 
 	dst = utoa_pad((unsigned int)tm->tm_mday, dst, 3); // day
@@ -1756,6 +1756,36 @@
 	return dst;
 }
 
+/* localdate2str_log: write a date in the format :
+ * "%02d/%s/%04d:%02d:%02d:%02d +0000(local timezone)" without using snprintf
+ * * return a pointer to the last char written (\0) or
+ * * NULL if there isn't enough space.
+ */
+char *localdate2str_log(char *dst, struct tm *tm, size_t size)
+{
+	if (size < 27) /* the size is fixed: 26 chars + \0 */
+		return NULL;
+
+	dst = utoa_pad((unsigned int)tm->tm_mday, dst, 3); // day
+	*dst++ = '/';
+	memcpy(dst, monthname[tm->tm_mon], 3); // month
+	dst += 3;
+	*dst++ = '/';
+	dst = utoa_pad((unsigned int)tm->tm_year+1900, dst, 5); // year
+	*dst++ = ':';
+	dst = utoa_pad((unsigned int)tm->tm_hour, dst, 3); // hour
+	*dst++ = ':';
+	dst = utoa_pad((unsigned int)tm->tm_min, dst, 3); // minutes
+	*dst++ = ':';
+	dst = utoa_pad((unsigned int)tm->tm_sec, dst, 3); // secondes
+	*dst++ = ' ';
+	memcpy(dst, localtimezone, 5); // timezone
+	dst += 5;
+	*dst = '\0';
+
+	return dst;
+}
+
 /* Dynamically allocates a string of the proper length to hold the formatted
  * output. NULL is returned on error. The caller is responsible for freeing the
  * memory area using free(). The resulting string is returned in <out> if the