~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/util/gmtime.cc

  • Committer: Brian Aker
  • Date: 2011-02-17 10:09:00 UTC
  • mfrom: (2173.2.1 clean-include-usuage)
  • Revision ID: brian@tangent.org-20110217100900-4tpuxxzdl1sj00sh
Merge Monty for headers.

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 */