I wonder if anyone knows a portable way (i.e., workable in all
ANSI C implementations) to increment a calendar time value (of
type time_t) by a certain amount. For example, given a time_t
value, how does one add (say) five seconds to it?
I know that on UNIX and most other systems time_t is defined
(typedef'd ?) to be long in <time.h>, and the value in a time_t
is usually the number of seconds since a magical moment in the
past (0:00:00, January 1 1970 being a favourite one). So to add
five seconds to a time_t would mean simply adding 5 to it. But
this implementation may not be the same on other conformant
compilers on other systems. As far as I can tell, ANSI allows
time_t to be any arithmetic type and the encoding of calendar
time in time_t can be anything the compiler implementors like.
So my conclusion at this time is that there is no portable way
to manipulate a time_t value.
Anyone has comments/suggestions/ideas/corrections?
Larry Huang, U of Waterloo
localtime/struct tm.tm_sec+=5/mktime.
---
Bill { uunet | decwrl | telesci }!twwells!bill
bi...@twwells.com
--
Brad Bobak -- bbo...@descartes.waterloo.edu
-- somewhere along the UUCP bang path
-------------------------------------------------------------------------------
"#892:ojm,n.120xa/.ajko -- Err..sorry, forgot to uncompress my sig!
The only way is to convert it to a `struct tm', adjust the tm_sec member,
and then convert back. This is unfortunately difficult with pre-ANSI
systems, on which there typically is no equivalent of mktime() to do the
back conversion.
ANSI C guarantees essentially *nothing* about the representation of time_t;
there is no portable way to do this operation on it directly.
In fact, ANSI C doesn't guarantee that time_t can resolve seconds at all.
It might encode the time only to the nearest minute.
--
I'd rather have a network file | Henry Spencer @ U of Toronto Zoology
system than NFS. -Geoff Collyer | he...@zoo.toronto.edu utzoo!henry
This is of course slow, and you might consider a #if to replace it
with a simple time += value, for some of the common encodings of
time_t.
Actually I knew about the two functions mentioned above when
posting my first message (sorry, I should have mentioned
that in my first post). My concern at that time was that
the member fields in a struct tm have range limits, in
particular, the tm_sec field has a range of [0..61]. So if
I converted a time_t to a struct tm using localtime() and
modified the fields, it would be a tedious job (though not
difficult) to get all the fields into their proper ranges
before I can pass the struct tm to mktime() to obtain the
new time_t. The worries about leap years/leap seconds etc.
would really cause some headaches. The references I had
were too short on details to reassure me that such worries
were unnecessary.
A quick flip through P.J. Plauger's "Standard C Library"
this morning shows that mktime() would take care of all the
out-of-bound fields in a struct tm. For each 60 that the
tm_sec field has in excess of 59, the tm_min field is
incremented by 1 and the 60 is subtracted from the tm_sec
field. This process is repeated for all affected fields.
So all I have to do is to add the appropriate amount (in
seconds, of course) to the tm_sec field (assuming no
overflow occurs) and mktime() will safely do the job.
A note to the one person who suggested that time_t is just
a long and one can simply add/subtract from it: that method
is not portable, better to use the library functions.
Again thanks to all those who responded.
Larry Huang.
>I wonder if anyone knows a portable way (i.e., workable in all
>ANSI C implementations) to increment a calendar time value (of
>type time_t) by a certain amount. For example, given a time_t
>value, how does one add (say) five seconds to it?
>[...]
You can use the 'localtime()' function to return a 'tm' structure. Then
increment the 'tm_sec' component by 5 (and take care of overflows) and
use the 'mktime()' function to convert back to a time_t type:
#include <time.h>
struct tm *tmPtr; /*be careful! this gets overwritten with each*/
/*call to localtime, so you may want to copy*/
/*the contents to your own tm structure*/
time_t timex;
const time_t *timexPtr = &timex;
main() {
timex = time(NULL); /*get current time*/
tmPtr = localtime(timexPtr); /*convert to tm structure*/
tmPtr->tm_sec += 5; /*increment as desired*/
if (tmPtr->tm_sec >= 60) { /*correct for overflows*/
tmPtr->tm_sec -= 60;
(tmPtr->tm_min)++;
if (tmPtr->tm_min == 60)
.
.
.
}
timex = mktime(tmPtr); /*convert back to time_t*/
}
I know this is somewhat tedious but you are guaranteed that it will
be portable to other machines.
Michael Mack
6500...@ucsbuxa.ucsb.edu
On the contrary, that practice is (highly) *portable*.
But it isn't (ANSI) *standard*.
More precisely, it will work on all Unix or POSIX systems, and on many other
systems where it was decided that adopting the Unix convention would cause
less trouble than implementing time() in the native format.
In fact, I'm not aware of *any* ANSI-conforming implementation that doesn't
measure time_t in seconds. Of course, this doesn't mean you shouldn't worry
about that case -- but I suspect that the absence of mktime() in many pre-ANSI
implementations is a worse portability problem, in practice.
You might want to use preprocessor conditionals to decide whether to interpret
time_t as a long, or as a magic cookie to be adjusted with mktime(). This
would cover both pre-ANSI Unix (for which only the former will work, assuming
you haven't supplied your own mktime()) and the hypothetical ANSI-compliant
non-Unix-native-format (for which only the latter will work). On POSIX
systems, either one is valid.
Karl W. Z. Heuer (ka...@ima.isc.com or uunet!ima!karl), The Walking Lint
>In article <1992May26....@watdragon.waterloo.edu> lhh...@jeeves.waterloo.edu (Larry Huang) writes:
>>I wonder if anyone knows a portable way (i.e., workable in all
>>ANSI C implementations) to increment a calendar time value (of
>>type time_t) by a certain amount. For example, given a time_t
>>value, how does one add (say) five seconds to it?
>>[...]
>You can use the 'localtime()' function to return a 'tm' structure. Then
>increment the 'tm_sec' component by 5 (and take care of overflows) and
>use the 'mktime()' function to convert back to a time_t type:
[Code deleted.]
Actually, as I understand the Standard, mktime() is guaranteed to reduce
its argument to canonical form before converting to a time_t. So you
can just blithely add to the seconds, minutes, months, or whatever field
you like of the tm structure, then hand it back to mktime() and be sure
of getting the right value.
--
- Craig Berry (be...@amasd.anatcp.rockwell.com)
"This sentence is true" : Epiminedes' Paradox -- NOT!
".surivorter erutangis a ma I"