rfctime.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00021  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00050 #include <stdio.h>
00051 #include <string.h>
00052 #include <ctype.h>
00053 
00054 #include <pro/rfctime.h>
00055 
00056 static char rfc1123_buf[32];
00057 static char *wkdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
00058 static char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
00059 
00067 static char *skip_spaces(CONST char *str)
00068 {
00069     while (*str == ' ' || *str == '\t')
00070         str++;
00071     return (char *)str;
00072 }
00073 
00084 static char *parse_digits(CONST char *str, int *val)
00085 {
00086     *val = 0;
00087     while (isdigit(*str)) {
00088         *val *= 10;
00089         *val += *str++ - '0';
00090     }
00091     return (char *)str;
00092 }
00093 
00106 char *TimeParseYear(CONST char *str, int *year)
00107 {
00108     str = parse_digits(str, year);
00109     if (*year < 70) {
00110         *year += 100;
00111     }
00112     else if (*year > 1900) {
00113         *year -= 1900;
00114     }
00115     return (char *)str;
00116 }
00117 
00132 char *TimeParseMonth(CONST char *str, int *month)
00133 {
00134     if (*str == 'A') {
00135         if (*++str == 'p' || *str == 'P') {
00136             /* April */
00137             *month = 3; 
00138         }
00139         else {
00140             /* August */
00141             *month = 7;
00142         }
00143     }
00144     else if (*str == 'D') {
00145         /* December */
00146         *month = 11;
00147     }
00148     else if (*str == 'F') {
00149         /* February */
00150         *month = 1;
00151     }
00152     else if (*str == 'J') {
00153         if (*++str == 'a' || *str == 'A') {
00154             /* January */
00155             *month = 0; 
00156         }
00157         else if (*str && (*++str == 'l' || *str == 'L')) {
00158             /* July */
00159             *month = 6;
00160         }
00161         else {
00162             /* June */
00163             *month = 5;
00164         }
00165     }
00166     else if (*str == 'M') {
00167         if (*++str == 'a' && (*++str == 'r' || *str == 'R')) {
00168             /* March */
00169             *month = 2;
00170         }
00171         else {
00172             /* May */
00173             *month = 4;
00174         }
00175     }
00176     else if (*str == 'N') {
00177         /* November */
00178         *month = 10;
00179     }
00180     else if (*str == 'O') {
00181         /* October */
00182         *month = 9;
00183     }
00184     else {
00185         /* September */
00186         *month = 8;
00187     }
00188     while (isalpha(*str)) {
00189         str++;
00190     }
00191     return (char *)str;
00192 }
00193 
00207 char *TimeParseDmy(CONST char *str, int *mday, int *mon, int *year)
00208 {
00209     str = parse_digits(str, mday);
00210     while (*str && !isalpha(*str)) {
00211         str++;
00212     }
00213     str = TimeParseMonth(str, mon);
00214     while (*str && !isdigit(*str)) {
00215         str++;
00216     }
00217     str = TimeParseYear(str, year);
00218 
00219     return (char *)str;
00220 }
00221 
00234 char *TimeParseHms(CONST char *str, int *hour, int *min, int *sec)
00235 {
00236     str = parse_digits(str, hour);
00237     if (*str == ':') {
00238         str = parse_digits(str + 1, min);
00239         if (*str == ':') {
00240             str = parse_digits(str + 1, sec);
00241         }
00242         else {
00243             *sec = 0;
00244         }
00245     }
00246     else {
00247         *min = 0;
00248     }
00249     return (char *)str;
00250 }
00251 
00261 time_t RfcTimeParse(CONST char *str)
00262 {
00263     struct _tm dts = { 0, 0, 0, 1, 0, 0, 0, 0, 0 };
00264 
00265     /* Skip leading whitespace. */
00266     str = skip_spaces(str);
00267 
00268     /* Skip weekday, optional in RFC 822. */
00269     if (isalpha(*str)) {
00270         while (*str && *str != ' ' && *str != '\t')
00271             str++;
00272         str = skip_spaces(str);
00273     }
00274 
00275     if (isalpha(*str)) {
00276         /* asctime format 'Fri Feb 2 2007 07:30:05'. */
00277         str = TimeParseMonth(str, &dts.tm_mon);
00278         str = skip_spaces(str);
00279         str = parse_digits(str, &dts.tm_mday);
00280         str = skip_spaces(str);
00281         str = TimeParseYear(str, &dts.tm_year);
00282         str = skip_spaces(str);
00283         str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec);
00284     }
00285     else if (*str) {
00286         /* RFC 850 'Friday, 02-Feb-2007 07:30:05 GMT'. */
00287         /* RFC 1123 'Fri, 02 Feb 2007 07:30:05 GMT'. */
00288         str = TimeParseDmy(str, &dts.tm_mday, &dts.tm_mon, &dts.tm_year);
00289         str = skip_spaces(str);
00290         str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec);
00291     }
00292     str = skip_spaces(str);
00293     if (strcmp(str, "GMT") == 0) {
00294         return mktime(&dts);
00295     }
00296     return _mkgmtime(&dts);
00297 }
00298 
00306 char *Rfc1123TimeString(struct _tm *tm)
00307 {
00308     sprintf(rfc1123_buf, "%s, %02d %s %04d %02d:%02d:%02d",
00309             wkdays[tm->tm_wday], 
00310             tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
00311             tm->tm_hour, tm->tm_min, tm->tm_sec);
00312 
00313     return rfc1123_buf;
00314 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/