00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <config.h>
00035
00036 #include <drizzled/type/time.h>
00037 #include <drizzled/util/gmtime.h>
00038
00039 namespace drizzled
00040 {
00041 namespace util
00042 {
00043 #define YEAR0 1900
00044 #define EPOCH_YR 1970
00045 #define SECS_DAY (24L * 60L * 60L)
00046 #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
00047 #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
00048 #define FIRSTSUNDAY(timp) (((timp)->tm_yday - (timp)->tm_wday + 420) % 7)
00049 #define FIRSTDAYOF(timp) (((timp)->tm_wday - (timp)->tm_yday + 420) % 7)
00050
00051 #define TIME_MAX INT64_MIN
00052
00053 int _daylight = 0;
00054 long _dstbias = 0;
00055 type::Time::epoch_t _timezone = 0;
00056 const char *_tzname[2] = {"GMT", "GMT"};
00057
00058 const char *_days[] =
00059 {
00060 "Sunday", "Monday", "Tuesday", "Wednesday",
00061 "Thursday", "Friday", "Saturday"
00062 };
00063
00064 const char *_days_abbrev[] =
00065 {
00066 "Sun", "Mon", "Tue", "Wed",
00067 "Thu", "Fri", "Sat"
00068 };
00069
00070 const char *_months[] =
00071 {
00072 "January", "February", "March",
00073 "April", "May", "June",
00074 "July", "August", "September",
00075 "October", "November", "December"
00076 };
00077
00078 const char *_months_abbrev[] =
00079 {
00080 "Jan", "Feb", "Mar",
00081 "Apr", "May", "Jun",
00082 "Jul", "Aug", "Sep",
00083 "Oct", "Nov", "Dec"
00084 };
00085
00086 const int _ytab[2][12] =
00087 {
00088 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
00089 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
00090 };
00091
00092 struct tm *gmtime(const type::Time::epoch_t &timer, struct tm *tmbuf)
00093 {
00094 uint64_t dayclock, dayno;
00095 int year = EPOCH_YR;
00096
00097 if (timer < 0)
00098 return NULL;
00099
00100 dayclock = (uint64_t) timer % SECS_DAY;
00101 dayno = (uint64_t) timer / SECS_DAY;
00102
00103 tmbuf->tm_sec = dayclock % 60;
00104 tmbuf->tm_min = (dayclock % 3600) / 60;
00105 tmbuf->tm_hour = dayclock / 3600;
00106 tmbuf->tm_wday = (dayno + 4) % 7;
00107 while (dayno >= (uint64_t) YEARSIZE(year))
00108 {
00109 dayno -= YEARSIZE(year);
00110 year++;
00111 }
00112 tmbuf->tm_year = year - YEAR0;
00113 tmbuf->tm_yday = dayno;
00114 tmbuf->tm_mon = 0;
00115 while (dayno >= (uint64_t) _ytab[LEAPYEAR(year)][tmbuf->tm_mon])
00116 {
00117 dayno -= _ytab[LEAPYEAR(year)][tmbuf->tm_mon];
00118 tmbuf->tm_mon++;
00119 }
00120 tmbuf->tm_mday = dayno + 1;
00121 tmbuf->tm_isdst = 0;
00122
00123 return tmbuf;
00124 }
00125
00126 void gmtime(const type::Time::epoch_t &timer, type::Time &tmbuf)
00127 {
00128 uint64_t dayclock, dayno;
00129 int32_t year= EPOCH_YR;
00130
00131 if (timer < 0)
00132 return;
00133
00134 tmbuf.reset();
00135
00136 dayclock= (uint64_t) timer % SECS_DAY;
00137 dayno= (uint64_t) timer / SECS_DAY;
00138
00139 tmbuf.second= dayclock % 60;
00140 tmbuf.minute= (dayclock % 3600) / 60;
00141 tmbuf.hour= dayclock / 3600;
00142 while (dayno >= (uint64_t) YEARSIZE(year))
00143 {
00144 dayno -= YEARSIZE(year);
00145 year++;
00146 }
00147 tmbuf.year= year;
00148 while (dayno >= (uint64_t) _ytab[LEAPYEAR(year)][tmbuf.month])
00149 {
00150 dayno -= _ytab[LEAPYEAR(year)][tmbuf.month];
00151 tmbuf.month++;
00152 }
00153 tmbuf.month++;
00154 tmbuf.day= dayno +1;
00155 tmbuf.time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
00156 }
00157
00158 void localtime(const type::Time::epoch_t &timer, type::Time &tmbuf)
00159 {
00160 type::Time::epoch_t t;
00161
00162 t = timer - _timezone;
00163 return util::gmtime(t, tmbuf);
00164 }
00165
00166 struct tm *localtime(const type::Time::epoch_t &timer, struct tm *tmbuf)
00167 {
00168 type::Time::epoch_t t;
00169
00170 t = timer - _timezone;
00171 return util::gmtime(t, tmbuf);
00172 }
00173
00174
00175 #if 0
00176 time_t mktime(struct tm *tmbuf)
00177 {
00178 long day, year;
00179 int tm_year;
00180 int yday, month;
00181 long seconds;
00182 int overflow;
00183 long dst;
00184
00185 tmbuf->tm_min += tmbuf->tm_sec / 60;
00186 tmbuf->tm_sec %= 60;
00187 if (tmbuf->tm_sec < 0)
00188 {
00189 tmbuf->tm_sec += 60;
00190 tmbuf->tm_min--;
00191 }
00192 tmbuf->tm_hour += tmbuf->tm_min / 60;
00193 tmbuf->tm_min = tmbuf->tm_min % 60;
00194 if (tmbuf->tm_min < 0)
00195 {
00196 tmbuf->tm_min += 60;
00197 tmbuf->tm_hour--;
00198 }
00199 day = tmbuf->tm_hour / 24;
00200 tmbuf->tm_hour= tmbuf->tm_hour % 24;
00201 if (tmbuf->tm_hour < 0)
00202 {
00203 tmbuf->tm_hour += 24;
00204 day--;
00205 }
00206 tmbuf->tm_year += tmbuf->tm_mon / 12;
00207 tmbuf->tm_mon %= 12;
00208 if (tmbuf->tm_mon < 0)
00209 {
00210 tmbuf->tm_mon += 12;
00211 tmbuf->tm_year--;
00212 }
00213 day += (tmbuf->tm_mday - 1);
00214 while (day < 0)
00215 {
00216 if(--tmbuf->tm_mon < 0)
00217 {
00218 tmbuf->tm_year--;
00219 tmbuf->tm_mon = 11;
00220 }
00221 day += _ytab[LEAPYEAR(YEAR0 + tmbuf->tm_year)][tmbuf->tm_mon];
00222 }
00223 while (day >= _ytab[LEAPYEAR(YEAR0 + tmbuf->tm_year)][tmbuf->tm_mon])
00224 {
00225 day -= _ytab[LEAPYEAR(YEAR0 + tmbuf->tm_year)][tmbuf->tm_mon];
00226 if (++(tmbuf->tm_mon) == 12)
00227 {
00228 tmbuf->tm_mon = 0;
00229 tmbuf->tm_year++;
00230 }
00231 }
00232 tmbuf->tm_mday = day + 1;
00233 year = EPOCH_YR;
00234 if (tmbuf->tm_year < year - YEAR0) return (time_t) -1;
00235 seconds = 0;
00236 day = 0;
00237 overflow = 0;
00238
00239
00240
00241
00242
00243
00244 tm_year = tmbuf->tm_year + YEAR0;
00245
00246 if (TIME_MAX / 365 < tm_year - year)
00247 overflow++;
00248 day = (tm_year - year) * 365;
00249 if (TIME_MAX - day < (tm_year - year) / 4 + 1) overflow++;
00250 day += (tm_year - year) / 4 + ((tm_year % 4) && tm_year % 4 < year % 4);
00251 day -= (tm_year - year) / 100 + ((tm_year % 100) && tm_year % 100 < year % 100);
00252 day += (tm_year - year) / 400 + ((tm_year % 400) && tm_year % 400 < year % 400);
00253
00254 yday = month = 0;
00255 while (month < tmbuf->tm_mon)
00256 {
00257 yday += _ytab[LEAPYEAR(tm_year)][month];
00258 month++;
00259 }
00260 yday += (tmbuf->tm_mday - 1);
00261 if (day + yday < 0) overflow++;
00262 day += yday;
00263
00264 tmbuf->tm_yday = yday;
00265 tmbuf->tm_wday = (day + 4) % 7;
00266
00267 seconds = ((tmbuf->tm_hour * 60L) + tmbuf->tm_min) * 60L + tmbuf->tm_sec;
00268
00269 if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
00270 seconds += day * SECS_DAY;
00271
00272
00273 if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
00274 || ((_timezone < 0) && (seconds < -_timezone)))
00275 overflow++;
00276 seconds += _timezone;
00277
00278 if (tmbuf->tm_isdst)
00279 dst = _dstbias;
00280 else
00281 dst = 0;
00282
00283 if (dst > seconds) overflow++;
00284 seconds -= dst;
00285
00286 if (overflow) return (time_t) -1;
00287
00288 if ((time_t) seconds != seconds) return (time_t) -1;
00289 return (time_t) seconds;
00290 }
00291 #endif
00292
00293 }
00294 }