/* Copyright (C) 1995 EGLE Magic, New Zealand, All rights reserved. */ #include #include #include #include #include #include #include "emsg.h" #include "lib.h" int parsedate(char *rec); int get_hour(char *rec, int *hour, int *min, int *sec); int get_zone(char *rec); int tzone_find(char *s); int month_find(char *s); /* Could use the routine in INN, it's public domain, but it's also crap (it's not really crap, I just don't like using yacc to do something this simple, it means people have to have and understand yacc to modify it. which includes most unix guru's, and virtually no-one else Doesn't implement relative times, e.g. 2 days, 3 hours, 1 week. Don't try and be nice with dates, if it isn't valid, chuck it, it should never have been accepted this far. */ /* Date: Fri, 19 Nov 82 16:14:55 EST Date: Sun, 27 Mar 83 20:39:37 -0500 Date: Fri, 19 Nov 82 16:14:55 + 22:00:12 Date: Fri, 19 Nov 82 16:14:55 -22:00:12 Date: Fri, 19 Nov 82 16:14:55 GMT Date: 1 Oct 86 11:26:15 GMT */ int parsedate(char *rec) { struct tm t; char bf[200]; char *s; int tzone; ncpy(bf,rec,199); s = bf; memset(&t,0,sizeof(t)); s = strtok(bf,", \n\t"); if (s==NULL) return 0; if (!isdigit(*s)) { /* Must be optional Day, ignore it!! */ s = strtok(NULL," \n\t"); if (s==NULL) return 0; } t.tm_mday = atoi(s); if (t.tm_mday==0) return 0; s = strtok(NULL," \n\t"); if (s==NULL) return 0; t.tm_mon = month_find(s); /* returns 0-11 */ if (t.tm_mon<0) return 0; s = strtok(NULL," \n\t"); if (s==NULL) return 0; t.tm_year = atoi(s); if (t.tm_year==0) return 0; if (t.tm_year>100) t.tm_year -= 1900; /* It's gonna die in 2000 ,thats ansi C ! */ s = strtok(NULL," \n\t"); if (s==NULL) return 0; if (!get_hour(s,&t.tm_hour,&t.tm_min,&t.tm_sec)) return 0; s = strtok(NULL," \n\t"); if (s==NULL) { /* Should have been a time zone, lets assume GMT */ tzone = 0; } else { tzone = get_zone(s); } if (s!=NULL) s = strtok(NULL," \n\t"); if (s!=NULL) tzone += get_zone(s); /*Offset from time zone*/ t.tm_hour += (tzone/(60*60)); t.tm_min += ((tzone % (60*60))/60); /* t.tm_sec += tzone;*/ #ifdef VAX return mymktime(&t); #else return mktime(&t); #endif } int get_hour(char *rec, int *hour, int *min, int *sec) { char hours[200],bf[50]; char *s2,*s3; strcpy(hours,rec); s2 = strchr(hours,':'); if (s2==NULL) { /* Maybe it's 4 digit format, no colon's */ if (strlen(hours)!=4) return FALSE; ncpy(bf,hours,2); *hour = atoi(bf); ncpy(bf,hours+2,2); *min = atoi(bf); *sec = 0; return TRUE; } s3 = strchr(s2+1,':'); *hour = atoi(hours); *min = atoi(s2+1); *sec = 0; if (s3!=NULL) *sec = atoi(s3+1); return TRUE; } int get_zone(char *rec) /* return time zone offset in seconds, GMT = 0 */ { int tsign = 1; int h,m,sec; if (*rec=='+') rec++; if (*rec=='-') {tsign = -1; rec++;} if (isdigit(*rec)) { get_hour(rec,&h,&m,&sec); return tsign*(h*60*60+m*60+sec); } else { return tzone_find(rec); } } typedef struct {char *name; int type; int value;} TABLE; #define tZONE 0 #define tDAYZONE 1 #define HOUR(x) (x*60) static TABLE tzone_table[] = { { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ { "ut", tZONE, HOUR( 0) }, /* Universal */ { "utc", tZONE, HOUR( 0) }, /* Universal Coordinated */ { "cut", tZONE, HOUR( 0) }, /* Coordinated Universal */ { "z", tZONE, HOUR( 0) }, /* Greenwich Mean */ { "wet", tZONE, HOUR( 0) }, /* Western European */ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */ { "nst", tZONE, HOUR(3)+30 }, /* Newfoundland Standard */ { "ndt", tDAYZONE, HOUR(3)+30 }, /* Newfoundland Daylight */ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */ { "cst", tZONE, HOUR( 6) }, /* Central Standard */ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */ { "akst", tZONE, HOUR( 9) }, /* Alaska Standard */ { "akdt", tDAYZONE, HOUR( 9) }, /* Alaska Daylight */ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */ { "hast", tZONE, HOUR(10) }, /* Hawaii-Aleutian Standard */ { "hadt", tDAYZONE, HOUR(10) }, /* Hawaii-Aleutian Daylight */ { "ces", tDAYZONE, -HOUR(1) }, /* Central European Summer */ { "cest", tDAYZONE, -HOUR(1) }, /* Central European Summer */ { "mez", tZONE, -HOUR(1) }, /* Middle European */ { "mezt", tDAYZONE, -HOUR(1) }, /* Middle European Summer */ { "cet", tZONE, -HOUR(1) }, /* Central European */ { "met", tZONE, -HOUR(1) }, /* Middle European */ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe */ { "msk", tZONE, -HOUR(3) }, /* Moscow Winter */ { "msd", tDAYZONE, -HOUR(3) }, /* Moscow Summer */ { "wast", tZONE, -HOUR(8) }, /* West Australian Standard */ { "wadt", tDAYZONE, -HOUR(8) }, /* West Australian Daylight */ { "hkt", tZONE, -HOUR(8) }, /* Hong Kong */ { "cct", tZONE, -HOUR(8) }, /* China Coast */ { "jst", tZONE, -HOUR(9) }, /* Japan Standard */ { "kst", tZONE, -HOUR(9) }, /* Korean Standard */ { "kdt", tZONE, -HOUR(9) }, /* Korean Daylight */ { "cast", tZONE, -(HOUR(9)+30) }, /* Central Australian Standard */ { "cadt", tDAYZONE, -(HOUR(9)+30) }, /* Central Australian Daylight */ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */ { NULL, tDAYZONE, 0 } /* End of table */ }; int tzone_find(char *s) { char bf[100]; int i; ncpy(bf,s,30); strlwr(bf); if (strlen(bf)==1) { /* Military time zones, could have sign wrong*/ if (*bf>='a' && *bf<='m') return -(bf[0]-'a'+1)*60; if (*bf>='n' && *bf<='y') return (bf[0]-'n'+1)*60; return 0; } for (i=0; tzone_table[i].name!=NULL; i++) { if (strcmp(bf,tzone_table[i].name)==0) return tzone_table[i].value*60; } return 0; } static char *months[]={ "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec" }; int month_find(char *s) { char bf[100]; int i; ncpy(bf,s,30); strlwr(bf); for (i=0; i<12; i++) if (strcmp(bf,months[i])==0) return i; return -1; } #ifdef TESTIT main() { char bf[200]; time_t t; struct tm *tt; for (;;) { gets(bf); printf("Input %s \n",bf); t = (time_t) parsedate(bf); tt = localtime(&t); printf("Time %d {%s} \n",t,asctime(tt)); } } char *strlwr(char *s) { char *ss=s; for (;*s!=0;s++) *s = tolower(*s); return ss; } char *ncpy(char *dst, char *src, int len) { strncpy(dst,src,len); dst[len] = 0; return dst; } #endif