Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

date.c

00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: date.c,v 1.11 2007/10/26 08:57:59 tho Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <time.h>
00015 #include <ctype.h>
00016 #include <fcntl.h>
00017 #include <unistd.h>
00018 #include <dirent.h>
00019 #include <sys/stat.h>
00020 #include <u/libu.h>
00021 #include <klone/os.h>
00022 #include <klone/utils.h>
00023 
00029 const char* days3[] = { 
00030     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 
00031 };
00032 const char* days[] = { 
00033     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",  "Friday",
00034     "Saturday", "Sunday" 
00035 };
00036 const char* months[] = { 
00037     "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
00038     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 
00039 };
00040 
00041 static int month_idx(const char *mon)
00042 {
00043     int i;
00044 
00045     dbg_return_if (mon == NULL, -1);
00046     
00047     for(i = 0; i < 12; ++i)
00048         if(strcasecmp(months[i], mon) == 0)
00049             return i;
00050 
00051     return -1;
00052 }
00053 
00066 int u_asctime_to_tt(const char *str, time_t *tp)
00067 {
00068     enum { BUFSZ = 64 };
00069     char wday[BUFSZ], mon[BUFSZ];
00070     unsigned int day, year, hour, min, sec;
00071     struct tm tm;
00072     int i;
00073 
00074     dbg_return_if (str == NULL, ~0);
00075     dbg_return_if (tp == NULL, ~0);
00076     dbg_return_if (strlen(str) >= BUFSZ, ~0);
00077 
00078     dbg_err_if((i = sscanf(str, "%s %s %u %u:%u:%u %u", wday, 
00079         mon, &day, &hour, &min, &sec, &year)) != 7);
00080 
00081     memset(&tm, 0, sizeof(struct tm));
00082 
00083     /* time */
00084     tm.tm_sec = sec; tm.tm_min = min; tm.tm_hour = hour;
00085 
00086     /* date */
00087     tm.tm_mday = day; 
00088     tm.tm_mon = month_idx(mon);
00089     tm.tm_year = year - 1900;
00090 
00091     dbg_err_if(tm.tm_mon < 0);
00092 
00093     *tp = timegm(&tm);
00094     
00095     return 0;
00096 err:
00097     return ~0;
00098 }
00099 
00112 int u_rfc850_to_tt(const char *str, time_t *tp)
00113 {
00114     enum { BUFSZ = 64 };
00115     char wday[BUFSZ], mon[BUFSZ], tzone[BUFSZ];
00116     unsigned int day, year, hour, min, sec;
00117     struct tm tm;
00118     int i;
00119     char c;
00120 
00121     dbg_return_if (str == NULL, ~0);
00122     dbg_return_if (tp == NULL, ~0);
00123     dbg_return_if (strlen(str) >= BUFSZ, ~0);
00124 
00125     dbg_err_if((i = sscanf(str, "%[^,], %u%c%[^-]%c%u %u:%u:%u %s", wday, 
00126         &day, &c, mon, &c, &year, &hour, &min, &sec, tzone)) != 10);
00127 
00128     memset(&tm, 0, sizeof(struct tm));
00129 
00130     /* time */
00131     tm.tm_sec = sec; tm.tm_min = min; tm.tm_hour = hour;
00132 
00133     /* date */
00134     tm.tm_mday = day; 
00135     tm.tm_mon = month_idx(mon);
00136     tm.tm_year = year - 1900;
00137 
00138     dbg_err_if(tm.tm_mon < 0);
00139 
00140 #ifdef HAVE_TMZONE
00141     /* time zone */
00142     tm.tm_zone = tzone;
00143 #endif
00144 
00145     *tp = timegm(&tm);
00146 
00147     return 0;
00148 err:
00149     return ~0;
00150 }
00151 
00164 int u_rfc822_to_tt(const char *str, time_t *tp)
00165 {
00166     enum { BUFSZ = 64 };
00167     char wday[BUFSZ], mon[BUFSZ], tzone[BUFSZ];
00168     unsigned int day, year, hour, min, sec;
00169     struct tm tm;
00170 
00171     dbg_return_if (str == NULL, ~0);
00172     dbg_return_if (tp == NULL, ~0);
00173     dbg_return_if (strlen(str) >= BUFSZ, ~0);
00174 
00175     dbg_err_if(sscanf(str, "%[^,], %u %s %u %u:%u:%u %s", wday, 
00176         &day, mon, &year, &hour, &min, &sec, tzone) != 8);
00177 
00178     memset(&tm, 0, sizeof(struct tm));
00179 
00180     /* time */
00181     tm.tm_sec = sec; tm.tm_min = min; tm.tm_hour = hour;
00182 
00183     /* date */
00184     tm.tm_mday = day; 
00185     tm.tm_mon = month_idx(mon);
00186     tm.tm_year = year - 1900; 
00187 
00188     dbg_err_if(tm.tm_mon < 0);
00189 
00190 #ifdef HAVE_TMZONE
00191     /* time zone */
00192     tm.tm_zone = tzone;
00193 #endif
00194 
00195     *tp = timegm(&tm);
00196 
00197     return 0;
00198 err:
00199     return ~0;
00200 }
00201 
00214 int u_httpdate_to_tt(const char *str, time_t *tp)
00215 {
00216     dbg_return_if (str == NULL, ~0);
00217     dbg_return_if (tp == NULL, ~0);
00218     dbg_return_if (strlen(str) < 4, ~0);
00219 
00220     if(str[3] == ',')
00221         return u_rfc822_to_tt(str, tp);
00222     else if(str[3] == ' ')
00223         return u_asctime_to_tt(str, tp);
00224 
00225     return u_rfc850_to_tt(str, tp);
00226 }
00227 
00242 int u_tt_to_rfc822(char dst[], time_t ts)
00243 {
00244     enum { RFC822_DATE_BUFSZ = 32 };
00245     char buf[RFC822_DATE_BUFSZ];
00246     struct tm tm;
00247 
00248     dbg_return_if (dst == NULL, ~0);
00249 
00250 #ifdef OS_WIN
00251     memcpy(&tm, gmtime(&ts), sizeof(tm));
00252 #else
00253     dbg_err_if(gmtime_r(&ts, &tm) == NULL);
00254 #endif
00255 
00256     dbg_err_if(tm.tm_wday > 6 || tm.tm_wday < 0);
00257     dbg_err_if(tm.tm_mon > 11 || tm.tm_mon < 0);
00258 
00259     dbg_err_if(u_snprintf(buf, RFC822_DATE_BUFSZ, 
00260                 "%s, %02u %s %02u %02u:%02u:%02u GMT",
00261                 days3[tm.tm_wday], 
00262                 tm.tm_mday, months[tm.tm_mon], tm.tm_year + 1900, 
00263                 tm.tm_hour, tm.tm_min, tm.tm_sec));
00264 
00265     /* copy out */
00266     u_sstrncpy(dst, buf, RFC822_DATE_BUFSZ - 1);
00267 
00268     return 0;
00269 err:
00270     return ~0;
00271 }
00272