When using the stat()
function in minGW-W64, and the struct it returns, here info
, why does ctime
return the same exact strings for info.st_atime
, mtime
, and ctime
, even though the their integer values are different?
If localtime
is used to get each time component separately, the results differ and appear accurate; that is, they match the dates in the file folders I've observed.
ctime(&info.st_atime ) versus localtime(&info.st_atime )->tm_wday,
localtime(&info.st_atime )->tm_mon,
localtime(&info.st_atime )->tm_mday,
localtime(&info.st_atime )->tm_hour,
localtime(&info.st_atime )->tm_min,
localtime(&info.st_atime )->tm_sec,
localtime(&info.st_atime )->tm_year
A similar question was asked over three years ago without answer.
Does anyone know why and whether or not there is any documentation on dates in minGW-W64?
Thank you.
Here is the full code example. It's an ugly printf set.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
int main (void)
{
DIR *dp;
struct dirent *ep;
struct stat info;
int rc;
char fl_name[300];
dp = opendir("./SQLite3");
if ( dp != NULL )
{
while ( ep = readdir( dp ) )
{
printf( "Name : %s, ", ep->d_name );
if ( *( ep->d_name ) == '.' )
{
printf(" non-useful file\n");
continue;
}
sprintf( fl_name, "%s%s", "./SQLite3/", ep->d_name );
if ( ( rc = stat( fl_name, &info ) ) != 0 )
{
printf( "rc : %d\n", rc );
printf( "errno : %d, strerror : %s\n", errno, strerror( errno ) );
break;
}
printf( "mode : %d, size : %d,\nst_atime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %d\n"
"st_mtime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %d\n"
"st_ctime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %d\n\n",
info.st_mode, info.st_size,
ctime(&info.st_atime ),
localtime(&info.st_atime )->tm_wday,
localtime(&info.st_atime )->tm_mon,
localtime(&info.st_atime )->tm_mday,
localtime(&info.st_atime )->tm_hour,
localtime(&info.st_atime )->tm_min,
localtime(&info.st_atime )->tm_sec,
localtime(&info.st_atime )->tm_year,
info.st_atime,
ctime(&info.st_mtime ),
localtime(&info.st_mtime )->tm_wday,
localtime(&info.st_mtime )->tm_mon,
localtime(&info.st_mtime )->tm_mday,
localtime(&info.st_mtime )->tm_hour,
localtime(&info.st_mtime )->tm_min,
localtime(&info.st_mtime )->tm_sec,
localtime(&info.st_mtime )->tm_year,
info.st_mtime,
ctime(&info.st_ctime ),
localtime(&info.st_ctime )->tm_wday,
localtime(&info.st_ctime )->tm_mon,
localtime(&info.st_ctime )->tm_mday,
localtime(&info.st_ctime )->tm_hour,
localtime(&info.st_ctime )->tm_min,
localtime(&info.st_ctime )->tm_sec,
localtime(&info.st_ctime )->tm_year ),
info.st_ctime;
}
printf( "Now : %ld\n", time(NULL) );
printf( "Broke" );
(void) closedir (dp);
}
else
perror ("Couldn't open the directory");
return 0;
}
Results for one file looks as follows.
Name : testing.c, mode : 33206, size : 21092,
st_atime : Thu Nov 26 23:56:20 2020
local : 4 10 26 23 : 56 : 20 120,
integer value : 1606452980
st_mtime : Thu Nov 26 23:56:20 2020
local : 5 10 27 0 : 16 : 58 120,
integer value : 1606454218
st_ctime : Thu Nov 26 23:56:20 2020
local : 6 9 31 23 : 8 : 28 120,
integer value : 5767254
Note that the data strings from ctime()
are identical although the integer values differ for all three. Also, the integer value for ctime
is a different format than for atime
and mtime
. The atime
and mtime
appear to be seconds since Jan 1, 1970 but I don't know what ctime
is as 5767254
.
Thanks.
Fixed code according to comment by @KamilCuk. My stupidity and ugly printf were the cause. Changes below and new results.
struct tm *local_tm_ptr;
local_tm_ptr = localtime(&info.st_atime );
printf( "mode : %d, size : %d,\nst_atime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %ld\n",
info.st_mode, info.st_size,
ctime(&info.st_atime ),
local_tm_ptr->tm_wday,
local_tm_ptr->tm_mon,
local_tm_ptr->tm_mday,
local_tm_ptr->tm_hour,
local_tm_ptr->tm_min,
local_tm_ptr->tm_sec,
local_tm_ptr->tm_year,
info.st_atime );
local_tm_ptr = localtime(&info.st_mtime );
printf( "st_mtime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %ld\n",
ctime(&info.st_mtime ),
local_tm_ptr->tm_wday,
local_tm_ptr->tm_mon,
local_tm_ptr->tm_mday,
local_tm_ptr->tm_hour,
local_tm_ptr->tm_min,
local_tm_ptr->tm_sec,
local_tm_ptr->tm_year,
info.st_mtime );
local_tm_ptr = localtime(&info.st_ctime );
printf( "st_ctime : %slocal : %d %d %d %d : %d : %d %d,\ninteger value : %ld\n\n",
ctime(&info.st_ctime ),
local_tm_ptr->tm_wday,
local_tm_ptr->tm_mon,
local_tm_ptr->tm_mday,
local_tm_ptr->tm_hour,
local_tm_ptr->tm_min,
local_tm_ptr->tm_sec,
local_tm_ptr->tm_year,
info.st_ctime );
New results.
Name : testing.c, mode : 33206, size : 21092,
st_atime : Thu Nov 26 23:56:20 2020
local : 4 10 26 23 : 56 : 20 120,
integer value : 1606452980
st_mtime : Fri Nov 27 00:16:58 2020
local : 5 10 27 0 : 16 : 58 120,
integer value : 1606454218
st_ctime : Sat Oct 31 23:08:28 2020
local : 6 9 31 23 : 8 : 28 120,
integer value : 1604200108
You are basically doing:
static char buffer[20]; // static buffer internal for asctime
char *my_asctime(int a) { // asctime
snprintf(buffer, 20, "%d", a); // asctime converts the input to some output
return buffer; // and returns pointer to internal buffer
}
int main() {
printf("%s %s %s %s\n",
my_asctime(1),
my_asctime(2),
my_asctime(3),
my_asctime(4)
);
// **Any** of the outputs are valid:
// 1 1 1 1
// 2 2 2 2
// 3 3 3 3
// 4 4 4 4
}
All asctime
(sane implementations) write to the same memory and return the same pointer. So when printf
is executed it's just going to print the content of the same memory. Note that the order of evaluation of arguments to functions are unsequenced with each other, but order of evaluation of function calls is indeterminately sequenced. Any one of the possible result of asctime
will be valid. Use asctime_r
or call one after another in separate printf
s.