--- libelwix/src/time.c 2013/03/05 13:09:51 1.1 +++ libelwix/src/time.c 2013/03/07 16:24:32 1.2 @@ -0,0 +1,263 @@ +/************************************************************************* +* (C) 2013 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov +* +* $Author: misho $ +* $Id: time.c,v 1.2 2013/03/07 16:24:32 misho Exp $ +* +************************************************************************** +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 + by Michael Pounov . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ +#include "global.h" + + +struct stridx { + char *str; + int id; +}; + +static struct stridx months[] = { + { "jan", 0 }, { "january", 0 }, + { "feb", 1 }, { "february", 1 }, + { "mar", 2 }, { "march", 2 }, + { "apr", 3 }, { "april", 3 }, + { "may", 4 }, + { "jun", 5 }, { "june", 5 }, + { "jul", 6 }, { "july", 6 }, + { "aug", 7 }, { "august", 7 }, + { "sep", 8 }, { "september", 8 }, + { "oct", 9 }, { "october", 9 }, + { "nov", 10 }, { "november", 10 }, + { "dec", 11 }, { "december", 11 }, +}; + +static struct stridx wdays[] = { + { "sun", 0 }, { "sunday", 0 }, + { "mon", 1 }, { "monday", 1 }, + { "tue", 2 }, { "tuesday", 2 }, + { "wed", 3 }, { "wednesday", 3 }, + { "thu", 4 }, { "thursday", 4 }, + { "fri", 5 }, { "friday", 5 }, + { "sat", 6 }, { "saturday", 6 }, +}; + +static int +stridx_compare(struct stridx * __restrict a, struct stridx * __restrict b) +{ + return strcmp(a->str, b->str); +} + +static int +search4month(char * psMonth, int * __restrict id) +{ + static int sorted = 0; + struct stridx *el, item = { psMonth, 0 }; + + if (!psMonth) + return -1; + + if (!sorted) { + qsort(months, sizeof(months) / sizeof(struct stridx), sizeof(struct stridx), + (int (*)(const void*, const void*)) stridx_compare); + sorted++; + } + + str_Lower(psMonth); + el = bsearch(&item, months, sizeof(months) / sizeof(struct stridx), sizeof(struct stridx), + (int (*)(const void*, const void*)) stridx_compare); + if (el && id) + *id = el->id; + + return !!el; +} + +static int +search4wday(char * __restrict psWDay, int * __restrict id) +{ + static int sorted = 0; + struct stridx *el, item = { psWDay, 0 }; + + if (!psWDay) + return -1; + + if (!sorted) { + qsort(wdays, sizeof(wdays) / sizeof(struct stridx), sizeof(struct stridx), + (int (*)(const void*, const void*)) stridx_compare); + sorted++; + } + + str_Lower(psWDay); + el = bsearch(&item, wdays, sizeof(wdays) / sizeof(struct stridx), sizeof(struct stridx), + (int (*)(const void*, const void*)) stridx_compare); + if (el && id) + *id = el->id; + + return !!el; +} + + +/* + * time_Parse() - Parse and make unix time from standart time strings ... + * + * @csTime = Time string + * return: =-1 error or !=-1 converted time + */ +time_t +time_Parse(const char *csTime) +{ + struct tm tm; + char *s; + int tm_sec, tm_min, tm_hour, tm_mday, tm_year, tm_mon, tm_wday; + char str_mon[512], str_wday[512]; + time_t tim; + + memset(&tm, 0, sizeof tm); + memset(&str_mon, 0, sizeof str_mon); + memset(&str_wday, 0, sizeof str_wday); + + for (s = (char*) csTime; isspace(*s); s++); + + /* + * And do the sscanfs. WARNING: you can add more formats here, + * but be careful! You can easily screw up the parsing of existing + * formats when you add new ones. The order is important. + */ + + /* DD-mth-YY HH:MM:SS GMT */ + if (sscanf(s, "%d-%400[a-zA-Z]-%d %d:%d:%d GMT", + &tm_mday, str_mon, &tm_year, + &tm_hour, &tm_min, &tm_sec) == 6 && + search4month(str_mon, &tm_mon)) { + tm.tm_mday = tm_mday; + tm.tm_mon = tm_mon; + tm.tm_year = tm_year; + tm.tm_hour = tm_hour; + tm.tm_min = tm_min; + tm.tm_sec = tm_sec; + } + /* DD mth YY HH:MM:SS GMT */ + else if (sscanf(s, "%d %400[a-zA-Z] %d %d:%d:%d GMT", + &tm_mday, str_mon, &tm_year, + &tm_hour, &tm_min, &tm_sec) == 6 && + search4month(str_mon, &tm_mon)) { + tm.tm_mday = tm_mday; + tm.tm_mon = tm_mon; + tm.tm_year = tm_year; + tm.tm_hour = tm_hour; + tm.tm_min = tm_min; + tm.tm_sec = tm_sec; + } + /* HH:MM:SS GMT DD-mth-YY */ + else if (sscanf(s, "%d:%d:%d GMT %d-%400[a-zA-Z]-%d", + &tm_hour, &tm_min, &tm_sec, + &tm_mday, str_mon, &tm_year) == 6 && + search4month(str_mon, &tm_mon)) { + tm.tm_hour = tm_hour; + tm.tm_min = tm_min; + tm.tm_sec = tm_sec; + tm.tm_mday = tm_mday; + tm.tm_mon = tm_mon; + tm.tm_year = tm_year; + } + /* HH:MM:SS GMT DD mth YY */ + else if (sscanf(s, "%d:%d:%d GMT %d %400[a-zA-Z] %d", + &tm_hour, &tm_min, &tm_sec, + &tm_mday, str_mon, &tm_year) == 6 && + search4month(str_mon, &tm_mon)) { + tm.tm_hour = tm_hour; + tm.tm_min = tm_min; + tm.tm_sec = tm_sec; + tm.tm_mday = tm_mday; + tm.tm_mon = tm_mon; + tm.tm_year = tm_year; + } + /* wdy, DD-mth-YY HH:MM:SS GMT */ + else if (sscanf(s, "%400[a-zA-Z], %d-%400[a-zA-Z]-%d %d:%d:%d GMT", + str_wday, &tm_mday, str_mon, + &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 && + search4wday(str_wday, &tm_wday) && + search4month(str_mon, &tm_mon)) { + tm.tm_wday = tm_wday; + tm.tm_mday = tm_mday; + tm.tm_mon = tm_mon; + tm.tm_year = tm_year; + tm.tm_hour = tm_hour; + tm.tm_min = tm_min; + tm.tm_sec = tm_sec; + } + /* wdy, DD mth YY HH:MM:SS GMT */ + else if (sscanf(s, "%400[a-zA-Z], %d %400[a-zA-Z] %d %d:%d:%d GMT", + str_wday, &tm_mday, str_mon, + &tm_year, &tm_hour, &tm_min, &tm_sec) == 7 && + search4wday(str_wday, &tm_wday) && + search4month(str_mon, &tm_mon)) { + tm.tm_wday = tm_wday; + tm.tm_mday = tm_mday; + tm.tm_mon = tm_mon; + tm.tm_year = tm_year; + tm.tm_hour = tm_hour; + tm.tm_min = tm_min; + tm.tm_sec = tm_sec; + } + /* wdy mth DD HH:MM:SS GMT YY */ + else if (sscanf(s, "%400[a-zA-Z] %400[a-zA-Z] %d %d:%d:%d GMT %d", + str_wday, str_mon, &tm_mday, + &tm_hour, &tm_min, &tm_sec, &tm_year) == 7 && + search4wday(str_wday, &tm_wday) && + search4month(str_mon, &tm_mon)) { + tm.tm_wday = tm_wday; + tm.tm_mon = tm_mon; + tm.tm_mday = tm_mday; + tm.tm_hour = tm_hour; + tm.tm_min = tm_min; + tm.tm_sec = tm_sec; + tm.tm_year = tm_year; + } else { + elwix_SetErr(EINVAL, "Invalid date/time format"); + return (time_t) -1; + } + + if (tm.tm_year > 1900) + tm.tm_year -= 1900; + else if (tm.tm_year < 70) + tm.tm_year += 100; + + if ((tim = timegm(&tm)) == (time_t) -1) + elwix_SetErr(EINVAL, "Invalid date/time format"); + return tim; +}