/*      rev_ctime.c (c)2002 Dave Von Pless ([email protected])

       This file is placed in the public domain.  Use as you see fit.

       Libray routine to perform the reverse of ctime(), i.e. convert
       ctime() formatted timestamp to a time_t.

       Usage: int rev_ctime(const char *ctime, time_t *timeptr);

       Input:  26-char string in ctime() format (Trailing '\n' will
               be handled, if present), pointer to a time_t.

       Return: 1 for success, 0 on failure.
               The correct time_t will be stored in the time_t
               pointer supplied.


       Compile with -DDEBUG to dump errors to stderr.  These will be
       either a malloc() failure or bad token parsing.

       Compile with -DDEBUG=2 for parse info.

EXAMPLE:

..
time_t some_time;
if((rev_ctime("Wed Dec 11 21:30:58 2002", &some_time)) {
       ...
}
..

*/
#ifdef DEBUG
#include <stdio.h>              /* for printf() */
#endif
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define NUM_FIELDS 7            /* wday mon day hh:mm:ss yyyy */

int  month2num(char *MonStr);   /* Month text to int lookup */

/*
       Make a copy of the input string, as we'll clobber it
       in the parsing.  Next, loop through the 7 fields,
       populating a struct tm with parsed data.  Lastly,
       call mktime() to get the time_t
*/
int rev_ctime(const char *ctime, time_t *timeptr)
{
       char    *mystr, *p, *param;
       char    sep=' ';        /* ctime() string splits on space */
       int     field=0;
       struct  tm tm;

       mystr=malloc(strlen(ctime)+1);
       if(!mystr) {
#ifdef DEBUG
               fprintf(stderr,"rev_ctime(): malloc failure.\n");
#endif
               return 0;
       }
       strcpy(mystr,ctime);
       p=strchr(mystr,'\n');   /* Handle trailing newline,
                                          if present */
       if(p) {
               *p='\0';
       }
       param=mystr;

       while(field < NUM_FIELDS) {
               p=strchr(param,sep);
               if(!p) {        /* We've failed */
#ifdef DEBUG
                       fprintf(stderr,"rev_ctime(): Bad input @field %d\n\t"
                         "-- can't find  '%c' before %s in '%s'\n", field,
                         sep,param, ctime);
#endif
                       free(mystr);
                       return 0;
               }
               *p='\0';
               p++;
#if DEBUG==2
                               /* Show what we're parsing */
               fprintf(stderr,"field=%d, param=%s, p=%s sep='%c'\n", field,
                       param,p,sep);
#endif
               switch(field) {
                       case 0: break;  /* We don't need tm_mday */
                       case 1: tm.tm_mon=month2num(param);
                               if(tm.tm_mon > 12) {
#ifdef DEBUG
                                       fprintf(stderr,"rev_ctime(): "
                                               "Bad month input -- "
                                               " %s\n", param);
#endif
                                       free(mystr);
                                       return 0;
                               }
                               break;
                       case 2: tm.tm_mday=atoi(param);
                               sep=':';        /* Time splits on ':' */
                               break;
                       case 3: tm.tm_hour=atoi(param);
                               break;
                       case 4: tm.tm_min=atoi(param);
                               sep=' ';        /* Split on ' ' */
                               break;
                       case 5: tm.tm_sec=atoi(param);
                               sep='\0';       /* Find string end */
                               break;
                       case 6: tm.tm_year=(atoi(param)-1900);
                               break;
               }
               param=p;
               field++;
       }
       tm.tm_isdst=-1;                 /* Have mktime() figure out DST */
       *timeptr=mktime(&tm);
       free(mystr);
       return 1;
}

/* Return month number 0-11.  Send 13 on error. */
int month2num(char *MonStr)
{
       char *mons[]={ "Jan","Feb","Mar","Apr","May", "Jun","Jul","Aug",
               "Sep","Oct","Nov","Dec" };
       int i;

       for(i=0;i<12;i++) {
               if(!strcmp(MonStr,mons[i])) {
                       return i;
               }
       }
       return 13;                      /* Failed, impossible month! */
}