Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright 2001-2004 Brandon Long
      3  * All Rights Reserved.
      4  *
      5  * ClearSilver Templating System
      6  *
      7  * This code is made available under the terms of the ClearSilver License.
      8  * http://www.clearsilver.net/license.hdf
      9  *
     10  */
     11 
     12 #include "cs_config.h"
     13 
     14 #include <stdlib.h>
     15 #include <stdio.h>
     16 #include <string.h>
     17 #include <time.h>
     18 #include <limits.h>
     19 #include "util/neo_misc.h"
     20 #include "neo_date.h"
     21 
     22 /* This is pretty much a HACK.  Eventually, we might bring the parsing
     23  * and stuff into this library (we can use the public domain source code
     24  * from ftp://elsie.nci.nih.gov/pub/ as a base)
     25  *
     26  * For now, we just do a putenv(TZ)... which sucks, especially since
     27  * many versions of putenv do a strdup... and then leak the memory the
     28  * next time you putenv the same var.
     29  */
     30 
     31 /* Since this is set to a partial filename and TZ=, it can't be bigger
     32  * than this */
     33 static char TzBuf[_POSIX_PATH_MAX + 4];
     34 
     35 static int time_set_tz (const char *mytimezone)
     36 {
     37   snprintf (TzBuf, sizeof(TzBuf), "TZ=%s", mytimezone);
     38   putenv(TzBuf);
     39   tzset();
     40   return 0;
     41 }
     42 
     43 void neo_time_expand (const time_t tt, const char *mytimezone, struct tm *ttm)
     44 {
     45   const char *cur_tz = getenv("TZ");
     46   int change_back = 0;
     47   if (cur_tz == NULL || strcmp(mytimezone, cur_tz)) {
     48     time_set_tz (mytimezone);
     49     change_back = 1;
     50   }
     51   localtime_r (&tt, ttm);
     52   if (cur_tz && change_back) {
     53     time_set_tz(cur_tz);
     54   }
     55 }
     56 
     57 time_t neo_time_compact (struct tm *ttm, const char *mytimezone)
     58 {
     59   time_t r;
     60   int save_isdst = ttm->tm_isdst;
     61 
     62   const char *cur_tz = getenv("TZ");
     63   int change_back = 0;
     64   if (cur_tz == NULL || strcmp(mytimezone, cur_tz)) {
     65     time_set_tz (mytimezone);
     66     change_back = 1;
     67   }
     68   ttm->tm_isdst = -1;
     69   r = mktime(ttm);
     70   ttm->tm_isdst = save_isdst;
     71   if (cur_tz && change_back) {
     72     time_set_tz(cur_tz);
     73   }
     74   return r;
     75 }
     76 
     77 /* Hefted from NCSA HTTPd src/util.c -- What a pain in the ass. */
     78 long neo_tz_offset(struct tm *ttm) {
     79   /* We assume here that HAVE_TM_ZONE implies HAVE_TM_GMTOFF and
     80    * HAVE_TZNAME implies HAVE_TIMEZONE since AC_STRUCT_TIMEZONE defines
     81    * the former and not the latter */
     82 #if defined(HAVE_TM_ZONE)
     83   return ttm->tm_gmtoff;
     84 #elif defined(HAVE_TZNAME)
     85   long tz;
     86 #ifndef __CYGWIN__
     87   tz = - timezone;
     88 #else
     89   tz = - _timezone;
     90 #endif
     91   if(ttm->tm_isdst)
     92     tz += 3600;
     93   return tz;
     94 #else
     95   long tz;
     96   struct tm loc_tm, gmt_tm;
     97   time_t tt;
     98 
     99   /* We probably shouldn't use the _r versions here since this
    100    * is for older platforms... */
    101   tt = time(NULL);
    102   localtime_r(&tt, &loc_tm);
    103   gmtime_r(&tt, &gmt_tm);
    104 
    105   tz = mktime(&loc_tm) - mktime(&gmt_tm);
    106   return tz;
    107 #endif /* GMT OFFSet Crap */
    108 }
    109 
    110