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 
00047 #include <stdio.h>
00048 #include <string.h>
00049 #include <ctype.h>
00050 
00051 #include <pro/rfctime.h>
00052 
00053 static char rfc1123_buf[32];
00054 static char *wkdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
00055 static char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
00056 
00064 static char *skip_spaces(CONST char *str)
00065 {
00066     while (*str == ' ' || *str == '\t')
00067         str++;
00068     return (char *)str;
00069 }
00070 
00081 static char *parse_digits(CONST char *str, int *val)
00082 {
00083     *val = 0;
00084     while (isdigit(*str)) {
00085         *val *= 10;
00086         *val += *str++ - '0';
00087     }
00088     return (char *)str;
00089 }
00090 
00103 char *TimeParseYear(CONST char *str, int *year)
00104 {
00105     str = parse_digits(str, year);
00106     if (*year < 70) {
00107         *year += 100;
00108     }
00109     else if (*year > 1900) {
00110         *year -= 1900;
00111     }
00112     return (char *)str;
00113 }
00114 
00129 char *TimeParseMonth(CONST char *str, int *month)
00130 {
00131     if (*str == 'A') {
00132         if (*++str == 'p' || *str == 'P') {
00133             /* April */
00134             *month = 3; 
00135         }
00136         else {
00137             /* August */
00138             *month = 7;
00139         }
00140     }
00141     else if (*str == 'D') {
00142         /* December */
00143         *month = 11;
00144     }
00145     else if (*str == 'F') {
00146         /* February */
00147         *month = 1;
00148     }
00149     else if (*str == 'J') {
00150         if (*++str == 'a' || *str == 'A') {
00151             /* January */
00152             *month = 0; 
00153         }
00154         else if (*str && (*++str == 'l' || *str == 'L')) {
00155             /* July */
00156             *month = 6;
00157         }
00158         else {
00159             /* June */
00160             *month = 5;
00161         }
00162     }
00163     else if (*str == 'M') {
00164         if (*++str == 'a' && (*++str == 'r' || *str == 'R')) {
00165             /* March */
00166             *month = 2;
00167         }
00168         else {
00169             /* May */
00170             *month = 4;
00171         }
00172     }
00173     else if (*str == 'N') {
00174         /* November */
00175         *month = 10;
00176     }
00177     else if (*str == 'O') {
00178         /* October */
00179         *month = 9;
00180     }
00181     else {
00182         /* September */
00183         *month = 8;
00184     }
00185     while (isalpha(*str)) {
00186         str++;
00187     }
00188     return (char *)str;
00189 }
00190 
00204 char *TimeParseDmy(CONST char *str, int *mday, int *mon, int *year)
00205 {
00206     str = parse_digits(str, mday);
00207     while (*str && !isalpha(*str)) {
00208         str++;
00209     }
00210     str = TimeParseMonth(str, mon);
00211     while (*str && !isdigit(*str)) {
00212         str++;
00213     }
00214     str = TimeParseYear(str, year);
00215 
00216     return (char *)str;
00217 }
00218 
00231 char *TimeParseHms(CONST char *str, int *hour, int *min, int *sec)
00232 {
00233     str = parse_digits(str, hour);
00234     if (*str == ':') {
00235         str = parse_digits(str + 1, min);
00236         if (*str == ':') {
00237             str = parse_digits(str + 1, sec);
00238         }
00239         else {
00240             *sec = 0;
00241         }
00242     }
00243     else {
00244         *min = 0;
00245     }
00246     return (char *)str;
00247 }
00248 
00258 time_t RfcTimeParse(CONST char *str)
00259 {
00260     struct _tm dts = { 0, 0, 0, 1, 0, 0, 0, 0, 0 };
00261 
00262     /* Skip leading whitespace. */
00263     str = skip_spaces(str);
00264 
00265     /* Skip weekday, optional in RFC 822. */
00266     if (isalpha(*str)) {
00267         while (*str && *str != ' ' && *str != '\t')
00268             str++;
00269         str = skip_spaces(str);
00270     }
00271 
00272     if (isalpha(*str)) {
00273         /* asctime format 'Fri Feb 2 2007 07:30:05'. */
00274         str = TimeParseMonth(str, &dts.tm_mon);
00275         str = skip_spaces(str);
00276         str = parse_digits(str, &dts.tm_mday);
00277         str = skip_spaces(str);
00278         str = TimeParseYear(str, &dts.tm_year);
00279         str = skip_spaces(str);
00280         str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec);
00281     }
00282     else if (*str) {
00283         /* RFC 850 'Friday, 02-Feb-2007 07:30:05 GMT'. */
00284         /* RFC 1123 'Fri, 02 Feb 2007 07:30:05 GMT'. */
00285         str = TimeParseDmy(str, &dts.tm_mday, &dts.tm_mon, &dts.tm_year);
00286         str = skip_spaces(str);
00287         str = TimeParseHms(str, &dts.tm_hour, &dts.tm_min, &dts.tm_sec);
00288     }
00289     str = skip_spaces(str);
00290     if (strcmp(str, "GMT")) {
00291         return mktime(&dts);
00292     }
00293     return _mkgmtime(&dts);
00294 }
00295 
00303 char *Rfc1123TimeString(struct _tm *tm)
00304 {
00305     sprintf(rfc1123_buf, "%s, %02d %s %04d %02d:%02d:%02d",
00306             wkdays[tm->tm_wday], 
00307             tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
00308             tm->tm_hour, tm->tm_min, tm->tm_sec);
00309 
00310     return rfc1123_buf;
00311 }

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