File:  [ELWIX - Embedded LightWeight unIX -] / libelwix / src / time.c
Revision 1.1.2.2: download - view: text, annotated - select for diffs - revision graph
Thu Mar 7 15:34:26 2013 UTC (11 years, 2 months ago) by misho
Branches: elwix1_1
added new time parse api

#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 * __restrict psMonth, int * __restrict id)
{
	static int sorted = 0;
	struct stridx *el;

	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(psMonth, 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;

	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(psWDay, 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: =0 error or !=0 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];

	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
		return (time_t) -1;

	if (tm.tm_year > 1900)
		tm.tm_year -= 1900;
	else if (tm.tm_year < 70)
		tm.tm_year += 100;

	return timegm(&tm);
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>