Hi Javier,
Follow up to previous reply. I've been doing some testing in addition to
the visual check I gave it before.
Bob Stout: If you've got this one for consideration for SNIPPETS, there
are some important changes. As originally posted the conversion gives
invalid results.
GW>JK>"Converts strings formated as asctime output to struct tm."
GW>JK>struct tm atotm(const char *str) {
GW>JK> int i;
GW>JK> char month[4];
GW>JK> struct tm timer;
GW>As you are returning the struct, I think it really needs to be static.
Corrected by Auke, the struct need not be static.
GW>JK> /* Redundant width specifiers, maybe some scanf implementation
GW>JK> works better with fixed widths, or maybe not */
GW>JK> if (6 != sscanf(str, "%*3s %3s %2d %2d:%2d:%2d %4d\n",
GW>JK> month, &timer.tm_mday, &timer.tm_hour,
GW>JK> &timer.tm_min, &timer.tm_sec, &timer.tm_year)) {
GW>JK> /* Returns a zeroed struct when a parse error occurs */
GW>JK> const struct tm zero = { 0 };
GW>JK> return (zero);
GW>JK> }
GW>JK> timer.tm_year -= 1900;
GW>JK> /* Convert month string to index number */
GW>JK> for (i = 0; i < 12; i++) {
GW>JK> if (0 == strcmp(month, months[i])) {
GW>JK> timer.tm_mon = i;
GW>JK> break;
GW>JK> }
GW>JK> }
GW>JK> timer.tm_wday = dow(timer.tm_year, timer.tm_mon, timer.tm_mday);
GW>As you have the day available as a string from the input, did you
GW>consider converting it in a similar way to the month rather than useing
GW>an independant calculation?
Also, the SNIPPETS routines need calendar year and months starting from
1, not 0, and the daynum() return starts from 1, whereas tm_yday starts
from 0:
timer.tm_wday = dow(timer.tm_year+1900,timer.tm_mon+1, timer.tm_mday);
timer.tm_yday=daynum(timer.tm_year+1900,timer.tm_mon+1,timer.tm_mday)-1;
This is probably better done by some code re-arrangement to calculate
the day of week and day number before correcting the year.
A further thought was that as the month is obtained by stepping through
all the months to the current one with very little overhead we can
calculate the day of year. As:
unsigned short days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
/* Convert month string to index number */
timer.tm_yday = 0;
for (i = 0; i < 12; i++) {
if (0 == strcmp(month, months[i])) {
timer.tm_mon = i;
break;
}
else
timer.tm_yday += days[i];
}
timer.tm_yday += timer.tm_mday - 1;
if (isleap (timer.tm_year) && (timer.tm_mon > 1))
timer.tm_yday += 1;
As the loop is already there doing it this way is quicker than going
through the SNIPPETS code you used.
Then again, calculating day-of year can also be done by:
unsigned short days_so_far[] =
{0,31,59,90,120,151,181,212,243,273,304,334};
timer.tm_yday = days_so_far[timer.tm_mon] + timer.tm_mday - 1;
if (isleap (timer.tm_year) && (timer.tm_mon > 1))
timer.tm_yday += 1;
Which is even quicker...
To Bob, why not use this method in the SNIPPETS code for daynum()?
I'll give my preferred version of the full modified code to prevent
confusion (well I got confused when I was trying to work out how to
describe what I meant by just specifying the changed bits...).
All Public Domain of course...
struct tm atotm(const char *str) {
unsigned short days_so_far[] =
{0,31,59,90,120,151,181,212,243,273,304,334};
int i;
char month[4];
struct tm timer;
/* Redundant width specifiers, maybe some scanf implementation
works better with fixed widths, or maybe not */
if (6 != sscanf(str, "%*3s %3s %2d %2d:%2d:%2d %4d\n",
month, &timer.tm_mday, &timer.tm_hour,
&timer.tm_min, &timer.tm_sec, &timer.tm_year)) {
/* Returns a zeroed struct when a parse error occurs */
const struct tm zero = { 0 };
return (zero);
}
/* Convert month string to index number */
for (i = 0; i < 12; i++) {
if (0 == strcmp(month, months[i])) {
timer.tm_mon = i;
break;
}
}
/* The following call needs calendar year and months starting at 1 */
timer.tm_wday = dow(timer.tm_year, timer.tm_mon + 1, timer.tm_mday);
timer.tm_yday = days_so_far[timer.tm_mon] + timer.tm_mday - 1;
if (isleap (timer.tm_year) && (timer.tm_mon > 1))
timer.tm_yday += 1;
timer.tm_year -= 1900; /* Now we can correct the year value */
/* This can not be implemented from the string */
timer.tm_isdst = 0;
return (timer);
}
George
* SLMR 2.1a * All Trademarks acknowledged (just in case ).
--- Maximus/2 3.01
---------------
* Origin: DoNoR/2,Woking UK (44-1483-717905) (2:440/4)
|