Unix time (predating epoch of Jan-1970)

G

Grey Alien

I need to convert timestamps that are given as the number of seconds
that have elapsed since midnight UTC of January 1, 1970, (not counting
leap seconds).

It seems all of the std C functions expect positive offsets from this
date and are incapable of working on dates preceeding the epoch (i.e.
negative offsets) - which IMHO shows a remarkable lack of foresight -
and is *just* a little bit annoying.

Does anyone know of an algo I can use to calculate the components to
fill a variable of type 'struct tm' - given a time_t variable with a -ve
offset from the UNIX epoch?

Or to reword teh above, does anyone know how I can extract the century,
year, month, day, hour, min, second from a time_t value that represents
a timestamp BEFORE midnight UTC of January 1, 1970?
 
G

Gordon Burditt

I need to convert timestamps that are given as the number of seconds
that have elapsed since midnight UTC of January 1, 1970, (not counting
leap seconds).

Is that the native format of a time_t on your machine? It might
be but that isn't guaranteed by standard C.
It seems all of the std C functions expect positive offsets from this
date and are incapable of working on dates preceeding the epoch (i.e.
negative offsets) - which IMHO shows a remarkable lack of foresight -
and is *just* a little bit annoying.

A time_t is intended to represent current times and file modification
times, and things like birth dates, which don't normally carry a
time or time zone, aren't really included in that. I'd prefer a
256-bit timestamp: number of yoctoseconds since the beginning of
the universe, except nobody knows exactly when that was.
Does anyone know of an algo I can use to calculate the components to
fill a variable of type 'struct tm' - given a time_t variable with a -ve
offset from the UNIX epoch?

Re-implement a function such as localtime() which treats time_t as signed.
Or to reword teh above, does anyone know how I can extract the century,
year, month, day, hour, min, second from a time_t value that represents
a timestamp BEFORE midnight UTC of January 1, 1970?

It appears that on the machine you have, a negative time_t value
*DOES* *NOT* represent a timestamp before midnight UTC of January
1, 1970, it represents one somewhat after January 2038.
 
K

Kenny McCormack

Gordon Burditt said:
time or time zone, aren't really included in that. I'd prefer a
256-bit timestamp: number of yoctoseconds since the beginning of
the universe, except nobody knows exactly when that was.

According to 75% of Americans, it was just over 6000 years ago.
 
R

Roberto Waltman

Grey said:
I need to convert timestamps that are given as the number of seconds
that have elapsed since midnight UTC of January 1, 1970,

It seems all of the std C functions expect positive offsets from this
date and are incapable of working on dates preceeding the epoch

That is implementation dependent. From N1124:
"7.23.1 ... 4 The range and precision of times representable in
clock_t and time_t are implementation-defined."

"7.23.2.4 ... 2 The time function determines the current calendar
time. The encoding of the value is unspecified."
...does anyone know how I can extract the century,
year, month, day, hour, min, second from a time_t value that represents
a timestamp BEFORE midnight UTC of January 1, 1970?

How were these time_t values produced? The code snippet below works
under 4.1.2 / Ubuntu 7.04.
May be you can port to your system the time functions from another
system that covers the time span you need.
Failing that, books such as "Calendrical calculations" will give you
all the information you need.
(http://emr.cs.uiuc.edu/home/reingold/calendar-book/index.shtml)


------------------------------------
$ cat time-test.c
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
* "... Armstrong landed the lunar module Eagle
* on the surface of the Moon at 4:17:42 p.m.
* Eastern Daylight Time, July 20, 1969"
*
*/

int main(void)
{
time_t landing;
struct tm man_on_the_moon;
struct tm *tmptr;

/* from struct tm to time_t */

man_on_the_moon.tm_sec = 42;
man_on_the_moon.tm_min = 17;
man_on_the_moon.tm_hour = 16;
man_on_the_moon.tm_mday = 20;
man_on_the_moon.tm_mon = 6;
man_on_the_moon.tm_year = 69;
man_on_the_moon.tm_isdst = 0;

landing = mktime(&man_on_the_moon);

if (landing == (time_t)-1)
{
puts("tm --> time_t, conversion failed");
return EXIT_FAILURE;
}
puts("tm --> time_t, conversion OK");

/* from time_t to struct tm */

memset(&man_on_the_moon, 0, sizeof(man_on_the_moon));
tmptr = gmtime(&landing);
if (tmptr == NULL)
{
puts("time_t --> tm, conversion failed");
return EXIT_FAILURE;
}
man_on_the_moon = *tmptr;
puts("time_t --> tm, conversion OK");

puts(asctime(&man_on_the_moon));
return EXIT_SUCCESS;
}
$ time-test
tm --> time_t, conversion OK
time_t --> tm, conversion OK
Sun Jul 20 16:17:42 1969



Roberto Waltman

[ Please reply to the group,
return address is invalid ]
 
M

Mark McIntyre

I need to convert timestamps that are given as the number of seconds
that have elapsed since midnight UTC of January 1, 1970, (not counting
leap seconds).

It seems all of the std C functions expect positive offsets from this
date

Yes. time_t is designed for storing a time since the epoch, not times
before the epoch.

Why do you want to use struct tm for this? If you want to store
arbitrary dates, you should be using a specialist library. Its not
that hard to write one that can store any date in the range of a long,
from any epoch you care to mention (post calendar reform at least).

A few years back I wrote a general purpose lib that did this for a
financial maths library my employer wanted to update. I ended up being
able to handle any date and time from 1/1/1600 to the year one million
- typically I needed to add or subtract days, months and years from a
date, work out the difference between two in days, months or years,
and handle fractional days when the difference became less than some
user-definable threshold. I probably overgeneralised it...
Or to reword teh above, does anyone know how I can extract the century,
year, month, day, hour, min, second from a time_t value that represents
a timestamp BEFORE midnight UTC of January 1, 1970?

By using a different method..... :)

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
K

Keith Thompson

Mark McIntyre said:
Yes. time_t is designed for storing a time since the epoch, not times
before the epoch.
[...]

What is the basis for this claim? The C standard says only that
time_t is an arithmetic type capable of representing times; it doesn't
even mention an "epoch". Even POSIX isn't all that much more
specific.

Consider the following program:

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

int main(void)
{
time_t now = time(NULL);
time_t zero = 0;
time_t then = - now;
/*
* NOTE: The above is non-portable. If time_t represents times
* in seconds, 'then' will represent a time as long
* as the current time is after the epoch.
*/

struct tm now_tm = *(gmtime(&now));
struct tm zero_tm = *(gmtime(&zero));
struct tm then_tm = *(gmtime(&then));

printf("now = %s", asctime(&now_tm));
printf("zero = %s", asctime(&zero_tm));
printf("then = %s", asctime(&then_tm));

return 0;
}

It could use some more error checking, and as the comment acknowledges
it makes one major non-portable assumption. On one system where that
assumption happens to be satisified (it happens to be a Solaris 9
system), it produced the following output:

now = Fri Jul 20 00:19:40 2007
zero = Thu Jan 1 00:00:00 1970
then = Tue Jun 14 23:40:20 1932

For details, consult comp.unix.programmer.
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top