diff --git a/src/tool_writeout.c b/src/tool_writeout.c
index 8023fc47ab..ac8d5434b8 100644
--- a/src/tool_writeout.c
+++ b/src/tool_writeout.c
@@ -562,18 +562,39 @@ static const char *outtime(const char *ptr, /* %time{ ... */
vlen = end - ptr;
curlx_dyn_init(&format, 1024);
- /* insert sub-seconds for %f */
- /* insert +0000 for %z because it is otherwise not portable */
- /* insert UTC for %Z because it is otherwise not portable */
+ /* Insert:
+ - sub-seconds for %f
+ - epoch seconds for %s; strftime %s uses mktime() and assumes
+ local time, which breaks UTC output on non-UTC hosts
+ - +0000 for %z because it is otherwise not portable
+ - UTC for %Z because it is otherwise not portable
+ - Keep '%%' as-is so that strftime() makes a single % out of them
+ */
for(i = 0; !result && i < vlen; i++) {
- if((i < vlen - 1) && ptr[i] == '%' &&
- ((ptr[i + 1] == 'f') || ((ptr[i + 1] | 0x20) == 'z'))) {
- if(ptr[i + 1] == 'f')
+ if((i < vlen - 1) && ptr[i] == '%') {
+ switch(ptr[i + 1]) {
+ case 'f':
result = curlx_dyn_addf(&format, "%06u", usecs);
- else if(ptr[i + 1] == 'Z')
+ break;
+ case 's': {
+ /* time_t might be either 32 or 64 bits big */
+ curl_off_t tsecs = secs;
+ result = curlx_dyn_addf(&format, "%" CURL_FORMAT_CURL_OFF_T, tsecs);
+ break;
+ }
+ case 'Z':
result = curlx_dyn_addn(&format, "UTC", 3);
- else
+ break;
+ case 'z':
result = curlx_dyn_addn(&format, "+0000", 5);
+ break;
+ case '%':
+ result = curlx_dyn_addn(&format, "%%", 2);
+ break;
+ default:
+ result = curlx_dyn_addn(&format, &ptr[i], 1);
+ continue;
+ }
i++;
}
else
diff --git a/tests/data/test1981 b/tests/data/test1981
index 9c9c1f35f1..e1fb24bf35 100644
--- a/tests/data/test1981
+++ b/tests/data/test1981
@@ -41,7 +41,7 @@ CURL_TIME=1754037103
LC_TIME=C
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --write-out='Time: %time{%d/%b/%Y %H:%M:%S.%f %z %Z}\n' -s -o %LOGDIR/dump
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --write-out='Time: %time{%d/%b/%Y %H:%M:%S.%f %z %Z%%s %s}\n' -s -o %LOGDIR/dump
@@ -55,7 +55,7 @@ Accept: */*
-Time: 01/Aug/2025 08:31:43.037103 +0000 UTC
+Time: 01/Aug/2025 08:31:43.037103 +0000 UTC%s 1754037103