00001 #include <time.h> 00002 00003 /* Converts struct tm to time_t, assuming the data in tm is UTC rather 00004 than local timezone. 00005 00006 mktime is similar but assumes struct tm, also known as the 00007 "broken-down" form of time, is in local time zone. mktime_from_utc 00008 uses mktime to make the conversion understanding that an offset 00009 will be introduced by the local time assumption. 00010 00011 mktime_from_utc then measures the introduced offset by applying 00012 gmtime to the initial result and applying mktime to the resulting 00013 "broken-down" form. The difference between the two mktime results 00014 is the measured offset which is then subtracted from the initial 00015 mktime result to yield a calendar time which is the value returned. 00016 00017 tm_isdst in struct tm is set to 0 to force mktime to introduce a 00018 consistent offset (the non DST offset) since tm and tm+o might be 00019 on opposite sides of a DST change. 00020 00021 Some implementations of mktime return -1 for the nonexistent 00022 localtime hour at the beginning of DST. In this event, use 00023 mktime(tm - 1hr) + 3600. 00024 00025 Schematically 00026 mktime(tm) --> t+o 00027 gmtime(t+o) --> tm+o 00028 mktime(tm+o) --> t+2o 00029 t+o - (t+2o - t+o) = t 00030 00031 Note that glibc contains a function of the same purpose named 00032 `timegm' (reverse of gmtime). But obviously, it is not universally 00033 available, and unfortunately it is not straightforwardly 00034 extractable for use here. Perhaps configure should detect timegm 00035 and use it where available. 00036 00037 Contributed by Roger Beeman <beeman@cisco.com>, with the help of 00038 Mark Baushke <mdb@cisco.com> and the rest of the Gurus at CISCO. 00039 Further improved by Roger with assistance from Edward J. Sabol 00040 based on input by Jamie Zawinski. */ 00041 00042 time_t 00043 mktime_from_utc (struct tm *t) 00044 { 00045 time_t tl, tb; 00046 struct tm *tg; 00047 00048 tl = mktime (t); 00049 if (tl == -1) 00050 { 00051 t->tm_hour--; 00052 tl = mktime (t); 00053 if (tl == -1) 00054 return -1; /* can't deal with output from strptime */ 00055 tl += 3600; 00056 } 00057 tg = gmtime (&tl); 00058 tg->tm_isdst = 0; 00059 tb = mktime (tg); 00060 if (tb == -1) 00061 { 00062 tg->tm_hour--; 00063 tb = mktime (tg); 00064 if (tb == -1) 00065 return -1; /* can't deal with output from gmtime */ 00066 tb += 3600; 00067 } 00068 return (tl - (tb - tl)); 00069 } 00070 00071 00072