Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   mktime (http://www.velocityreviews.com/forums/t955197-mktime.html)

Anders Wegge Keller 12-06-2012 02:25 PM

mktime
 

According to the C2011 draft I have available, the values in the
struct tm, passed to mktime(), are not restricted to the normalized
ranges. (2.27.2.3 §2).

Is this to be taken literally, such that any combination of values in
the tm struct, that corresponds to something that can be expressed in
a time_t is a valid input?

As I read the following paragrahp, that seem to be the case. Which
lead me to think of exxtreme cases like tm_sec, tm_min, tm_hour,
tm_mday and tm_mon all at INT_MAX, and tm_year set to a sufficiently
large negative value.

Am I missing something, or would a conforming implementation have to
handle this?

--
/Wegge

Leder efter redundant peering af dk.*,linux.debian.*

James Kuyper 12-06-2012 02:53 PM

Re: mktime
 
On 12/06/2012 09:25 AM, Anders Wegge Keller wrote:
>
> According to the C2011 draft I have available, the values in the
> struct tm, passed to mktime(), are not restricted to the normalized
> ranges. (2.27.2.3 §2).
>
> Is this to be taken literally, such that any combination of values in
> the tm struct, that corresponds to something that can be expressed in
> a time_t is a valid input?


Yes. This feature, allows performance of date arithmetic. For instance,
take a struct tm that represents 2012-12-06 09:41, subtract 7 from
tm_mday, and pass it to mktime(), which should normalize that struct to
describe 2012-11-29 09:41. This is, in fact, the main thing I've ever
used mktime() for. mktime() has to know how many days there are in each
month, which years are leap years, what day of the week each date is; so
it saves me from having to write all that logic in my own code.

> As I read the following paragrahp, that seem to be the case. Which
> lead me to think of exxtreme cases like tm_sec, tm_min, tm_hour,
> tm_mday and tm_mon all at INT_MAX, and tm_year set to a sufficiently
> large negative value.
>
> Am I missing something, or would a conforming implementation have to
> handle this?


Yes, it would.
--
James Kuyper

Eric Sosman 12-06-2012 03:11 PM

Re: mktime
 
On 12/6/2012 9:25 AM, Anders Wegge Keller wrote:
>
> According to the C2011 draft I have available, the values in the
> struct tm, passed to mktime(), are not restricted to the normalized
> ranges. (2.27.2.3 §2).


ITYM 7.27.2.3.

> Is this to be taken literally,


That's the usual way to take normative text ...

> such that any combination of values in
> the tm struct, that corresponds to something that can be expressed in
> a time_t is a valid input?


Yes, keeping in mind that time_t's range is implementation-
defined (7.27.1p4). If the tm_xxx values correspond to a time_t
value in that implementation-defined range, 7.27.2.3p3 requires
mktime() to return that time_t value.

Clearly, the intent is to relieve the programmer of the burden
of all that date arithmetic. If you've got a struct tm representing
some time T and you want to determine the time at T plus 01:23:45,
you can blithely add 1*3600+23*60+45 to the tm_sec field and call
mktime(), and mktime() will figure things out.

> As I read the following paragrahp, that seem to be the case. Which
> lead me to think of exxtreme cases like tm_sec, tm_min, tm_hour,
> tm_mday and tm_mon all at INT_MAX, and tm_year set to a sufficiently
> large negative value.
>
> Am I missing something, or would a conforming implementation have to
> handle this?


I think so. The only out I can imagine is that if mktime()
cannot determine whether Standard or Daylight time prevails, it
may be unable to find "the" corresponding time_t value and could
then return (time_t)-1 to indicate failure. But if the question
boils down to "Must mktime() be careful about overflow in its
internal computations?" I think the answer must be "Yes."

--
Eric Sosman
esosman@comcast-dot-net.invalid

Anders Wegge Keller 12-06-2012 04:40 PM

Re: mktime
 
Eric Sosman <esosman@comcast-dot-net.invalid> writes:

> On 12/6/2012 9:25 AM, Anders Wegge Keller wrote:


>> According to the C2011 draft I have available, the values in the
>> struct tm, passed to mktime(), are not restricted to the normalized
>> ranges. (2.27.2.3 §2).


> ITYM 7.27.2.3.


yes.

>> Is this to be taken literally,


> That's the usual way to take normative text ...


As for legislative works, the wording of normative standards doesn't
always mean what the un-initiated takes them to mean.

...

> then return (time_t)-1 to indicate failure. But if the question
> boils down to "Must mktime() be careful about overflow in its
> internal computations?" I think the answer must be "Yes."


I guess my question can be reduced to exactly that.

--
/Wegge

Leder efter redundant peering af dk.*,linux.debian.*

Eric Sosman 12-06-2012 07:20 PM

Re: mktime
 
On 12/6/2012 11:40 AM, Anders Wegge Keller wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>> [...]
>> then return (time_t)-1 to indicate failure. But if the question
>> boils down to "Must mktime() be careful about overflow in its
>> internal computations?" I think the answer must be "Yes."

>
> I guess my question can be reduced to exactly that.


Okay: I'm sticking with "Yes."

FWIW, PJ Plauger seems to agree (he's non-normative, but since
he served on the library subcommittee for the original ANSI Standard,
he's a pretty good indicator of intent). In "The Standard C Library"
he exhibits a sample implementation of mktime(), and in describing
its underpinnings he writes

"You can start with the year 2000, back up 2,000 months,
and advance 2 billion seconds, for example. [...] The
logic is carefully crafted to avoid integer overflow
regardless of argument values."

--
Eric Sosman
esosman@comcast-dot-net.invalid

Keith Thompson 12-06-2012 08:20 PM

Re: mktime
 
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
[...]
> Clearly, the intent is to relieve the programmer of the burden
> of all that date arithmetic. If you've got a struct tm representing
> some time T and you want to determine the time at T plus 01:23:45,
> you can blithely add 1*3600+23*60+45 to the tm_sec field and call
> mktime(), and mktime() will figure things out.

[...]

Or you can add 1 to tm_hour, 23 to tm_min, and 45 to tm_sec, and let
mktime() figure *everything* out.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson 12-06-2012 08:28 PM

Re: mktime
 
Eric Sosman <esosman@comcast-dot-net.invalid> writes:

> On 12/6/2012 11:40 AM, Anders Wegge Keller wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>> [...]
>>> then return (time_t)-1 to indicate failure. But if the question
>>> boils down to "Must mktime() be careful about overflow in its
>>> internal computations?" I think the answer must be "Yes."

>>
>> I guess my question can be reduced to exactly that.

>
> Okay: I'm sticking with "Yes."
>
> FWIW, PJ Plauger seems to agree (he's non-normative, but since
> he served on the library subcommittee for the original ANSI Standard,
> he's a pretty good indicator of intent). In "The Standard C Library"
> he exhibits a sample implementation of mktime(), and in describing
> its underpinnings he writes
>
> "You can start with the year 2000, back up 2,000 months,
> and advance 2 billion seconds, for example. [...] The
> logic is carefully crafted to avoid integer overflow
> regardless of argument values."


You can advance 2 billion seconds *if* int is at least 32 bit (tm_sec is
of type int).

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Anders Wegge Keller 12-06-2012 08:37 PM

Re: mktime
 
Keith Thompson <kst-u@mib.org> writes:

> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> [...]
> > Clearly, the intent is to relieve the programmer of the burden
> > of all that date arithmetic. If you've got a struct tm representing
> > some time T and you want to determine the time at T plus 01:23:45,
> > you can blithely add 1*3600+23*60+45 to the tm_sec field and call
> > mktime(), and mktime() will figure things out.

> [...]
>
> Or you can add 1 to tm_hour, 23 to tm_min, and 45 to tm_sec, and let
> mktime() figure *everything* out.


Yep :)

I should have thought about this possibility 10 years ago, and spared
myself a lot of trouble.

--
/Wegge

Leder efter redundant peering af dk.*,linux.debian.*

Eric Sosman 12-06-2012 10:36 PM

Re: mktime
 
On 12/6/2012 3:28 PM, Keith Thompson wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>
>> FWIW, PJ Plauger seems to agree (he's non-normative, but since
>> he served on the library subcommittee for the original ANSI Standard,
>> he's a pretty good indicator of intent). In "The Standard C Library"
>> he exhibits a sample implementation of mktime(), and in describing
>> its underpinnings he writes
>>
>> "You can start with the year 2000, back up 2,000 months,
>> and advance 2 billion seconds, for example. [...] The
>> logic is carefully crafted to avoid integer overflow
>> regardless of argument values."

>
> You can advance 2 billion seconds *if* int is at least 32 bit (tm_sec is
> of type int).


Don't complain to me; complain to the quoted author. Besides:

for (int count = 0; count < 100; ++count) {
mktime(tm);
tm->tm_sec += 20000;
}
mktime(tm);
printf("So there, nyaaah!\n");

--
Eric Sosman
esosman@comcast-dot-net.invalid

Eric Sosman 12-06-2012 10:42 PM

Re: mktime
 
On 12/6/2012 5:36 PM, Eric Sosman wrote:
> On 12/6/2012 3:28 PM, Keith Thompson wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>
>>> FWIW, PJ Plauger seems to agree (he's non-normative, but since
>>> he served on the library subcommittee for the original ANSI Standard,
>>> he's a pretty good indicator of intent). In "The Standard C Library"
>>> he exhibits a sample implementation of mktime(), and in describing
>>> its underpinnings he writes
>>>
>>> "You can start with the year 2000, back up 2,000 months,
>>> and advance 2 billion seconds, for example. [...] The
>>> logic is carefully crafted to avoid integer overflow
>>> regardless of argument values."

>>
>> You can advance 2 billion seconds *if* int is at least 32 bit (tm_sec is
>> of type int).

>
> Don't complain to me; complain to the quoted author. Besides:
>
> for (int count = 0; count < 100; ++count) {
> mktime(tm);
> tm->tm_sec += 20000;
> }
> mktime(tm);
> printf("So there, nyaaah!\n");


Oh, ratz.

for (int a = 0; a < 1000; ++a) {
for (int b = 0; b < 1000; ++b) {
mktime(tm);
tm->tm_sec += 2000;
}
}
mktime(tm);
printf("So there, this time for sure!\n");

--
Eric Sosman
esosman@comcast-dot-net.invalid


All times are GMT. The time now is 05:09 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.