How to compute time into integer?

H

Huey

Hi All,

I need to compute the current time value in seconds: the current time
is 12/16/2003, and it's time value in integer should around 1071560616
seconds since 1/1/1970. It is easy to get such a value in Tcl, but i
noticed it is uneasy to do in C. Well, ANSI provides functions such as
time(), asctime(), localtime(), gmtime(), ctime() in time.h file. But,
I can't convert the returns into integer in seconds.

I did think of the way as computing by:

year*365 + month * 12 + day *24 + .....

with the values derived from struct tm members. but I can't handle
the leap year and leap month well. Anybody can help? Thanks!


Huey
 
R

Robert Stankowic

Huey said:
Hi All,

I need to compute the current time value in seconds: the current time
is 12/16/2003, and it's time value in integer should around 1071560616
seconds since 1/1/1970. It is easy to get such a value in Tcl, but i
noticed it is uneasy to do in C. Well, ANSI provides functions such as
time(), asctime(), localtime(), gmtime(), ctime() in time.h file. But,
I can't convert the returns into integer in seconds.

I did think of the way as computing by:

year*365 + month * 12 + day *24 + .....

Assuming your input is in the format mm/dd/yyyy:
Checks, necessary headers and calling function omitted, may/must be expanded
eventually to handle hours, minutes and seconds as well as daylight saving.
I suggest you read the description of a struct tm carefully :)

time_t StringToTimestamp(const char *time_string)
{
struct tm time_in = {0};
char *tmp = NULL;

time_in.tm_year = strtoul(time_string + 6, &tmp, 10) - 1900;
time_in.tm_mon = strtoul(time_string, &tmp, 10) - 1;
time_in.tm_mday = strtoul(time_string + 3, &tmp, 10);
/* Convert the date in seconds (since 1/1/1970) */
return mktime(&time_in);
} /* StringToTimestamp */

HTH
Robert
 
N

nrk

Huey said:
Hi All,

I need to compute the current time value in seconds: the current time
is 12/16/2003, and it's time value in integer should around 1071560616
seconds since 1/1/1970. It is easy to get such a value in Tcl, but i
noticed it is uneasy to do in C. Well, ANSI provides functions such as
time(), asctime(), localtime(), gmtime(), ctime() in time.h file. But,
I can't convert the returns into integer in seconds.

I did think of the way as computing by:

year*365 + month * 12 + day *24 + .....

with the values derived from struct tm members. but I can't handle
the leap year and leap month well. Anybody can help? Thanks!


Huey

Here's one way:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(void) {
struct tm epoch_strt;
time_t basetime;
time_t curtime;
double nsecs;

epoch_strt.tm_sec = 0;
epoch_strt.tm_min = 0;
epoch_strt.tm_hour = 0;
epoch_strt.tm_mday = 1;
epoch_strt.tm_mon = 1;
epoch_strt.tm_year = 70;
epoch_strt.tm_isdst = -1;

basetime = mktime(&epoch_strt);
if ( basetime == (time_t)-1 ) {
fprintf(stderr, "Cannot convert time\n");
exit(EXIT_FAILURE);
}

curtime = time(NULL);
if ( curtime == (time_t)-1 ) {
fprintf(stderr, "Cannot get current time\n");
exit(EXIT_FAILURE);
}

nsecs = difftime(curtime, basetime);

printf("Seconds since start of epoch: %.0f\n", nsecs);

return 0;
}

-nrk.
 
N

nrk

Robert said:
Assuming your input is in the format mm/dd/yyyy:
Checks, necessary headers and calling function omitted, may/must be
expanded eventually to handle hours, minutes and seconds as well as
daylight saving. I suggest you read the description of a struct tm
carefully :)

time_t StringToTimestamp(const char *time_string)
{
struct tm time_in = {0};
char *tmp = NULL;

time_in.tm_year = strtoul(time_string + 6, &tmp, 10) - 1900;
time_in.tm_mon = strtoul(time_string, &tmp, 10) - 1;
time_in.tm_mday = strtoul(time_string + 3, &tmp, 10);
/* Convert the date in seconds (since 1/1/1970) */
return mktime(&time_in);
} /* StringToTimestamp */

HTH
Robert

Is the return of mktime guaranteed to be seconds since epoch?

-nrk.
 
M

Martin Dickopp

nrk said:
Is the return of mktime guaranteed to be seconds since epoch?

No. 7.23.1#4: "The range and precision of times representable in clock_t
and time_t are implementation-defined. [...]"

<OT>
Even on systems where time_t does represent the seconds since epoch, it is
not guaranteed to take leap seconds into account (which may or may not be
a problem).
</OT>

Martin
 
C

CBFalconer

Huey said:
I need to compute the current time value in seconds: the current
time is 12/16/2003, and it's time value in integer should around
1071560616 seconds since 1/1/1970. It is easy to get such a value
in Tcl, but i noticed it is uneasy to do in C. Well, ANSI provides
functions such as time(), asctime(), localtime(), gmtime(),
ctime() in time.h file. But, I can't convert the returns into
integer in seconds.

I did think of the way as computing by:

year*365 + month * 12 + day *24 + .....

with the values derived from struct tm members. but I can't
handle the leap year and leap month well.

Ignoring leapseconds, and restricting the range to 1901 .. 2099,
start by considering quadyears of 1461 days, deltayears in the
range 0..3, followed by months, days, hours, etc. You will need
two tables of monthlength versus month.

It may be convenient to do as did the Romans, and consider the
year to begin in March.
 
B

Ben Pfaff

I need to compute the current time value in seconds: the current time
is 12/16/2003, and it's time value in integer should around 1071560616
seconds since 1/1/1970. It is easy to get such a value in Tcl, but i
noticed it is uneasy to do in C. Well, ANSI provides functions such as
time(), asctime(), localtime(), gmtime(), ctime() in time.h file. But,
I can't convert the returns into integer in seconds.

Commonly, time_t is a count of seconds from 1970. You can't
depend on this portably, but it's true on many systems. This is
probably what Tcl is using.
 
P

Peter Slootweg

nrk said:
Here's one way:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(void) {
struct tm epoch_strt;
time_t basetime;
time_t curtime;
double nsecs;

epoch_strt.tm_sec = 0;
epoch_strt.tm_min = 0;
epoch_strt.tm_hour = 0;
epoch_strt.tm_mday = 1;
epoch_strt.tm_mon = 1;
epoch_strt.tm_year = 70;
epoch_strt.tm_isdst = -1;

basetime = mktime(&epoch_strt);
if ( basetime == (time_t)-1 ) {
fprintf(stderr, "Cannot convert time\n");
exit(EXIT_FAILURE);
}

curtime = time(NULL);
if ( curtime == (time_t)-1 ) {
fprintf(stderr, "Cannot get current time\n");
exit(EXIT_FAILURE);
}

nsecs = difftime(curtime, basetime);

printf("Seconds since start of epoch: %.0f\n", nsecs);

return 0;
}

-nrk.
almost
shouldn't it be?
epoch_strt.tm_mon = 0;
 
D

Dave Thompson

Commonly, time_t is a count of seconds from 1970. You can't
depend on this portably, but it's true on many systems. This is
probably what Tcl is using.

Note that mktime() converts *local* time in struct tm (including DST
if applicable) called "broken down", to *UTC* time in time_t, which is
(as you say) almost always seconds from 1970-01-01midnight though that
is not actually required by the standard. (UTC is often referred to as
GMT, for example in the name of gmtime(), although technically that is
very slightly different.)

If this distinction matters to you, you may be able to set the (local)
timezone to UTC before using the conversion, often just by setting an
environment variable, although this is not addressed by the C standard
at all; if not, there is no standard mkgmtime() and you have to do the
calculation yourself along the lines stated by CBFalconer.

- David.Thompson1 at worldnet.att.net
 
K

Keith Thompson

Dave Thompson said:
Note that mktime() converts *local* time in struct tm (including DST
if applicable) called "broken down", to *UTC* time in time_t, which is
(as you say) almost always seconds from 1970-01-01midnight though that
is not actually required by the standard. (UTC is often referred to as
GMT, for example in the name of gmtime(), although technically that is
very slightly different.)

Strictly speaking, a time_t value is neither local time nor UTC.
 
D

Dave Thompson

Strictly speaking, a time_t value is neither local time nor UTC.

You're right. It is UTC in Unix/POSIX (actually not-quite-UTC, but
let's not go there), and I think it must effectively be so in any
implementation with the switch-timezone-setting usage I was preparing
to talk about (and too focussed on), but is not required in general.

- David.Thompson1 at worldnet.att.net
 
K

Keith Thompson

Dave Thompson said:
You're right. It is UTC in Unix/POSIX (actually not-quite-UTC, but
let's not go there), and I think it must effectively be so in any
implementation with the switch-timezone-setting usage I was preparing
to talk about (and too focussed on), but is not required in general.

Well, sort of. In Unix/POSIX (and ignoring leap seconds and the
distinction between UTC and GMT), a time_t value has no inherent time
zone. It's a count of seconds since an arbitrary time in the past.
It happens to be defined as 1970-01-01 00:00:00 UTC, but it could as
validly be defined as 1969-12-31 16:00:00 PST (though using UTC/GMT
makes the math a bit easier). That was the point I was trying to
make.

If you just look at the C standard, of course, (almost) all bets are
off.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top