ctime double double check

A

aisling.cronin

Hi

I am using ctime to convert the following string 1144412677847 ....
Please could some one to double check if they get the same result as
me (The Time is Sun Nov 02 09:11:51 2031). It seems incorrect and
would like a second opion.

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

int main ()
{
unsigned long Timestamp;
time_t CTime;
Timestamp= (long)1144412677847 ;
CTime=ctime(&Timestamp);
printf ("The Time is %s", CTime);
exit(0);
}

The Time is Sun Nov 02 09:11:51 2031
 
L

Lew Pitcher

Hi

I am using ctime to convert the following string 1144412677847 ....
Please could some one to double check if they get the same result as
me (The Time is Sun Nov 02 09:11:51 2031). It seems incorrect and
would like a second opion.

First off, your example code is wrong. Fix it before you continue.
Secondly, your integer constant may be too large for an unsigned long
(or a time_t, see below) to hold. Check your compiler warnings.
#include <time.h>
#include <stdio.h>

int main ()

ITYM
int main(void)
{
unsigned long Timestamp;
time_t CTime;
Timestamp= (long)1144412677847 ;

The cast wont help; remove it.
As Timestamp is defined as unsigned long, your cast may reduce the
precision of the value (assume the constant can fit into an unsigned
long, but not a signed long). It certainly wont increase the precision
of the value.
CTime=ctime(&Timestamp);

Way wrong.

go look up the ctime() call, and reread the documentation
1) ctime() returns a pointer to a char, not time_t value
2) ctime() takes as its only argument a pointer to a time_t, not a
pointer to an unsigned long (time_t may /or may not/ be typedefed as
such)

printf ("The Time is %s", CTime);

Way wrong.

Go look up the printf() call and reread the documentation.
Specifically, look at what argument types correspond to each escape
sequence.

You use "%s", which corresponds to a char *, but you give it a time_t
instead.
 
E

Eric Sosman

Hi

I am using ctime to convert the following string 1144412677847 ....
Please could some one to double check if they get the same result as
me (The Time is Sun Nov 02 09:11:51 2031). It seems incorrect and
would like a second opion.

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

int main ()
{
unsigned long Timestamp;
time_t CTime;
Timestamp= (long)1144412677847 ;
CTime=ctime(&Timestamp);

Get a different compiler. A working C compiler should
have issued at least one diagnostic here, perhaps two (or
even more), because this statement is grossly in error:

1) The argument to ctime() must be a `time_t*', not
the `unsigned long*' you have provided. There is a faint
possibility that `unsigned long' and `time_t' are synonyms
on the system you are using, hence a faint chance that the
"mismatch" matches after all. It is an error nonetheless,
because as soon as you move the code to a machine where
`time_t' is not `unsigned long' (and there are manymanymany
such machines), the code will be wrong, R-O-N-G, wrong.

2) The value returned by ctime() is a `char*', which
is *guaranteed* not to be the same as a `time_t'. Yet you
try to store this `char*' value in a `time_t' variable.
A proper compiler is required to complain about this abuse.
printf ("The Time is %s", CTime);

This is another error: The "%s" conversion must be
matched with a `char*' argument, yet you are supplying a
`time_t' instead. The compiler is not required to catch
this error, but good compilers will spot it anyhow. Get
one of them.

Yet another error, albeit a "venial" one. There is
no declaration of the exit() function in scope, so the
compiler will assume it takes a fixed but unknown number
of arguments and returns an `int' value. In actual fact,
exit() takes one argument and returns no value, so the
assumption at the point of call disagrees with reality.
It's undefined behavior -- U.B. that you are likely to
get away with, but U.B. nonetheless.
 
R

Richard Bos

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

int main ()
{
unsigned long Timestamp;
time_t CTime;
Timestamp= (long)1144412677847 ;
CTime=ctime(&Timestamp);

ctime() takes a pointer to a time_t, not to an unsigned long; and it
returns a char *, not a time_t.
Even where time_t happens to be the same size and so forth as an
unsigned long, that doesn't mean that any random integral value assigned
to one is going to be a valid time. The way times are encoded in a
time_t is system-dependent; the ISO C Standard makes no demands on it at
all, beyond it being an arithmetic type that (somehow) represents a
time. Your big number may or may not represent the time you think it
represents, on your system; ISO C, and therefore comp.lang.c, cannot
tell.
printf ("The Time is %s", CTime);

HTF did you manage to get this compiled?

You need <stdlib.h> for exit().

Richard
 
A

aisling.cronin

(e-mail address removed) wrote On 03/08/07 09:28,:









Get a different compiler. A working C compiler should
have issued at least one diagnostic here, perhaps two (or
even more), because this statement is grossly in error:

1) The argument to ctime() must be a `time_t*', not
the `unsigned long*' you have provided. There is a faint
possibility that `unsigned long' and `time_t' are synonyms
on the system you are using, hence a faint chance that the
"mismatch" matches after all. It is an error nonetheless,
because as soon as you move the code to a machine where
`time_t' is not `unsigned long' (and there are manymanymany
such machines), the code will be wrong, R-O-N-G, wrong.

2) The value returned by ctime() is a `char*', which
is *guaranteed* not to be the same as a `time_t'. Yet you
try to store this `char*' value in a `time_t' variable.
A proper compiler is required to complain about this abuse.


This is another error: The "%s" conversion must be
matched with a `char*' argument, yet you are supplying a
`time_t' instead. The compiler is not required to catch
this error, but good compilers will spot it anyhow. Get
one of them.


Yet another error, albeit a "venial" one. There is
no declaration of the exit() function in scope, so the
compiler will assume it takes a fixed but unknown number
of arguments and returns an `int' value. In actual fact,
exit() takes one argument and returns no value, so the
assumption at the point of call disagrees with reality.
It's undefined behavior -- U.B. that you are likely to
get away with, but U.B. nonetheless.

Thank you all for pointing out all my coding errors, I have fixed it
up, hopefully this is correct

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

int main (void)
{
time_t Timestamp;
char *CTime;
Timestamp= 1144412677847 ;
CTime=ctime(&Timestamp);
printf ("The Time is %s ", CTime);
}

I am not sure of what to cast the timestamp as I get ..
test.c:8: warning: integer constant is too large for "long" type
test.c:8: warning: overflow in implicit constant conversion
When the program is run is still produces the same result (The Time is
Sun Nov 02 09:11:51 2031)
 
L

Lew Pitcher

Thank you all for pointing out all my coding errors, I have fixed it
up, hopefully this is correct

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

int main (void)
{
time_t Timestamp;
char *CTime;
Timestamp= 1144412677847 ;
CTime=ctime(&Timestamp);
printf ("The Time is %s ", CTime);

}

I am not sure of what to cast the timestamp as I get ..

You don't cast the timestamp.
test.c:8: warning: integer constant is too large for "long" type
test.c:8: warning: overflow in implicit constant conversion

Read the warning messages. Try to understand what they say.
They are telling you that the compiler cannot fit the number
1144412677847 into a time_t variable. No amount of casting will
improve this situation; a cast will at worst truncate the value before
assigning it to the time_t, and at best do nothing.

Basically, your number is just too big to use as a time stamp.
 
F

Flash Gordon

(e-mail address removed) wrote, On 08/03/07 15:37:

Thank you all for pointing out all my coding errors, I have fixed it
up, hopefully this is correct

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

int main (void)
{
time_t Timestamp;
char *CTime;
Timestamp= 1144412677847 ;
CTime=ctime(&Timestamp);
printf ("The Time is %s ", CTime);
}

I am not sure of what to cast the timestamp as I get ..
test.c:8: warning: integer constant is too large for "long" type

Then perhaps the compiler knows it does not fit it to a long and it
thought you should know? It might fit in to an unsigned long.
test.c:8: warning: overflow in implicit constant conversion

This warning probably means that on your implementation the value you
have used does not fit in to whatever type time_t is. The standard does
not guarantee it will. I suggest you check the documentation for your
implementation to see what (if any) guarantees it gives about time_t.
When the program is run is still produces the same result (The Time is
Sun Nov 02 09:11:51 2031)

Since the standard does not specify what any values of time_t correspond
to I suggest asking in a place that talks about whatever implementation
you are using. Richard Bos has already said that we cannot tell you how
specific values of time_t map to specific times.
 
R

R Pradeep Chandran

I am using ctime to convert the following string 1144412677847 ....
Please could some one to double check if they get the same result as
me (The Time is Sun Nov 02 09:11:51 2031). It seems incorrect and
would like a second opion.

There are a lot of things that are incorrect.
#include <time.h>
#include <stdio.h>
#include said:
/*int main ()*/
int main (void) /* No arguments */
{
unsigned long Timestamp;
time_t CTime;
Timestamp= (long)1144412677847 ;

Why are you casting an integer constant to a long before assigning to
a variable of type unsigned long?
long is required to support only -2147483647 to +2147483647. Since you
are casting to a signed type, the result of the cast is implementation
defined.
If your implementation supports 32 bit longs, as most do, Timestamp
will not have the value 1144412677847.
CTime=ctime(&Timestamp);

You are assigning a pointer to character to CTime which is an object
of type time_t. time_t is an arithmetic type. The conversion is
implementation defined.
printf ("The Time is %s", CTime);
exit(0);
}

Here you have undefined behavior. The argument corresponding to %s
should be a pointer to character.

Have a nice day,
Pradeep
 
K

Keith Thompson

Flash Gordon said:
Then perhaps the compiler knows it does not fit it to a long and it
thought you should know? It might fit in to an unsigned long.

1144412677847 is between 2**40 and 2**41. If it doesn't fit into a
long, it's not likely to fit into an unsigned long.

To the OP: where did you get the number 1144412677847, and what makes
you think it's a valid time_t value?

As others have pointed out, the standard imposes very few requirements
on how time_t is represented. (In my opinion, it's under-specified.)
There happens to be a very common system-specific representation,
where a time_t is an integer type (usually signed, usually 32 bits,
sometimes 64 bits) representing the number of seconds since 1970-01-01
00:00:00 GMT. Assuming that particular representation, the value
1144412677847 represents a time in late December of the year 38,234.
(It may or may not be coincidental that if you divide it by 1000, it
represents a time about 13 months ago.)

Any program that works with specific numeric time_t values is
non-portable, perhaps needlessly so. If you really need to work with
the specific representation I described above, you should ask in a
system-specific newsgroup, perhaps comp.unix.programmer.
 
A

aisling.cronin

1144412677847 is between 2**40 and 2**41. If it doesn't fit into a
long, it's not likely to fit into an unsigned long.

To the OP: where did you get the number 1144412677847, and what makes
you think it's a valid time_t value?

As others have pointed out, the standard imposes very few requirements
on how time_t is represented. (In my opinion, it's under-specified.)
There happens to be a very common system-specific representation,
where a time_t is an integer type (usually signed, usually 32 bits,
sometimes 64 bits) representing the number of seconds since 1970-01-01
00:00:00 GMT. Assuming that particular representation, the value
1144412677847 represents a time in late December of the year 38,234.
(It may or may not be coincidental that if you divide it by 1000, it
represents a time about 13 months ago.)

Any program that works with specific numeric time_t values is
non-portable, perhaps needlessly so. If you really need to work with
the specific representation I described above, you should ask in a
system-specific newsgroup, perhaps comp.unix.programmer.

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"- Hide quoted text -

- Show quoted text -

I am trying to create a decoder...

I started in Perl and switched to C yesterday because of my issues
with converting the time. So I apologise for all my syntax errors. I
don't program everyday so I am slightly rusty...

The initial value is '00000109744ea6d6' I was told that I should split
the data up into 2bytes, the first 2bytes are spare, the next 6bytes
are the data, each 2bytes of data the last character gets counted up
(I have no idea why? Maybe someone could explain this to me?). The
rounded up 2bytes are then concated together and convert from hex to
decimal this is how I go the value 1144412677847. I have to take it in
good faith that this is correct... Although I was told yesterday that
the value 1144412677847 is in microseconds so that would explain why I
could not fit it into time_t.

ts_hex= 0109744ea6d6;
ts_number_hex[0] = 0109; ts_number_hex_countup [0]:010a
ts_number_hex[1] = 744e; ts_number_hex_countup [1]:744f
ts_number_hex[2] = a6d6; ts_number_hex_countup [2]:a6d7
tsCountUpPacked 010a744fa6d7
# Using Math::BigInt v1.80 (from initial perl program)
tsCountUpPackedBigInt 1144412677847

How do people normally store / encode / decode unix/ posix machine
time? Has anyone seen this approach and can guide me?
 
N

Nelu

I am trying to create a decoder...

I started in Perl and switched to C yesterday because of my issues
with converting the time. So I apologise for all my syntax errors. I
don't program everyday so I am slightly rusty...

The initial value is '00000109744ea6d6' I was told that I should split
the data up into 2bytes, the first 2bytes are spare, the next 6bytes
are the data, each 2bytes of data the last character gets counted up
(I have no idea why? Maybe someone could explain this to me?). The
rounded up 2bytes are then concated together and convert from hex to
decimal this is how I go the value 1144412677847. I have to take it in
good faith that this is correct... Although I was told yesterday that
the value 1144412677847 is in microseconds so that would explain why I
could not fit it into time_t.

Microseconds since when? Although the standard doesn't say
anything about sub-second divisions of time an implementation may
extend the struct tm structure and possibly alter the value of a
time_t variable to take milliseconds into consideration or not.
However I couldn't find anything in the standard that specifies
how the struct tm - time_t conversions should be done which means
it's up to the implementation, which also means that it is not
portable to use time_t between different applications.
If the number you are receiving is giving you the number of
milliseconds since a fixed time in the past it's up to you to
write a conversion tool or find something to convert it for you
but you should not rely on time_t.
How do people normally store / encode / decode unix/ posix machine
time? Has anyone seen this approach and can guide me?

If you are talking portable then store the numbers as ASCII text
like: "YYYYMMDDHHMMSS[ss] or YYYY-MM-DD HH:MM:SS[.ss]" or if
other format that suits you best. I think there is a standard for
storing date as a string of characters and it may look like in
the previous examples. The advantage of storing the time like
that is that it will also sort the time correctly even as a
string. To make it even more portable you could add a timezone
identifier somewhere.
 
K

Keith Thompson

Nelu said:
If you are talking portable then store the numbers as ASCII text
like: "YYYYMMDDHHMMSS[ss] or YYYY-MM-DD HH:MM:SS[.ss]" or if
other format that suits you best. I think there is a standard for
storing date as a string of characters and it may look like in
the previous examples. The advantage of storing the time like
that is that it will also sort the time correctly even as a
string. To make it even more portable you could add a timezone
identifier somewhere.

ISO standard 8601, described at
<http://www.cl.cam.ac.uk/~mgk25/iso-time.html>.
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top