A recent discussion in the tz mail-list (the list for maintaining the
Arthur D. Olson's code about timezones) raises an interesting point:
as mktime() should return (time_t)-1, should -1 be forbidden as a valid
value in the time_t range?
The general advice tends to authorize this value, but we then need a
mean to distinguish the two flavors of a (time_t)-1 return. How?
And if we use the errno mechanism, is any already-in-use <errno.h>
constant adequate for this use? Or if a new one is needed, which?
Before defining a response (in the tz code base, and therefore making
a precedent), we would like to hear the lawyers of C about these
points.
Thanks in advance for your cooperation,
Antoine Leca
Here is the (nearly full) thread:
> > > > > > > Antoine Leca <Antoin...@Renault.FR> wrote:
> > > > > > > > Comparing t with 0 doesn't take any sense (I know one system where
> > > > > > > > (time_t)0 is J2000,0, so negative t are allowed before 2000-01-01 12:00:00Z
> > > > > >
> > > > > > Markus G. Kuhn <ku...@cs.purdue.edu> answered:
> > > > > > >
> > > > > > > Ok, you are right. I just hope that the system you know does not encode
> > > > > > >
> > > > > > > 2000-01-01 11:59:59Z = (time_t) -1
> > > > > > >
> > > > > > > as this value is reserved by the standard for error conditions.
> > > > >
> > > > > to which Ken Pizzini <k...@spry.com> answered:
> > > > > >
> > > > > > A problematical situation on any implementation is distinguishing
> > > > > > between an error return from mktime() and mktime() returning a
> > > > > > legitimate -1 value. Another unpleasantness of the API. But this
> > > > > > is the only place besides time() where the C standard has a function
> > > > > > returning a time_t, and time() is not defined to have an error return.
> > > >
> > > > Tom Peterson (USG) <to...@zk3.dec.com> then wrote:
> > > > >
> > > > > An error code (or errno) would help here I think. If errno were set to a
> > > > > particular value when mktime() really couldn't represent the value, we'd have
> > > > > a way to distinguish between a valid -1 and and error -1 return value.
> > > > >
> > > > > Problem is, we'd have trouble getting the standards like X/Open to accept
> > > > > this, since they claim they don't support negative time_t's (ie: times before
> > > > > the Epoch).
> > >
> > > Antoine Leca <Antoin...@Renault.FR> answered:
> > > >
> > > > Strictly speaking, mktime() is not a X/Open standard, but part of the standard
> > > > C library. So IMHO, the solution lie more in the realm of ISO/JTC2/SC22/WG14
> > > > (the comittee in charge of C standardization) than in X/Open.
> >
> > and Tom Peterson (USG) <to...@zk3.dec.com> then answered:
> > >
> > > Good point. X/Open (or more accurately, The Open Group (TOG)), does include
> > > mktime() in their C library specification, but their definitions are a superset
> > > of the ISO/ANSI C library specs. The fact that ISO defines mktime() means any
> > > change/addition to the base interface would have to start there.
> > >
> > > (Antoine Leca)
> > > > And BTW, ISO C doesn't put any restriction on the range of the value of
> > > > the time_t (which is only arithmetical, not necessary [un]signed long int);
> > > > and Epoch does take any sense as long as ISO C is concerned.
> > >
> > (Tom Peterson)
> > > Since ISO C doesn't appear to present restrictions here and TOG says they
> > > don't support negative time_t's, perhaps this is an area where an industry
> > > precedent should be set. I've yet to see an errno defined for mktime() on
> > > other systems, but I don't see anything precluding it. Is this something we
> > > should consider adding to the tz code base?
>
> and Ken Pizzini <k...@spry.com> answered:
> >
> > The question I have to ask here is: are we working on an ANSI/ISO C
> > standard compatible interface, or a POSIX/TOG based standard? If
> > the latter we can work with the understanding that time_t values
> > represent seconds since some epoch and consider following TOG's
> > lead in saying that negative time_t values are not allowed.
> >
> > But if we are working on something that trancends POSIX compliance
> > and should work on any standard C system then I don't feel that
> > we can reasonably rule out negative time_t values -- the C
> > standard allows far too many possible underlying semanatics
> > for time_t values.
>
> > (Tom Peterson)
> > > Is there an existing errno value/macro that
> > > would fit the description of "time is not representable"?
> >
> (Ken Pizzini)
> > The best existing one I see is ERANGE, but the explanitory text
> > on this system says "Result too large", so it isn't perfect.
> > (I feel that the description has a bug myself -- a range error
> > really does encompass more than just "too large" a result.)
Antoine Leca <Antoin...@Renault.FR> wrote:
>
> As the current standard says, this seems correct. ERANGE is used
> for signaling overflowing of mathematical operations. And the
> standard explicitly says that it *could* be used for signaling
> underflows, but doesn't enforce this behavior. If your system
> don't do it, "Result too large" seems a good description to me.
>
> I don't like the idea of re-using ERANGE, because mktime() can fail
> for others reasons than excessing the available values for time_t
> (one obvious example is a time in the autumn overloapping period
> with tm->tm_isdst==-1).
> I think a new constant is in order (I don't like the idea of a new
> signaling mechanism); what about EILTIME?
>
> Furthermore, since mktime can fail for different reasons (before
> Epoch, result too large, wrong DST setting, autumn indetermination,
> spring gap; others?), perhaps can we set up different constants?
: A recent discussion in the tz mail-list (the list for maintaining the
: Arthur D. Olson's code about timezones) raises an interesting point:
: as mktime() should return (time_t)-1, should -1 be forbidden as a valid
: value in the time_t range?
The C standard does not make any explicit statement on this. It would
seem sensible that (time_t)-1 should not be expected to occur as a
real time.
: The general advice tends to authorize this value, but we then need a
: mean to distinguish the two flavors of a (time_t)-1 return. How?
: And if we use the errno mechanism, is any already-in-use <errno.h>
: constant adequate for this use? Or if a new one is needed, which?
The C standard does not require mktime to set errno on an error so this
won't work. However it does not forbid mktime from setting errno.
Note that unix implementations do set errno (I don't know if
posix requires this). From the HPUX man page for mktime:
If the calendar time cannot be represented, the
function returns the value (time_t)-1 and sets errno
to ERANGE. Note the value (time_t)-1 also
corresponds to the time 23:59:59 on Dec 31, 1969
(plus or minus time zone and Daylight Saving Time
adjustments). Thus it is necessary to check both
the return value and errno to reliably detect an
error condition.
: Before defining a response (in the tz code base, and therefore making
: a precedent), we would like to hear the lawyers of C about these
: points.
I think the thread that you quote (I have snipped it as it is a lot to
repeat) covers most of the arguments. The problem is that either the
interface to mktime needs to be changed or you place some restictions
on the implementation of time_t that are incompatible with Unix.
--
Stephen Baynes MBCS CEng Stephen...@soton.sc.philips.com
Philips Semiconductors Ltd
Southampton SO15 0DJ +44 (01703) 316431
United Kingdom My views are my own.
Do you use ISO8859-1? Yes if you see © as copyright, ÷ as division and ½ as 1/2.
>On Tue, 21 Jan 1997 08:27:22 GMT in article
><E4CnH...@ukpsshp1.serigate.philips.nl>
> bay...@ukpsshp1.serigate.philips.nl (Stephen Baynes) (Stephen Baynes) wrote:>
>>The C standard does not require mktime to set errno on an error so this
>>won't work. However it does not forbid mktime from setting errno.
Even when no error has occurred.
>>Note that unix implementations do set errno (I don't know if
>>posix requires this). From the HPUX man page for mktime:
It isn't mentioned in Lewine which is usually a good POSIX.1 reference.
>> If the calendar time cannot be represented, the
>> function returns the value (time_t)-1 and sets errno
>> to ERANGE. Note the value (time_t)-1 also
>> corresponds to the time 23:59:59 on Dec 31, 1969
>> (plus or minus time zone and Daylight Saving Time
>> adjustments). Thus it is necessary to check both
>> the return value and errno to reliably detect an
>> error condition.
>
>And, of course, in common with all library functions, this check is only valid
>if you set errno to zero before calling mktime. The value of errno is only
>meaningful after an error has occurred, and in this case you cannot know from
>the returned value whether an error has occurred.
In effect 23:59:59 on Dec 31 1969 is simply not a representable time using
this time_t representation, or at least library functions such as time() or
mktime() can't return a representation for such a time. POSIX allows time_t
to have an unsigned type so no POSIX-portable program should assume this is
representable anyway.
--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------
>In effect 23:59:59 on Dec 31 1969 is simply not a representable time using
>this time_t representation, or at least library functions such as time() or
>mktime() can't return a representation for such a time. POSIX allows time_t
>to have an unsigned type so no POSIX-portable program should assume this is
>representable anyway.
This gets us right back to the original question - can mktime() return -1 as a
valid result? I don't see anything in the standard that precludes it. It says
it returns -1 if the time cannot be represented - it does not say that -1 cannot
represent a time. Can you cite something that supports your statement?
It has always seemed to me to be a problem with the library - there are various
integer-valued functions that return -1 as an error indicator, but that value is
within the range of the function. ftell() could be another example. Most of
these problems were sorted out during the standardization process, but a few
remain, when "existing practice" couldn't be changed sufficiently. It seems to
me that the standard should be clearer in these cases.
--
Peter Curran pcu...@acm.org
>The C standard does not require mktime to set errno on an error so this
>won't work. However it does not forbid mktime from setting errno.
>Note that unix implementations do set errno (I don't know if
>posix requires this). From the HPUX man page for mktime:
>
> If the calendar time cannot be represented, the
> function returns the value (time_t)-1 and sets errno
> to ERANGE. Note the value (time_t)-1 also
> corresponds to the time 23:59:59 on Dec 31, 1969
> (plus or minus time zone and Daylight Saving Time
> adjustments). Thus it is necessary to check both
> the return value and errno to reliably detect an
> error condition.
And, of course, in common with all library functions, this check is only valid
if you set errno to zero before calling mktime. The value of errno is only
meaningful after an error has occurred, and in this case you cannot know from
the returned value whether an error has occurred.
--
Peter Curran pcu...@acm.org
>In effect 23:59:59 on Dec 31 1969 is simply not a representable time using
>this time_t representation, or at least library functions such as time() or
>mktime() can't return a representation for such a time.
Actually, in practice, those functions return -1 for that instant of time;
it's not a problem. E.g. localtime does the right thing with -1.
Now that you mention it, the C Standard doesn't seem to allow localtime
to do anything other than yield some valid struct tm * pointer when given
(time_t) -1.
Perhaps the simplest way to modify the mktime spec is to have it set
errno to ERANGE if there is an error, and to have it preserve errno if
there's not an error.
> On Tue, 21 Jan 97 22:00:18 GMT in article <853884...@genesis.demon.co.uk>
> fr...@genesis.demon.co.uk (Lawrence Kirby) (Lawrence Kirby) wrote:
>
>
> >In effect 23:59:59 on Dec 31 1969 is simply not a representable time using
> >this time_t representation, or at least library functions such as time() or
> >mktime() can't return a representation for such a time. POSIX allows time_t
> >to have an unsigned type so no POSIX-portable program should assume this is
> >representable anyway.
>
But one can get 'ctime' (in Unix systems) to produce the time string:
"23:59:59 on Dec 31 1969", by judicious use of time zone variables and
putting really low values in for seconds from the epoch. You see GMT
started the year before the USA (at least most of it, I understand that
Guam is on the other side of the date line, but I'm not really sure).
time_t is what the environment defines it to be. In Unix systems (as we
know them today) it is a 32 bit thingy. If, or not it becomes unsigned,
is a matter for those to determine before the year 2038 or so. I'll be
retired by then, but everyone will have gone thru the Y2K problem, and we
will all know what to do.
I mention this because a system I used set its start time for processes at
zero at boot time, so the swap/init processes always said 'Dec 31 1969' in
the 'ps' display. Bugged me for a while unitl I understood.
--
Tom Watson
t...@3do.com (Home: t...@johana.com)
"Result too large" is not a good description. Fortunately the standard
doesn't seem to be responsible for this one, as far as I can see :-)
"Result cannot be represented" is better and "range error" is accurate :-)
ERANGE seems appropriate when the target time cannot be represented.
> I don't like the idea of re-using ERANGE, because mktime() can fail
> for others reasons than excessing the available values for time_t
> (one obvious example is a time in the autumn overloapping period
> with tm->tm_isdst==-1).
EDOM seems appropriate for those other cases.
--
<< If this were the company's opinion, I would not be allowed to post it. >>
"I paid money for this car, I pay taxes for vehicle registration and a driver's
license, so I can drive in any lane I want, and no innocent victim gets to call
the cops just 'cause the lane's not goin' the same direction as me" - J Spammer
: >In effect 23:59:59 on Dec 31 1969 is simply not a representable time using
: >this time_t representation, or at least library functions such as time() or
: >mktime() can't return a representation for such a time. POSIX allows time_t
: >to have an unsigned type so no POSIX-portable program should assume this is
: >representable anyway.
: This gets us right back to the original question - can mktime() return -1 as a
: valid result? I don't see anything in the standard that precludes it. It says
: it returns -1 if the time cannot be represented - it does not say that -1 cannot
: represent a time. Can you cite something that supports your statement?
The original question was (or should have been) can mktime return (time_t)-1
as a valid result. As was stated in the paragraph you quote time_t can be
unsigned so (time_t)-1 might not be -1, though it often will be and in the
case being discussed, POSIX, (time_t)-1 will be -1.
The point is well taken, I see it as unanimous.
>
> I'm not convinced that there are any other valid errors. I'm not sure
> what you mean by "wrong DST setting",
If you are in USA/Canada or in Europa Union:
#include <time.h>
int main()
{
struct tm tm;
tm.tm_year = 96;
tm.tm_mon = 6;
tm.tm_mday = 4;
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
tm.tm_isdst= 0;
if( mktime(&tm)==(time_t)-1 )
perror("mktime failed!");
return 0;
}
Use tm.tm_mon=0; if you're in Australia;
If you're in Japan or in Africa, please take a plane ;-).
(and please correct obvious mistakes).
The question is, can this program outputs something?
I personally think it can, especially while reading the footnote.
> but the others you mention (spring
> gap and autumn indetermination with tm_isdst==-1) are NOT errors.
> The C standard says:
in a footnote (not normative material)
>
> "A negative value for tm_isdst causes the mktime function to attempt
> to determine whether Daylight Saving Time is in effect for the
> specified time."
(I'm not easy with English, so please excuse in advance my stupidity
if this is an odd question)
Is "to attempt" an imperative verb?
In others terms, can mktime() fail to attempt?
If it is, could/should C9X comittee consider a rewriting of this
footnote with the use of "shall attempt".
I will consider this to be able to reduce the vagueness.
>
> Thus a call to mktime() with tm_isdst = -1 must always return either the
> same as an equivalent call with tm_isdst = 0 or the same as an equivalent
> call with tm_isdst = 1. For times in the spring gap and autumn "fold"
> either one of these two values can be returned.
>
> This aspect of the behaviour of mktime() is tested in X/Open's test suite
> for XPG3 and XPG4 compliance.
Again, assuming we are in the USA/Canada or in "Central Europe"
(France, Germany, Italy, Spain; for UK, substract 1 from tm_hour).
#include <time.h>
#include <stdio.h>
int main()
{
struct tm tm;
char buf[80];
tm.tm_year = 96;
tm.tm_mon = 9;
tm.tm_mday = 27;
tm.tm_hour = 1;
tm.tm_min = 30;
tm.tm_sec = 0;
tm.tm_isdst= -1;
if( mktime(&tm)==(time_t)-1 )
perror("mktime failed!");
else {
if( strftime(buf, sizeof(buf)-1, "It outputs %c ", &tm) != 0 )
fputs(buf, stdout);
else
fputs("strftime failed ", stdout);
if( tm.tm_isdst<0 )
perror("tm_isdst still negative!");
else
if( tm.tm_isdst==0 )
puts("Winter time");
else /*if( tm.tm_isdst>0 )*/
puts("Summer time");
}
return 0;
}
What you are saying is that a conforming implementation can't call
perror() while executing this program?
(short of having range problems for time_t, of course).
Seems very funny to me, but if you are right, I'm very sorry for
annoying all the people here in comp.std.c with my studity.
Antoine
>In article <5c3ine$7...@news.inforamp.net>, See...@bottom.msg wrote:
>
>> On Tue, 21 Jan 97 22:00:18 GMT in article <853884...@genesis.demon.co.uk>
>> fr...@genesis.demon.co.uk (Lawrence Kirby) (Lawrence Kirby) wrote:
>>
>>
>> >In effect 23:59:59 on Dec 31 1969 is simply not a representable time using
>> >this time_t representation, or at least library functions such as time() or
>> >mktime() can't return a representation for such a time. POSIX allows time_t
>> >to have an unsigned type so no POSIX-portable program should assume this is
>> >representable anyway.
>>
>
>But one can get 'ctime' (in Unix systems) to produce the time string:
>"23:59:59 on Dec 31 1969", by judicious use of time zone variables and
>putting really low values in for seconds from the epoch. You see GMT
>started the year before the USA (at least most of it, I understand that
>Guam is on the other side of the date line, but I'm not really sure).
Well, yes, I mean GMT or UTC or whatever the equivalent point in time would
have been had these things been in operation in 1969.
>time_t is what the environment defines it to be. In Unix systems (as we
>know them today) it is a 32 bit thingy. If, or not it becomes unsigned,
>is a matter for those to determine before the year 2038 or so. I'll be
>retired by then, but everyone will have gone thru the Y2K problem, and we
>will all know what to do.
AFAIK POSIX makes the same requirements about the type of time_t as the C
standard, it just says more about the representation. I believe that
makeing it unsigned is quite common on Unix systems. However I'm sure it
will become, to all intents and purposes, at least a 64 bit thingy well
before 2038. I suspect it will be a signed 64 bit thingy! :-)
>The C standard does not require mktime to set errno on an error so this
>won't work. However it does not forbid mktime from setting errno.
>Note that unix implementations do set errno (I don't know if
>posix requires this). From the HPUX man page for mktime:
POSIX doesn't require it (at least that's how Lewine documents it and the
Unix system I have here doesn't set errno).
> If the calendar time cannot be represented, the
> function returns the value (time_t)-1 and sets errno
> to ERANGE. Note the value (time_t)-1 also
> corresponds to the time 23:59:59 on Dec 31, 1969
> (plus or minus time zone and Daylight Saving Time
> adjustments). Thus it is necessary to check both
> the return value and errno to reliably detect an
> error condition.
The problem is that this is non-portable. On a system that never sets errno
this will never see an error condition.
>: This gets us right back to the original question - can mktime() return -1 as a>: valid result? I don't see anything in the standard that precludes it. It
> says
>: it returns -1 if the time cannot be represented - it does not say that -1
> cannot
>: represent a time. Can you cite something that supports your statement?
The standard says "The value (time_t)-1 is returned if the calendar time is
not available". Since there is no means defined to distinguish this from
a valid date value, this is all that (time_t)-1 returned from time() can
mean. Of course on other contexts (such as being passe to localtime() )
(time_t)-1 can represent a date. This could result in it converting the
right date (i.e. the one that time() couldn't return) by accident. However
that only works in one case, ther dates that time() can't return will be
converted incorrectly by localtime().
>The original question was (or should have been) can mktime return (time_t)-1
>as a valid result. As was stated in the paragraph you quote time_t can be
>unsigned so (time_t)-1 might not be -1, though it often will be and in the
>case being discussed, POSIX, (time_t)-1 will be -1.
POSIX permits time_t to be unsigned.
Can you please explain to me why. (This is for my enlightment).
Thanks in advance for your answer.
> "Result cannot be represented" is better and "range error" is accurate :-)
> ERANGE seems appropriate when the target time cannot be represented.
>
> > I don't like the idea of re-using ERANGE, because mktime() can fail
> > for others reasons than excessing the available values for time_t
> > (one obvious example is a time in the autumn overloapping period
> > with tm->tm_isdst==-1).
>
> EDOM seems appropriate for those other cases.
OK.
Another question I had: Should this be enforced/recommanded by the
standard (perhaps a new redaction in C9X), or do you consider it
to be only a matter of quality-of-implementation.
I will appreciate any advice in this issue.
Thanks for your response,
Antoine
>> >> Furthermore, since mktime can fail for different reasons
> tm.tm_year = 96;
> tm.tm_mon = 6;
> tm.tm_mday = 4;
> tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
> tm.tm_isdst= 0;
> if( mktime(&tm)==(time_t)-1 )
> perror("mktime failed!");
I don't think mktime should fail in this case. mktime is often used for
date arithmetic (in fact it is the only means of doing this portably),
so crossing a DST switch should not cause mktime to fail. This is
probably a quality of implementation issue, though.
hp
--
_ | Peter J. Holzer | If I were God, or better yet
|_|_) | Sysadmin WSR | Linus, I would ...
| | | h...@wsr.ac.at | -- Bill Davidsen
__/ | http://wsrx.wsr.ac.at/~hjp/ | (davi...@tmr.com)