Bug 30321 - [patch] strftime(3) '%s' format does not work properly
Summary: [patch] strftime(3) '%s' format does not work properly
Status: Closed Unable to Reproduce
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 4.3-RELEASE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2001-09-04 22:10 UTC by Archie Cobbs
Modified: 2019-01-22 19:10 UTC (History)
2 users (show)

See Also:


Attachments
file.diff (477 bytes, patch)
2001-09-04 22:10 UTC, Archie Cobbs
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Archie Cobbs 2001-09-04 22:10:01 UTC
	The strftime(3) '%s' format is supposed to convert a
	'struct tm' into the number of seconds since the epoch
	(1/1/70 GMT).

	When it does this conversion, it uses the currently set
	system time zone instead of using the time zone from the
	'struct tm' argument. Therefore, if the two timezones are
	different, incorrect results are computed.

Fix: I think this should fix it. From the timegm(3) man
	page, "The tm_isdst and tm_gmtoff members are forced
	to zero by timegm()" which I guess means that the
	value of 'tm_gmtoff' is added into the computation
	before being forced to zero.
How-To-Repeat: 
	Run this program with your system time zone set to
	any timezone other than GMT. Notice that the value
	printed for "now" is different before and after the
	converstion.

	#include <sys/types.h>
	#include <sys/time.h>
	#include <stdio.h>
	#include <stdlib.h>
	#include <unistd.h>
	#include <time.h>

	int
	main(int ac, char **av)
	{
		time_t now;
		char buf[32];

		now = time(NULL);
		printf("now = %lu\n", (u_long)now);
		strftime(buf, sizeof(buf), "%s", gmtime(&now));
		printf("now = %s\n", buf);
		return (0);
	}
Comment 1 Garrett A. Wollman 2001-09-04 22:52:18 UTC
<<On Tue, 4 Sep 2001 14:01:02 -0700 (PDT), Archie Cobbs <archie@packetdesign.com> said:

> 	When it does this conversion, it uses the currently set
> 	system time zone instead of using the time zone from the
> 	'struct tm' argument. Therefore, if the two timezones are
> 	different, incorrect results are computed.

This behavior is correct.  In the general case, as codified in the ISO
C standard, `struct tm' does not contain time zone information.  ISO C
functions such as strftime() are specified to use the system's time
zone.

Having said that, `%s' is not specified in either POSIX or ISO C, so
we are free to make it mean anything we want.

-GAWollman
Comment 2 Archie Cobbs 2001-09-05 00:42:38 UTC
Garrett Wollman wrote:
> >       When it does this conversion, it uses the currently set
> >       system time zone instead of using the time zone from the
> >       'struct tm' argument. Therefore, if the two timezones are
> >       different, incorrect results are computed.
> 
> This behavior is correct.  In the general case, as codified in the ISO
> C standard, `struct tm' does not contain time zone information.  ISO C
> functions such as strftime() are specified to use the system's time
> zone.

The current behavior of '%s' is inconsistent with every other
format character supported by strftime(3). For example, if you
use '%z' you get the time zone offset read directly from the struct tm;
the system time zone has no effect on that conversion whatsoever.
Same for '%H', etc.

So at best, it violates POLA and is bizarre, undocumented behavior.

-Archie

__________________________________________________________________________
Archie Cobbs     *     Packet Design     *     http://www.packetdesign.com
Comment 3 Garrett A. Wollman 2001-09-05 01:46:42 UTC
<<On Tue, 04 Sep 2001 16:42:38 -0700, Archie Cobbs <archie@packetdesign.com> said:

> For example, if you use '%z' you get the time zone offset read
> directly from the struct tm; the system time zone has no effect on
> that conversion whatsoever.

This is a bug.  POSIX says that ``Local timezone information is used
as though strftime( ) called tzset( ).''  POSIX does not appear to
permit the implementation to require initialization of non-standard
fields in `struct tm' for strftime() to work.  I would interpret the
specification as requiring that strftime() always use the ``system''
timezone.  In order for our implementation to meet the specification,
we need to call mktime() on a copy of the input structure in order to
determine the timezone to generate for `%z' and `%Z'.

-GAWollman
Comment 4 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 07:59:41 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped
Comment 5 Yuri Pankov 2018-10-13 22:22:54 UTC
(17 years later) this behavior now looks like being there forever, and glibc agrees, likely we can close this?
Comment 6 David Bright freebsd_committer freebsd_triage 2019-01-22 19:10:40 UTC
Works for me, at least in 12.0-RELEASE