TIP: Click on subject to list as thread! ANSI
echo: c_echo
to: JAVIER KOHEN
from: GEORGE WHITE
date: 1998-03-01 13:07:00
subject: Atotm

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)

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.