In the first code
char d[20];
... ...
return d;
"d[20]" is on the stack. You are returning a pointer to data on the stack. As soon as update_date() returns all of its local variables are now invalid.
In the second you print the value of d[] before returning so there is no problem.
strok() is probably best to avoid. It modifies the string that you pass in and it keeps static state, both of which are serious pitfalls and often cause subtle bugs.
Here are a couple of alternative implementations. (Of course, in production code you should avoid writing code to parse dates/times in the first place. There are OS and library functions to do this. There are many subtleties).
// Scanf can do parsing for you
int date[3];
int n;
n = sscanf(dat, "%d/%d/%d", &date[0], &date[1], &date[2]);
if (n == 3)
{
// OK, we got 3 integers...
}
// atoi() stops on non-digits, use it instead of strtok
char *result = dat;
int date[3];
int i = 0;
while (i < 3 && result)
{
date[i++] = atoi(result);
result = strchr(result, '/');
if (result)
{
++result; // Skip the '/'
}
}