~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/util/gmtime.cc

  • Committer: Brian Aker
  • Date: 2011-01-12 06:45:23 UTC
  • mto: (2073.1.4 catalogs)
  • mto: This revision was merged to the branch mainline in revision 2080.
  • Revision ID: brian@tangent.org-20110112064523-rqhptaqbph22qmj1
RemoveĀ customĀ error.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
// time.c
3
 
//
4
 
// Time routines
5
 
//
6
 
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
7
 
//
8
 
// Redistribution and use in source and binary forms, with or without
9
 
// modification, are permitted provided that the following conditions
10
 
// are met:
11
 
// 
12
 
// 1. Redistributions of source code must retain the above copyright 
13
 
//    notice, this list of conditions and the following disclaimer.  
14
 
// 2. Redistributions in binary form must reproduce the above copyright
15
 
//    notice, this list of conditions and the following disclaimer in the
16
 
//    documentation and/or other materials provided with the distribution.  
17
 
// 3. Neither the name of the project nor the names of its contributors
18
 
//    may be used to endorse or promote products derived from this software
19
 
//    without specific prior written permission. 
20
 
// 
21
 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22
 
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
25
 
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
31
 
// SUCH DAMAGE.
32
 
// 
33
 
 
34
 
#include <config.h>
35
 
 
36
 
#include <drizzled/type/time.h>
37
 
#include <drizzled/util/gmtime.h>
38
 
 
39
 
namespace drizzled
40
 
{
41
 
namespace util
42
 
{
43
 
#define YEAR0                   1900
44
 
#define EPOCH_YR                1970
45
 
#define SECS_DAY                (24L * 60L * 60L)
46
 
#define LEAPYEAR(year)          (!((year) % 4) && (((year) % 100) || !((year) % 400)))
47
 
#define YEARSIZE(year)          (LEAPYEAR(year) ? 366 : 365)
48
 
#define FIRSTSUNDAY(timp)       (((timp)->tm_yday - (timp)->tm_wday + 420) % 7)
49
 
#define FIRSTDAYOF(timp)        (((timp)->tm_wday - (timp)->tm_yday + 420) % 7)
50
 
 
51
 
#define TIME_MAX                INT64_MIN
52
 
 
53
 
int _daylight = 0;                  // Non-zero if daylight savings time is used
54
 
long _dstbias = 0;                  // Offset for Daylight Saving Time
55
 
type::Time::epoch_t _timezone = 0;                 // Difference in seconds between GMT and local time
56
 
const char *_tzname[2] = {"GMT", "GMT"};  // Standard/daylight savings time zone names
57
 
 
58
 
const char *_days[] = 
59
 
{
60
 
  "Sunday", "Monday", "Tuesday", "Wednesday",
61
 
  "Thursday", "Friday", "Saturday"
62
 
};
63
 
 
64
 
const char *_days_abbrev[] = 
65
 
{
66
 
  "Sun", "Mon", "Tue", "Wed", 
67
 
  "Thu", "Fri", "Sat"
68
 
};
69
 
 
70
 
const char *_months[] = 
71
 
{
72
 
  "January", "February", "March",
73
 
  "April", "May", "June",
74
 
  "July", "August", "September",
75
 
  "October", "November", "December"
76
 
};
77
 
 
78
 
const char *_months_abbrev[] = 
79
 
{
80
 
  "Jan", "Feb", "Mar",
81
 
  "Apr", "May", "Jun",
82
 
  "Jul", "Aug", "Sep",
83
 
  "Oct", "Nov", "Dec"
84
 
};
85
 
 
86
 
const int _ytab[2][12] = 
87
 
{
88
 
  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
89
 
  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
90
 
};
91
 
 
92
 
struct tm *gmtime(const type::Time::epoch_t &timer, struct tm *tmbuf)
93
 
{
94
 
  uint64_t dayclock, dayno;
95
 
  int year = EPOCH_YR;
96
 
 
97
 
  if (timer < 0)
98
 
    return NULL;
99
 
 
100
 
  dayclock = (uint64_t) timer % SECS_DAY;
101
 
  dayno = (uint64_t) timer / SECS_DAY;
102
 
 
103
 
  tmbuf->tm_sec = dayclock % 60;
104
 
  tmbuf->tm_min = (dayclock % 3600) / 60;
105
 
  tmbuf->tm_hour = dayclock / 3600;
106
 
  tmbuf->tm_wday = (dayno + 4) % 7; // Day 0 was a thursday
107
 
  while (dayno >= (uint64_t) YEARSIZE(year)) 
108
 
  {
109
 
    dayno -= YEARSIZE(year);
110
 
    year++;
111
 
  }
112
 
  tmbuf->tm_year = year - YEAR0;
113
 
  tmbuf->tm_yday = dayno;
114
 
  tmbuf->tm_mon = 0;
115
 
  while (dayno >= (uint64_t) _ytab[LEAPYEAR(year)][tmbuf->tm_mon]) 
116
 
  {
117
 
    dayno -= _ytab[LEAPYEAR(year)][tmbuf->tm_mon];
118
 
    tmbuf->tm_mon++;
119
 
  }
120
 
  tmbuf->tm_mday = dayno + 1;
121
 
  tmbuf->tm_isdst = 0;
122
 
 
123
 
  return tmbuf;
124
 
}
125
 
 
126
 
void gmtime(const type::Time::epoch_t &timer, type::Time &tmbuf)
127
 
{
128
 
  uint64_t dayclock, dayno;
129
 
  int32_t year= EPOCH_YR;
130
 
 
131
 
  if (timer < 0)
132
 
    return;
133
 
 
134
 
  tmbuf.reset();
135
 
 
136
 
  dayclock= (uint64_t) timer % SECS_DAY;
137
 
  dayno= (uint64_t) timer / SECS_DAY;
138
 
 
139
 
  tmbuf.second= dayclock % 60;
140
 
  tmbuf.minute= (dayclock % 3600) / 60;
141
 
  tmbuf.hour= dayclock / 3600;
142
 
  while (dayno >= (uint64_t) YEARSIZE(year)) 
143
 
  {
144
 
    dayno -= YEARSIZE(year);
145
 
    year++;
146
 
  }
147
 
  tmbuf.year= year;
148
 
  while (dayno >= (uint64_t) _ytab[LEAPYEAR(year)][tmbuf.month]) 
149
 
  {
150
 
    dayno -= _ytab[LEAPYEAR(year)][tmbuf.month];
151
 
    tmbuf.month++;
152
 
  }
153
 
  tmbuf.month++;
154
 
  tmbuf.day= dayno +1;
155
 
  tmbuf.time_type= type::DRIZZLE_TIMESTAMP_DATETIME;
156
 
}
157
 
 
158
 
void localtime(const type::Time::epoch_t &timer, type::Time &tmbuf)
159
 
{
160
 
  type::Time::epoch_t t;
161
 
 
162
 
  t = timer - _timezone;
163
 
  return util::gmtime(t, tmbuf);
164
 
}
165
 
 
166
 
struct tm *localtime(const type::Time::epoch_t &timer, struct tm *tmbuf)
167
 
{
168
 
  type::Time::epoch_t t;
169
 
 
170
 
  t = timer - _timezone;
171
 
  return util::gmtime(t, tmbuf);
172
 
}
173
 
 
174
 
// We don't use this code.
175
 
#if 0
176
 
time_t mktime(struct tm *tmbuf)
177
 
{
178
 
  long day, year;
179
 
  int tm_year;
180
 
  int yday, month;
181
 
  /*unsigned*/ long seconds;
182
 
  int overflow;
183
 
  long dst;
184
 
 
185
 
  tmbuf->tm_min += tmbuf->tm_sec / 60;
186
 
  tmbuf->tm_sec %= 60;
187
 
  if (tmbuf->tm_sec < 0) 
188
 
  {
189
 
    tmbuf->tm_sec += 60;
190
 
    tmbuf->tm_min--;
191
 
  }
192
 
  tmbuf->tm_hour += tmbuf->tm_min / 60;
193
 
  tmbuf->tm_min = tmbuf->tm_min % 60;
194
 
  if (tmbuf->tm_min < 0) 
195
 
  {
196
 
    tmbuf->tm_min += 60;
197
 
    tmbuf->tm_hour--;
198
 
  }
199
 
  day = tmbuf->tm_hour / 24;
200
 
  tmbuf->tm_hour= tmbuf->tm_hour % 24;
201
 
  if (tmbuf->tm_hour < 0) 
202
 
  {
203
 
    tmbuf->tm_hour += 24;
204
 
    day--;
205
 
  }
206
 
  tmbuf->tm_year += tmbuf->tm_mon / 12;
207
 
  tmbuf->tm_mon %= 12;
208
 
  if (tmbuf->tm_mon < 0) 
209
 
  {
210
 
    tmbuf->tm_mon += 12;
211
 
    tmbuf->tm_year--;
212
 
  }
213
 
  day += (tmbuf->tm_mday - 1);
214
 
  while (day < 0) 
215
 
  {
216
 
    if(--tmbuf->tm_mon < 0) 
217
 
    {
218
 
      tmbuf->tm_year--;
219
 
      tmbuf->tm_mon = 11;
220
 
    }
221
 
    day += _ytab[LEAPYEAR(YEAR0 + tmbuf->tm_year)][tmbuf->tm_mon];
222
 
  }
223
 
  while (day >= _ytab[LEAPYEAR(YEAR0 + tmbuf->tm_year)][tmbuf->tm_mon]) 
224
 
  {
225
 
    day -= _ytab[LEAPYEAR(YEAR0 + tmbuf->tm_year)][tmbuf->tm_mon];
226
 
    if (++(tmbuf->tm_mon) == 12) 
227
 
    {
228
 
      tmbuf->tm_mon = 0;
229
 
      tmbuf->tm_year++;
230
 
    }
231
 
  }
232
 
  tmbuf->tm_mday = day + 1;
233
 
  year = EPOCH_YR;
234
 
  if (tmbuf->tm_year < year - YEAR0) return (time_t) -1;
235
 
  seconds = 0;
236
 
  day = 0;                      // Means days since day 0 now
237
 
  overflow = 0;
238
 
 
239
 
  // Assume that when day becomes negative, there will certainly
240
 
  // be overflow on seconds.
241
 
  // The check for overflow needs not to be done for leapyears
242
 
  // divisible by 400.
243
 
  // The code only works when year (1970) is not a leapyear.
244
 
  tm_year = tmbuf->tm_year + YEAR0;
245
 
 
246
 
  if (TIME_MAX / 365 < tm_year - year)
247
 
    overflow++;
248
 
  day = (tm_year - year) * 365;
249
 
  if (TIME_MAX - day < (tm_year - year) / 4 + 1) overflow++;
250
 
  day += (tm_year - year) / 4 + ((tm_year % 4) && tm_year % 4 < year % 4);
251
 
  day -= (tm_year - year) / 100 + ((tm_year % 100) && tm_year % 100 < year % 100);
252
 
  day += (tm_year - year) / 400 + ((tm_year % 400) && tm_year % 400 < year % 400);
253
 
 
254
 
  yday = month = 0;
255
 
  while (month < tmbuf->tm_mon)
256
 
  {
257
 
    yday += _ytab[LEAPYEAR(tm_year)][month];
258
 
    month++;
259
 
  }
260
 
  yday += (tmbuf->tm_mday - 1);
261
 
  if (day + yday < 0) overflow++;
262
 
  day += yday;
263
 
 
264
 
  tmbuf->tm_yday = yday;
265
 
  tmbuf->tm_wday = (day + 4) % 7;               // Day 0 was thursday (4)
266
 
 
267
 
  seconds = ((tmbuf->tm_hour * 60L) + tmbuf->tm_min) * 60L + tmbuf->tm_sec;
268
 
 
269
 
  if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++;
270
 
  seconds += day * SECS_DAY;
271
 
 
272
 
  // Now adjust according to timezone and daylight saving time
273
 
  if (((_timezone > 0) && (TIME_MAX - _timezone < seconds))
274
 
      || ((_timezone < 0) && (seconds < -_timezone)))
275
 
          overflow++;
276
 
  seconds += _timezone;
277
 
 
278
 
  if (tmbuf->tm_isdst)
279
 
    dst = _dstbias;
280
 
  else 
281
 
    dst = 0;
282
 
 
283
 
  if (dst > seconds) overflow++;        // dst is always non-negative
284
 
  seconds -= dst;
285
 
 
286
 
  if (overflow) return (time_t) -1;
287
 
 
288
 
  if ((time_t) seconds != seconds) return (time_t) -1;
289
 
  return (time_t) seconds;
290
 
}
291
 
#endif
292
 
 
293
 
} /* namespace util */
294
 
} /* namespace drizzled */