Back to index

avfs  1.0.1
dates.c
Go to the documentation of this file.
00001 /* 
00002    Date manipulation routines
00003    Copyright (C) 1999-2001, Joe Orton <joe@light.plus.com>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009    
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018    MA 02111-1307, USA
00019 
00020 */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 
00026 #include <sys/types.h>
00027 
00028 #include <time.h>
00029 #ifdef HAVE_STDLIB_H
00030 #include <stdlib.h>
00031 #endif
00032 #include <stdio.h>
00033 
00034 #ifdef HAVE_STRING_H
00035 #include <string.h>
00036 #endif
00037 
00038 #ifdef HAVE_SNPRINTF_H
00039 #include "snprintf.h"
00040 #endif
00041 
00042 #include "ne_alloc.h"
00043 #include "dates.h"
00044 
00045 /* Generic date manipulation routines. */
00046 
00047 /* RFC1123: Sun, 06 Nov 1994 08:49:37 GMT */
00048 #define RFC1123_FORMAT "%3s, %02d %3s %4d %02d:%02d:%02d GMT"
00049 /* RFC850:  Sunday, 06-Nov-94 08:49:37 GMT */
00050 #define RFC1036_FORMAT "%s, %2d-%3s-%2d %2d:%2d:%2d GMT"
00051 /* asctime: Wed Jun 30 21:49:08 1993 */
00052 #define ASCTIME_FORMAT "%3s %3s %2d %2d:%2d:%2d %4d"
00053 
00054 static const char *rfc1123_weekdays[7] = { 
00055     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 
00056 };
00057 static const char *short_months[12] = { 
00058     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00059     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00060 };
00061 
00062 /* Returns the time/date GMT, in RFC1123-type format: eg
00063  *  Sun, 06 Nov 1994 08:49:37 GMT. */
00064 char *rfc1123_date(time_t anytime) {
00065     struct tm *gmt;
00066     char *ret;
00067     gmt = gmtime(&anytime);
00068     if (gmt == NULL)
00069        return NULL;
00070     ret = ne_malloc(29 + 1); /* dates are 29 chars long */
00071 /*  it goes: Sun, 06 Nov 1994 08:49:37 GMT */
00072     snprintf(ret, 30, RFC1123_FORMAT,
00073              rfc1123_weekdays[gmt->tm_wday], gmt->tm_mday, 
00074              short_months[gmt->tm_mon], 1900 + gmt->tm_year, 
00075              gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
00076     
00077     return ret;
00078 }
00079 
00080 /* Takes an RFC1123-formatted date string and returns the time_t.
00081  * Returns (time_t)-1 if the parse fails. */
00082 time_t rfc1123_parse(const char *date) 
00083 {
00084     struct tm gmt = {0};
00085     static char wkday[4], mon[4];
00086     int n;
00087 /*  it goes: Sun, 06 Nov 1994 08:49:37 GMT */
00088     n = sscanf(date, RFC1123_FORMAT,
00089            wkday, &gmt.tm_mday, mon, &gmt.tm_year, &gmt.tm_hour,
00090            &gmt.tm_min, &gmt.tm_sec);
00091     /* Is it portable to check n==7 here? */
00092     gmt.tm_year -= 1900;
00093     for (n=0; n<12; n++)
00094        if (strcmp(mon, short_months[n]) == 0)
00095            break;
00096     /* tm_mon comes out as 12 if the month is corrupt, which is desired,
00097      * since the mktime will then fail */
00098     gmt.tm_mon = n;
00099     return mktime(&gmt);
00100 }
00101 
00102 /* Takes a string containing a RFC1036-style date and returns the time_t */
00103 time_t rfc1036_parse(const char *date) 
00104 {
00105     struct tm gmt = {0};
00106     int n;
00107     static char wkday[10], mon[4];
00108     /* RFC850/1036 style dates: Sunday, 06-Nov-94 08:49:37 GMT */
00109     n = sscanf(date, RFC1036_FORMAT,
00110               wkday, &gmt.tm_mday, mon, &gmt.tm_year,
00111               &gmt.tm_hour, &gmt.tm_min, &gmt.tm_sec);
00112     /* portable to check n here? */
00113     for (n=0; n<12; n++)
00114        if (strcmp(mon, short_months[n]) == 0)
00115            break;
00116     /* tm_mon comes out as 12 if the month is corrupt, which is desired,
00117      * since the mktime will then fail */
00118     gmt.tm_mon = n;
00119     return mktime(&gmt);
00120 }
00121 
00122 
00123 /* (as)ctime dates are like:
00124  *    Wed Jun 30 21:49:08 1993
00125  */
00126 time_t asctime_parse(const char *date) 
00127 {
00128     struct tm gmt = {0};
00129     int n;
00130     static char wkday[4], mon[4];
00131     n = sscanf(date, ASCTIME_FORMAT,
00132               wkday, mon, &gmt.tm_mday, 
00133               &gmt.tm_hour, &gmt.tm_min, &gmt.tm_sec,
00134               &gmt.tm_year);
00135     /* portable to check n here? */
00136     for (n=0; n<12; n++)
00137        if (strcmp(mon, short_months[n]) == 0)
00138            break;
00139     /* tm_mon comes out as 12 if the month is corrupt, which is desired,
00140      * since the mktime will then fail */
00141     gmt.tm_mon = n;
00142     return mktime(&gmt);
00143 }
00144 
00145 #undef RFC1036_FORMAT
00146 #undef ASCTIME_FORMAT
00147 #undef RFC1123_FORMAT
00148 
00149 #ifdef RFC1123_TEST
00150 
00151 int main(int argc, char **argv) {
00152     time_t now, in;
00153     char *out;
00154     if (argc > 1) {
00155        printf("Got: %s\n", argv[1]);
00156        in = rfc1123_parse(argv[1]);
00157        printf("Parsed: %d\n", in);
00158        out = rfc1123_date(in);
00159        printf("Back again: %s\n", out);
00160     } else {
00161        now = time(NULL);
00162        out = rfc1123_date(now);
00163        in = rfc1123_parse(out);
00164        printf("time(NULL) = %d\n", now);
00165        printf("RFC1123 Time: [%s]\n", out);
00166        printf("Parsed = %d\n", in);
00167        out = rfc1123_date(in);
00168        printf("Back again: [%s]\n", out);
00169     }
00170     return 0;
00171 }
00172 
00173 #endif
00174 
00175