~drizzle-trunk/drizzle/development

520.4.14 by Monty Taylor
Removed korr.h and tztime.h from common_includes. Also removed the HAVE_DTRACE block and stuck it in autoconf.
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
1 by brian
clean slate
19
20
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
21
#include "config.h"
1237.9.4 by Padraig O'Sullivan
Removed the inclusion of drizzled/field.h in the server_includes header file.
22
#include "drizzled/tzfile.h"
23
#include "drizzled/tztime.h"
24
#include "drizzled/gettext.h"
25
#include "drizzled/session.h"
1237.9.8 by Monty Taylor
Fixed solaris build.
26
#include "drizzled/time_functions.h"
1 by brian
clean slate
27
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
28
namespace drizzled
29
{
30
1 by brian
clean slate
31
/* Structure describing local time type (e.g. Moscow summer time (MSD)) */
32
typedef struct ttinfo
33
{
34
  long tt_gmtoff; // Offset from UTC in seconds
482 by Brian Aker
Remove uint.
35
  uint32_t tt_isdst;   // Is daylight saving time or not. Used to set tm_isdst
36
  uint32_t tt_abbrind; // Index of start of abbreviation for this time type.
1 by brian
clean slate
37
  /*
38
    We don't use tt_ttisstd and tt_ttisgmt members of original elsie-code
39
    struct since we don't support POSIX-style TZ descriptions in variables.
40
  */
41
} TRAN_TYPE_INFO;
42
43
/* Structure describing leap-second corrections. */
44
typedef struct lsinfo
45
{
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
46
  time_t ls_trans; // Transition time
1 by brian
clean slate
47
  long      ls_corr;  // Correction to apply
48
} LS_INFO;
49
50
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
51
  Structure with information describing ranges of time_t shifted to local
52
  time (time_t + offset). Used for local DRIZZLE_TIME -> time_t conversion.
1 by brian
clean slate
53
  See comments for TIME_to_gmt_sec() for more info.
54
*/
55
typedef struct revtinfo
56
{
57
  long rt_offset; // Offset of local time from UTC in seconds
482 by Brian Aker
Remove uint.
58
  uint32_t rt_type;    // Type of period 0 - Normal period. 1 - Spring time-gap
1 by brian
clean slate
59
} REVT_INFO;
60
61
62
/*
63
  Structure which fully describes time zone which is
64
  described in our db or in zoneinfo files.
65
*/
66
typedef struct st_time_zone_info
67
{
482 by Brian Aker
Remove uint.
68
  uint32_t leapcnt;  // Number of leap-second corrections
69
  uint32_t timecnt;  // Number of transitions between time types
70
  uint32_t typecnt;  // Number of local time types
71
  uint32_t charcnt;  // Number of characters used for abbreviations
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
72
  uint32_t revcnt;   // Number of transition descr. for TIME->time_t conversion
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
73
  /* The following are dynamical arrays are allocated in memory::Root */
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
74
  time_t *ats;       // Times of transitions between time types
481 by Brian Aker
Remove all of uchar.
75
  unsigned char	*types; // Local time types for transitions
1 by brian
clean slate
76
  TRAN_TYPE_INFO *ttis; // Local time types descriptions
77
  /* Storage for local time types abbreviations. They are stored as ASCIIZ */
78
  char *chars;
79
  /*
80
    Leap seconds corrections descriptions, this array is shared by
81
    all time zones who use leap seconds.
82
  */
83
  LS_INFO *lsis;
84
  /*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
85
    Starting points and descriptions of shifted time_t (time_t + offset)
86
    ranges on which shifted time_t -> time_t mapping is linear or undefined.
87
    Used for tm -> time_t conversion.
1 by brian
clean slate
88
  */
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
89
  time_t *revts;
1 by brian
clean slate
90
  REVT_INFO *revtis;
91
  /*
92
    Time type which is used for times smaller than first transition or if
93
    there are no transitions at all.
94
  */
95
  TRAN_TYPE_INFO *fallback_tti;
96
97
} TIME_ZONE_INFO;
98
99
100
#if !defined(TZINFO2SQL)
101
482 by Brian Aker
Remove uint.
102
static const uint32_t mon_lengths[2][MONS_PER_YEAR]=
1 by brian
clean slate
103
{
104
  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
105
  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
106
};
107
482 by Brian Aker
Remove uint.
108
static const uint32_t mon_starts[2][MONS_PER_YEAR]=
1 by brian
clean slate
109
{
110
  { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
111
  { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
112
};
113
482 by Brian Aker
Remove uint.
114
static const uint32_t year_lengths[2]=
1 by brian
clean slate
115
{
116
  DAYS_PER_NYEAR, DAYS_PER_LYEAR
117
};
118
119
#define LEAPS_THRU_END_OF(y)  ((y) / 4 - (y) / 100 + (y) / 400)
120
121
122
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
123
  Converts time from time_t representation (seconds in UTC since Epoch)
1 by brian
clean slate
124
  to broken down representation using given local time zone offset.
125
126
  SYNOPSIS
127
    sec_to_TIME()
128
      tmp    - pointer to structure for broken down representation
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
129
      t      - time_t value to be converted
1 by brian
clean slate
130
      offset - local time zone offset
131
132
  DESCRIPTION
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
133
    Convert time_t with offset to DRIZZLE_TIME struct. Differs from timesub
1 by brian
clean slate
134
    (from elsie code) because doesn't contain any leap correction and
135
    TM_GMTOFF and is_dst setting and contains some MySQL specific
136
    initialization. Funny but with removing of these we almost have
137
    glibc's offtime function.
138
*/
139
static void
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
140
sec_to_TIME(DRIZZLE_TIME * tmp, time_t t, long offset)
1 by brian
clean slate
141
{
142
  long days;
143
  long rem;
144
  int y;
145
  int yleap;
482 by Brian Aker
Remove uint.
146
  const uint32_t *ip;
1 by brian
clean slate
147
148
  days= (long) (t / SECS_PER_DAY);
149
  rem=  (long) (t % SECS_PER_DAY);
150
151
  /*
152
    We do this as separate step after dividing t, because this
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
153
    allows us handle times near time_t bounds without overflows.
1 by brian
clean slate
154
  */
155
  rem+= offset;
156
  while (rem < 0)
157
  {
158
    rem+= SECS_PER_DAY;
159
    days--;
160
  }
161
  while (rem >= SECS_PER_DAY)
162
  {
163
    rem -= SECS_PER_DAY;
164
    days++;
165
  }
895 by Brian Aker
Completion (?) of uint conversion.
166
  tmp->hour= (uint32_t)(rem / SECS_PER_HOUR);
1 by brian
clean slate
167
  rem= rem % SECS_PER_HOUR;
895 by Brian Aker
Completion (?) of uint conversion.
168
  tmp->minute= (uint32_t)(rem / SECS_PER_MIN);
1 by brian
clean slate
169
  /*
170
    A positive leap second requires a special
171
    representation.  This uses "... ??:59:60" et seq.
172
  */
895 by Brian Aker
Completion (?) of uint conversion.
173
  tmp->second= (uint32_t)(rem % SECS_PER_MIN);
1 by brian
clean slate
174
175
  y= EPOCH_YEAR;
176
  while (days < 0 || days >= (long)year_lengths[yleap= isleap(y)])
177
  {
178
    int	newy;
179
180
    newy= y + days / DAYS_PER_NYEAR;
181
    if (days < 0)
182
      newy--;
183
    days-= (newy - y) * DAYS_PER_NYEAR +
184
           LEAPS_THRU_END_OF(newy - 1) -
185
           LEAPS_THRU_END_OF(y - 1);
186
    y= newy;
187
  }
188
  tmp->year= y;
189
190
  ip= mon_lengths[yleap];
191
  for (tmp->month= 0; days >= (long) ip[tmp->month]; tmp->month++)
192
    days= days - (long) ip[tmp->month];
193
  tmp->month++;
895 by Brian Aker
Completion (?) of uint conversion.
194
  tmp->day= (uint32_t)(days + 1);
1 by brian
clean slate
195
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
196
  /* filling MySQL specific DRIZZLE_TIME members */
1 by brian
clean slate
197
  tmp->neg= 0; tmp->second_part= 0;
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
198
  tmp->time_type= DRIZZLE_TIMESTAMP_DATETIME;
1 by brian
clean slate
199
}
200
201
202
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
203
  Find time range wich contains given time_t value
1 by brian
clean slate
204
205
  SYNOPSIS
206
    find_time_range()
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
207
      t                - time_t value for which we looking for range
1 by brian
clean slate
208
      range_boundaries - sorted array of range starts.
209
      higher_bound     - number of ranges
210
211
  DESCRIPTION
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
212
    Performs binary search for range which contains given time_t value.
213
    It has sense if number of ranges is greater than zero and time_t value
1 by brian
clean slate
214
    is greater or equal than beginning of first range. It also assumes that
722.1.8 by Monty Taylor
Merged from Toru - removal of my_time_t.
215
    t belongs to some range specified.
1 by brian
clean slate
216
217
    With this localtime_r on real data may takes less time than with linear
218
    search (I've seen 30% speed up).
219
220
  RETURN VALUE
221
    Index of range to which t belongs
222
*/
223
static uint
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
224
find_time_range(time_t t, const time_t *range_boundaries,
482 by Brian Aker
Remove uint.
225
                uint32_t higher_bound)
1 by brian
clean slate
226
{
482 by Brian Aker
Remove uint.
227
  uint32_t i, lower_bound= 0;
1 by brian
clean slate
228
229
  /*
230
    Function will work without this assertion but result would be meaningless.
231
  */
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
232
  assert(higher_bound > 0 && t >= range_boundaries[0]);
1 by brian
clean slate
233
234
  /*
235
    Do binary search for minimal interval which contain t. We preserve:
236
    range_boundaries[lower_bound] <= t < range_boundaries[higher_bound]
237
    invariant and decrease this higher_bound - lower_bound gap twice
238
    times on each step.
239
  */
240
241
  while (higher_bound - lower_bound > 1)
242
  {
243
    i= (lower_bound + higher_bound) >> 1;
244
    if (range_boundaries[i] <= t)
245
      lower_bound= i;
246
    else
247
      higher_bound= i;
248
  }
249
  return lower_bound;
250
}
251
252
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
253
  Find local time transition for given time_t.
1 by brian
clean slate
254
255
  SYNOPSIS
256
    find_transition_type()
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
257
      t   - time_t value to be converted
1 by brian
clean slate
258
      sp  - pointer to struct with time zone description
259
260
  RETURN VALUE
261
    Pointer to structure in time zone description describing
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
262
    local time type for given time_t.
1 by brian
clean slate
263
*/
264
static
265
const TRAN_TYPE_INFO *
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
266
find_transition_type(time_t t, const TIME_ZONE_INFO *sp)
1 by brian
clean slate
267
{
268
  if (unlikely(sp->timecnt == 0 || t < sp->ats[0]))
269
  {
270
    /*
271
      If we have not any transitions or t is before first transition let
272
      us use fallback time type.
273
    */
274
    return sp->fallback_tti;
275
  }
276
277
  /*
278
    Do binary search for minimal interval between transitions which
279
    contain t. With this localtime_r on real data may takes less
280
    time than with linear search (I've seen 30% speed up).
281
  */
282
  return &(sp->ttis[sp->types[find_time_range(t, sp->ats, sp->timecnt)]]);
283
}
284
285
286
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
287
  Converts time in time_t representation (seconds in UTC since Epoch) to
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
288
  broken down DRIZZLE_TIME representation in local time zone.
1 by brian
clean slate
289
290
  SYNOPSIS
291
    gmt_sec_to_TIME()
292
      tmp          - pointer to structure for broken down represenatation
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
293
      sec_in_utc   - time_t value to be converted
1 by brian
clean slate
294
      sp           - pointer to struct with time zone description
295
296
  TODO
297
    We can improve this function by creating joined array of transitions and
298
    leap corrections. This will require adding extra field to TRAN_TYPE_INFO
299
    for storing number of "extra" seconds to minute occured due to correction
300
    (60th and 61st second, look how we calculate them as "hit" in this
301
    function).
302
    Under realistic assumptions about frequency of transitions the same array
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
303
    can be used for DRIZZLE_TIME -> time_t conversion. For this we need to
1 by brian
clean slate
304
    implement tweaked binary search which will take into account that some
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
305
    DRIZZLE_TIME has two matching time_t ranges and some of them have none.
1 by brian
clean slate
306
*/
307
static void
685.3.4 by Toru Maesaka
Fixed the issues pointed out by Jay's code review
308
gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t sec_in_utc, const TIME_ZONE_INFO *sp)
1 by brian
clean slate
309
{
310
  const TRAN_TYPE_INFO *ttisp;
311
  const LS_INFO *lp;
312
  long  corr= 0;
313
  int   hit= 0;
314
  int   i;
315
316
  /*
317
    Find proper transition (and its local time type) for our sec_in_utc value.
318
    Funny but again by separating this step in function we receive code
319
    which very close to glibc's code. No wonder since they obviously use
320
    the same base and all steps are sensible.
321
  */
322
  ttisp= find_transition_type(sec_in_utc, sp);
323
324
  /*
325
    Let us find leap correction for our sec_in_utc value and number of extra
326
    secs to add to this minute.
327
    This loop is rarely used because most users will use time zones without
328
    leap seconds, and even in case when we have such time zone there won't
329
    be many iterations (we have about 22 corrections at this moment (2004)).
330
  */
331
  for ( i= sp->leapcnt; i-- > 0; )
332
  {
333
    lp= &sp->lsis[i];
334
    if (sec_in_utc >= lp->ls_trans)
335
    {
336
      if (sec_in_utc == lp->ls_trans)
337
      {
338
        hit= ((i == 0 && lp->ls_corr > 0) ||
339
              lp->ls_corr > sp->lsis[i - 1].ls_corr);
340
        if (hit)
341
        {
342
          while (i > 0 &&
343
                 sp->lsis[i].ls_trans == sp->lsis[i - 1].ls_trans + 1 &&
344
                 sp->lsis[i].ls_corr == sp->lsis[i - 1].ls_corr + 1)
345
          {
346
            hit++;
347
            i--;
348
          }
349
        }
350
      }
351
      corr= lp->ls_corr;
352
      break;
353
    }
354
  }
355
356
  sec_to_TIME(tmp, sec_in_utc, ttisp->tt_gmtoff - corr);
357
358
  tmp->second+= hit;
359
}
360
361
362
/*
363
  Converts local time in broken down representation to local
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
364
  time zone analog of time_t represenation.
1 by brian
clean slate
365
366
  SYNOPSIS
367
    sec_since_epoch()
368
      year, mon, mday, hour, min, sec - broken down representation.
369
370
  DESCRIPTION
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
371
    Converts time in broken down representation to time_t representation
1 by brian
clean slate
372
    ignoring time zone. Note that we cannot convert back some valid _local_
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
373
    times near ends of time_t range because of time_t overflow. But we
1 by brian
clean slate
374
    ignore this fact now since MySQL will never pass such argument.
375
376
  RETURN VALUE
377
    Seconds since epoch time representation.
378
*/
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
379
static time_t
1 by brian
clean slate
380
sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec)
381
{
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
382
  /* Guard against time_t overflow (on system with 32 bit time_t) */
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
383
  assert(!(year == TIMESTAMP_MAX_YEAR && mon == 1 && mday > 17));
1 by brian
clean slate
384
#ifndef WE_WANT_TO_HANDLE_UNORMALIZED_DATES
385
  /*
386
    It turns out that only whenever month is normalized or unnormalized
387
    plays role.
388
  */
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
389
  assert(mon > 0 && mon < 13);
1 by brian
clean slate
390
  long days= year * DAYS_PER_NYEAR - EPOCH_YEAR * DAYS_PER_NYEAR +
391
             LEAPS_THRU_END_OF(year - 1) -
392
             LEAPS_THRU_END_OF(EPOCH_YEAR - 1);
393
  days+= mon_starts[isleap(year)][mon - 1];
394
#else
395
  long norm_month= (mon - 1) % MONS_PER_YEAR;
396
  long a_year= year + (mon - 1)/MONS_PER_YEAR - (int)(norm_month < 0);
397
  long days= a_year * DAYS_PER_NYEAR - EPOCH_YEAR * DAYS_PER_NYEAR +
398
             LEAPS_THRU_END_OF(a_year - 1) -
399
             LEAPS_THRU_END_OF(EPOCH_YEAR - 1);
400
  days+= mon_starts[isleap(a_year)]
401
                    [norm_month + (norm_month < 0 ? MONS_PER_YEAR : 0)];
402
#endif
403
  days+= mday - 1;
404
405
  return ((days * HOURS_PER_DAY + hour) * MINS_PER_HOUR + min) *
406
         SECS_PER_MIN + sec;
407
}
408
409
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
410
  Converts local time in broken down DRIZZLE_TIME representation to time_t
1 by brian
clean slate
411
  representation.
412
413
  SYNOPSIS
414
    TIME_to_gmt_sec()
415
      t               - pointer to structure for broken down represenatation
416
      sp              - pointer to struct with time zone description
417
      in_dst_time_gap - pointer to bool which is set to true if datetime
418
                        value passed doesn't really exist (i.e. falls into
419
                        spring time-gap) and is not touched otherwise.
420
421
  DESCRIPTION
422
    This is mktime analog for MySQL. It is essentially different
423
    from mktime (or hypotetical my_mktime) because:
424
    - It has no idea about tm_isdst member so if it
425
      has two answers it will give the smaller one
426
    - If we are in spring time gap then it will return
427
      beginning of the gap
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
428
    - It can give wrong results near the ends of time_t due to
1 by brian
clean slate
429
      overflows, but we are safe since in MySQL we will never
430
      call this function for such dates (its restriction for year
431
      between 1970 and 2038 gives us several days of reserve).
432
    - By default it doesn't support un-normalized input. But if
433
      sec_since_epoch() function supports un-normalized dates
434
      then this function should handle un-normalized input right,
435
      altough it won't normalize structure TIME.
436
437
    Traditional approach to problem of conversion from broken down
438
    representation to time_t is iterative. Both elsie's and glibc
439
    implementation try to guess what time_t value should correspond to
440
    this broken-down value. They perform localtime_r function on their
441
    guessed value and then calculate the difference and try to improve
442
    their guess. Elsie's code guesses time_t value in bit by bit manner,
443
    Glibc's code tries to add difference between broken-down value
444
    corresponding to guess and target broken-down value to current guess.
445
    It also uses caching of last found correction... So Glibc's approach
446
    is essentially faster but introduces some undetermenism (in case if
447
    is_dst member of broken-down representation (tm struct) is not known
448
    and we have two possible answers).
449
450
    We use completely different approach. It is better since it is both
451
    faster than iterative implementations and fully determenistic. If you
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
452
    look at time_t to DRIZZLE_TIME conversion then you'll find that it consist
1 by brian
clean slate
453
    of two steps:
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
454
    The first is calculating shifted time_t value and the second - TIME
455
    calculation from shifted time_t value (well it is a bit simplified
456
    picture). The part in which we are interested in is time_t -> shifted
457
    time_t conversion. It is piecewise linear function which is defined
1 by brian
clean slate
458
    by combination of transition times as break points and times offset
459
    as changing function parameter. The possible inverse function for this
460
    converison would be ambiguos but with MySQL's restrictions we can use
461
    some function which is the same as inverse function on unambigiuos
462
    ranges and coincides with one of branches of inverse function in
463
    other ranges. Thus we just need to build table which will determine
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
464
    this shifted time_t -> time_t conversion similar to existing
465
    (time_t -> shifted time_t table). We do this in
1 by brian
clean slate
466
    prepare_tz_info function.
467
468
  TODO
469
    If we can even more improve this function. For doing this we will need to
470
    build joined map of transitions and leap corrections for gmt_sec_to_TIME()
471
    function (similar to revts/revtis). Under realistic assumptions about
472
    frequency of transitions we can use the same array for TIME_to_gmt_sec().
473
    We need to implement special version of binary search for this. Such step
474
    will be beneficial to CPU cache since we will decrease data-set used for
475
    conversion twice.
476
477
  RETURN VALUE
478
    Seconds in UTC since Epoch.
479
    0 in case of error.
480
*/
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
481
static time_t
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
482
TIME_to_gmt_sec(const DRIZZLE_TIME *t, const TIME_ZONE_INFO *sp,
93 by Brian Aker
Convert tztime.cc to bool from my_bool.
483
                bool *in_dst_time_gap)
1 by brian
clean slate
484
{
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
485
  time_t local_t;
482 by Brian Aker
Remove uint.
486
  uint32_t saved_seconds;
487
  uint32_t i;
1 by brian
clean slate
488
  int shift= 0;
489
490
  if (!validate_timestamp_range(t))
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
491
    return(0);
1 by brian
clean slate
492
493
494
  /* We need this for correct leap seconds handling */
495
  if (t->second < SECS_PER_MIN)
496
    saved_seconds= 0;
497
  else
498
    saved_seconds= t->second;
499
500
  /*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
501
    NOTE: to convert full time_t range we do a shift of the
502
    boundary dates here to avoid overflow of time_t.
1 by brian
clean slate
503
    We use alike approach in my_system_gmt_sec().
504
505
    However in that function we also have to take into account
506
    overflow near 0 on some platforms. That's because my_system_gmt_sec
507
    uses localtime_r(), which doesn't work with negative values correctly
508
    on platforms with unsigned time_t (QNX). Here we don't use localtime()
509
    => we negative values of local_t are ok.
510
  */
511
512
  if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4)
513
  {
514
    /*
515
      We will pass (t->day - shift) to sec_since_epoch(), and
516
      want this value to be a positive number, so we shift
517
      only dates > 4.01.2038 (to avoid owerflow).
518
    */
519
    shift= 2;
520
  }
521
522
523
  local_t= sec_since_epoch(t->year, t->month, (t->day - shift),
524
                           t->hour, t->minute,
525
                           saved_seconds ? 0 : t->second);
526
527
  /* We have at least one range */
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
528
  assert(sp->revcnt >= 1);
1 by brian
clean slate
529
530
  if (local_t < sp->revts[0] || local_t > sp->revts[sp->revcnt])
531
  {
532
    /*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
533
      This means that source time can't be represented as time_t due to
534
      limited time_t range.
1 by brian
clean slate
535
    */
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
536
    return(0);
1 by brian
clean slate
537
  }
538
539
  /* binary search for our range */
540
  i= find_time_range(local_t, sp->revts, sp->revcnt);
541
542
  /*
543
    As there are no offset switches at the end of TIMESTAMP range,
544
    we could simply check for overflow here (and don't need to bother
545
    about DST gaps etc)
546
  */
547
  if (shift)
548
  {
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
549
    if (local_t > (time_t) (TIMESTAMP_MAX_VALUE - shift * SECS_PER_DAY +
550
                            sp->revtis[i].rt_offset - saved_seconds))
1 by brian
clean slate
551
    {
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
552
      return(0);                           /* time_t overflow */
1 by brian
clean slate
553
    }
554
    local_t+= shift * SECS_PER_DAY;
555
  }
556
557
  if (sp->revtis[i].rt_type)
558
  {
559
    /*
560
      Oops! We are in spring time gap.
561
      May be we should return error here?
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
562
      Now we are returning time_t value corresponding to the
1 by brian
clean slate
563
      beginning of the gap.
564
    */
565
    *in_dst_time_gap= 1;
566
    local_t= sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds;
567
  }
568
  else
569
    local_t= local_t - sp->revtis[i].rt_offset + saved_seconds;
570
571
  /* check for TIMESTAMP_MAX_VALUE was already done above */
572
  if (local_t < TIMESTAMP_MIN_VALUE)
573
    local_t= 0;
574
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
575
  return(local_t);
1 by brian
clean slate
576
}
577
578
579
/*
580
  End of elsie derived code.
581
*/
582
#endif /* !defined(TZINFO2SQL) */
583
584
585
/*
586
  String with names of SYSTEM time zone.
587
*/
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
588
static const String tz_SYSTEM_name("SYSTEM", 6, &my_charset_utf8_general_ci);
1 by brian
clean slate
589
590
591
/*
592
  Instance of this class represents local time zone used on this system
593
  (specified by TZ environment variable or via any other system mechanism).
594
  It uses system functions (localtime_r, my_system_gmt_sec) for conversion
595
  and is always available. Because of this it is used by default - if there
596
  were no explicit time zone specified. On the other hand because of this
597
  conversion methods provided by this class is significantly slower and
598
  possibly less multi-threaded-friendly than corresponding Time_zone_db
599
  methods so the latter should be preffered there it is possible.
600
*/
601
class Time_zone_system : public Time_zone
602
{
603
public:
604
  Time_zone_system() {}                       /* Remove gcc warning */
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
605
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
93 by Brian Aker
Convert tztime.cc to bool from my_bool.
606
                                    bool *in_dst_time_gap) const;
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
607
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
1 by brian
clean slate
608
  virtual const String * get_name() const;
609
};
610
611
612
/*
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
613
  Converts local time in system time zone in DRIZZLE_TIME representation
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
614
  to its time_t representation.
1 by brian
clean slate
615
616
  SYNOPSIS
617
    TIME_to_gmt_sec()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
618
      t               - pointer to DRIZZLE_TIME structure with local time in
1 by brian
clean slate
619
                        broken-down representation.
620
      in_dst_time_gap - pointer to bool which is set to true if datetime
621
                        value passed doesn't really exist (i.e. falls into
622
                        spring time-gap) and is not touched otherwise.
623
624
  DESCRIPTION
625
    This method uses system function (localtime_r()) for conversion
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
626
    local time in system time zone in DRIZZLE_TIME structure to its time_t
1 by brian
clean slate
627
    representation. Unlike the same function for Time_zone_db class
628
    it it won't handle unnormalized input properly. Still it will
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
629
    return lowest possible time_t in case of ambiguity or if we
1 by brian
clean slate
630
    provide time corresponding to the time-gap.
631
632
    You should call init_time() function before using this function.
633
634
  RETURN VALUE
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
635
    Corresponding time_t value or 0 in case of error
1 by brian
clean slate
636
*/
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
637
time_t
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
638
Time_zone_system::TIME_to_gmt_sec(const DRIZZLE_TIME *t, bool *in_dst_time_gap) const
1 by brian
clean slate
639
{
640
  long not_used;
641
  return my_system_gmt_sec(t, &not_used, in_dst_time_gap);
642
}
643
644
645
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
646
  Converts time from UTC seconds since Epoch (time_t) representation
1 by brian
clean slate
647
  to system local time zone broken-down representation.
648
649
  SYNOPSIS
650
    gmt_sec_to_TIME()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
651
      tmp - pointer to DRIZZLE_TIME structure to fill-in
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
652
      t   - time_t value to be converted
1 by brian
clean slate
653
654
  NOTE
655
    We assume that value passed to this function will fit into time_t range
656
    supported by localtime_r. This conversion is putting restriction on
657
    TIMESTAMP range in MySQL. If we can get rid of SYSTEM time zone at least
658
    for interaction with client then we can extend TIMESTAMP range down to
659
    the 1902 easily.
660
*/
661
void
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
662
Time_zone_system::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
1 by brian
clean slate
663
{
664
  struct tm tmp_tm;
665
  time_t tmp_t= (time_t)t;
666
667
  localtime_r(&tmp_t, &tmp_tm);
668
  localtime_to_TIME(tmp, &tmp_tm);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
669
  tmp->time_type= DRIZZLE_TIMESTAMP_DATETIME;
1 by brian
clean slate
670
}
671
672
673
/*
674
  Get name of time zone
675
676
  SYNOPSIS
677
    get_name()
678
679
  RETURN VALUE
680
    Name of time zone as String
681
*/
682
const String *
683
Time_zone_system::get_name() const
684
{
685
  return &tz_SYSTEM_name;
686
}
687
688
689
/*
690
  Instance of this class represents UTC time zone. It uses system gmtime_r
691
  function for conversions and is always available. It is used only for
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
692
  time_t -> DRIZZLE_TIME conversions in various UTC_...  functions, it is not
693
  intended for DRIZZLE_TIME -> time_t conversions and shouldn't be exposed to user.
1 by brian
clean slate
694
*/
695
class Time_zone_utc : public Time_zone
696
{
697
public:
698
  Time_zone_utc() {}                          /* Remove gcc warning */
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
699
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
93 by Brian Aker
Convert tztime.cc to bool from my_bool.
700
                                    bool *in_dst_time_gap) const;
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
701
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
1 by brian
clean slate
702
  virtual const String * get_name() const;
703
};
704
705
706
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
707
  Convert UTC time from DRIZZLE_TIME representation to its time_t representation.
1 by brian
clean slate
708
709
  SYNOPSIS
710
    TIME_to_gmt_sec()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
711
      t               - pointer to DRIZZLE_TIME structure with local time
1 by brian
clean slate
712
                        in broken-down representation.
713
      in_dst_time_gap - pointer to bool which is set to true if datetime
714
                        value passed doesn't really exist (i.e. falls into
715
                        spring time-gap) and is not touched otherwise.
716
717
  DESCRIPTION
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
718
    Since Time_zone_utc is used only internally for time_t -> TIME
1 by brian
clean slate
719
    conversions, this function of Time_zone interface is not implemented for
720
    this class and should not be called.
721
722
  RETURN VALUE
723
    0
724
*/
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
725
time_t
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
726
Time_zone_utc::TIME_to_gmt_sec(const DRIZZLE_TIME *,
727
                               bool *) const
1 by brian
clean slate
728
{
729
  /* Should be never called */
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
730
  assert(0);
1 by brian
clean slate
731
  return 0;
732
}
733
734
735
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
736
  Converts time from UTC seconds since Epoch (time_t) representation
1 by brian
clean slate
737
  to broken-down representation (also in UTC).
738
739
  SYNOPSIS
740
    gmt_sec_to_TIME()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
741
      tmp - pointer to DRIZZLE_TIME structure to fill-in
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
742
      t   - time_t value to be converted
1 by brian
clean slate
743
744
  NOTE
745
    See note for apropriate Time_zone_system method.
746
*/
747
void
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
748
Time_zone_utc::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
1 by brian
clean slate
749
{
750
  struct tm tmp_tm;
751
  time_t tmp_t= (time_t)t;
752
  gmtime_r(&tmp_t, &tmp_tm);
753
  localtime_to_TIME(tmp, &tmp_tm);
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
754
  tmp->time_type= DRIZZLE_TIMESTAMP_DATETIME;
1 by brian
clean slate
755
}
756
757
758
/*
759
  Get name of time zone
760
761
  SYNOPSIS
762
    get_name()
763
764
  DESCRIPTION
765
    Since Time_zone_utc is used only internally by SQL's UTC_* functions it
766
    is not accessible directly, and hence this function of Time_zone
767
    interface is not implemented for this class and should not be called.
768
769
  RETURN VALUE
770
    0
771
*/
772
const String *
773
Time_zone_utc::get_name() const
774
{
775
  /* Should be never called */
51.1.72 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
776
  assert(0);
1 by brian
clean slate
777
  return 0;
778
}
779
780
781
/*
782
  Instance of this class represents some time zone which is
783
  described in mysql.time_zone family of tables.
784
*/
785
class Time_zone_db : public Time_zone
786
{
787
public:
788
  Time_zone_db(TIME_ZONE_INFO *tz_info_arg, const String * tz_name_arg);
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
789
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
93 by Brian Aker
Convert tztime.cc to bool from my_bool.
790
                                    bool *in_dst_time_gap) const;
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
791
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
1 by brian
clean slate
792
  virtual const String * get_name() const;
793
private:
794
  TIME_ZONE_INFO *tz_info;
795
  const String *tz_name;
796
};
797
798
799
/*
800
  Initializes object representing time zone described by mysql.time_zone
801
  tables.
802
803
  SYNOPSIS
804
    Time_zone_db()
805
      tz_info_arg - pointer to TIME_ZONE_INFO structure which is filled
806
                    according to db or other time zone description
807
                    (for example by my_tz_init()).
808
                    Several Time_zone_db instances can share one
809
                    TIME_ZONE_INFO structure.
810
      tz_name_arg - name of time zone.
811
*/
812
Time_zone_db::Time_zone_db(TIME_ZONE_INFO *tz_info_arg,
813
                           const String *tz_name_arg):
814
  tz_info(tz_info_arg), tz_name(tz_name_arg)
815
{
816
}
817
818
819
/*
820
  Converts local time in time zone described from TIME
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
821
  representation to its time_t representation.
1 by brian
clean slate
822
823
  SYNOPSIS
824
    TIME_to_gmt_sec()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
825
      t               - pointer to DRIZZLE_TIME structure with local time
1 by brian
clean slate
826
                        in broken-down representation.
827
      in_dst_time_gap - pointer to bool which is set to true if datetime
828
                        value passed doesn't really exist (i.e. falls into
829
                        spring time-gap) and is not touched otherwise.
830
831
  DESCRIPTION
832
    Please see ::TIME_to_gmt_sec for function description and
833
    parameter restrictions.
834
835
  RETURN VALUE
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
836
    Corresponding time_t value or 0 in case of error
1 by brian
clean slate
837
*/
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
838
time_t
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
839
Time_zone_db::TIME_to_gmt_sec(const DRIZZLE_TIME *t, bool *in_dst_time_gap) const
1 by brian
clean slate
840
{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
841
  return ::drizzled::TIME_to_gmt_sec(t, tz_info, in_dst_time_gap);
1 by brian
clean slate
842
}
843
844
845
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
846
  Converts time from UTC seconds since Epoch (time_t) representation
1 by brian
clean slate
847
  to local time zone described in broken-down representation.
848
849
  SYNOPSIS
850
    gmt_sec_to_TIME()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
851
      tmp - pointer to DRIZZLE_TIME structure to fill-in
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
852
      t   - time_t value to be converted
1 by brian
clean slate
853
*/
854
void
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
855
Time_zone_db::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
1 by brian
clean slate
856
{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
857
  ::drizzled::gmt_sec_to_TIME(tmp, t, tz_info);
1 by brian
clean slate
858
}
859
860
861
/*
862
  Get name of time zone
863
864
  SYNOPSIS
865
    get_name()
866
867
  RETURN VALUE
868
    Name of time zone as ASCIIZ-string
869
*/
870
const String *
871
Time_zone_db::get_name() const
872
{
873
  return tz_name;
874
}
875
876
877
/*
878
  Instance of this class represents time zone which
879
  was specified as offset from UTC.
880
*/
881
class Time_zone_offset : public Time_zone
882
{
883
public:
884
  Time_zone_offset(long tz_offset_arg);
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
885
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
93 by Brian Aker
Convert tztime.cc to bool from my_bool.
886
                                    bool *in_dst_time_gap) const;
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
887
  virtual void   gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
1 by brian
clean slate
888
  virtual const String * get_name() const;
889
  /*
890
    This have to be public because we want to be able to access it from
891
    my_offset_tzs_get_key() function
892
  */
893
  long offset;
894
private:
895
  /* Extra reserve because of snprintf */
896
  char name_buff[7+16];
897
  String name;
898
};
899
900
901
/*
902
  Initializes object representing time zone described by its offset from UTC.
903
904
  SYNOPSIS
905
    Time_zone_offset()
906
      tz_offset_arg - offset from UTC in seconds.
907
                      Positive for direction to east.
908
*/
909
Time_zone_offset::Time_zone_offset(long tz_offset_arg):
910
  offset(tz_offset_arg)
911
{
482 by Brian Aker
Remove uint.
912
  uint32_t hours= abs((int)(offset / SECS_PER_HOUR));
913
  uint32_t minutes= abs((int)(offset % SECS_PER_HOUR / SECS_PER_MIN));
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
914
  ulong length= snprintf(name_buff, sizeof(name_buff), "%s%02d:%02d",
915
                         (offset>=0) ? "+" : "-", hours, minutes);
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
916
  name.set(name_buff, length, &my_charset_utf8_general_ci);
1 by brian
clean slate
917
}
918
919
920
/*
921
  Converts local time in time zone described as offset from UTC
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
922
  from DRIZZLE_TIME representation to its time_t representation.
1 by brian
clean slate
923
924
  SYNOPSIS
925
    TIME_to_gmt_sec()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
926
      t               - pointer to DRIZZLE_TIME structure with local time
1 by brian
clean slate
927
                        in broken-down representation.
928
      in_dst_time_gap - pointer to bool which should be set to true if
929
                        datetime  value passed doesn't really exist
930
                        (i.e. falls into spring time-gap) and is not
931
                        touched otherwise.
932
                        It is not really used in this class.
933
934
  RETURN VALUE
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
935
    Corresponding time_t value or 0 in case of error
1 by brian
clean slate
936
*/
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
937
time_t
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
938
Time_zone_offset::TIME_to_gmt_sec(const DRIZZLE_TIME *t,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
939
                                  bool *) const
1 by brian
clean slate
940
{
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
941
  time_t local_t;
1 by brian
clean slate
942
  int shift= 0;
943
944
  /*
945
    Check timestamp range.we have to do this as calling function relies on
946
    us to make all validation checks here.
947
  */
948
  if (!validate_timestamp_range(t))
949
    return 0;
950
951
  /*
952
    Do a temporary shift of the boundary dates to avoid
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
953
    overflow of time_t if the time value is near it's
1 by brian
clean slate
954
    maximum range
955
  */
956
  if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4)
957
    shift= 2;
958
959
  local_t= sec_since_epoch(t->year, t->month, (t->day - shift),
960
                           t->hour, t->minute, t->second) -
961
           offset;
962
963
  if (shift)
964
  {
965
    /* Add back the shifted time */
966
    local_t+= shift * SECS_PER_DAY;
967
  }
968
969
  if (local_t >= TIMESTAMP_MIN_VALUE && local_t <= TIMESTAMP_MAX_VALUE)
970
    return local_t;
971
972
  /* range error*/
973
  return 0;
974
}
975
976
977
/*
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
978
  Converts time from UTC seconds since Epoch (time_t) representation
1 by brian
clean slate
979
  to local time zone described as offset from UTC and in broken-down
980
  representation.
981
982
  SYNOPSIS
983
    gmt_sec_to_TIME()
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
984
      tmp - pointer to DRIZZLE_TIME structure to fill-in
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
985
      t   - time_t value to be converted
1 by brian
clean slate
986
*/
987
void
726.1.1 by Toru Maesaka
Use time_t instead of my_time_t which should be safe (as in wide enough) on POSIX compliant systems.
988
Time_zone_offset::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
1 by brian
clean slate
989
{
990
  sec_to_TIME(tmp, t, offset);
991
}
992
993
994
/*
995
  Get name of time zone
996
997
  SYNOPSIS
998
    get_name()
999
1000
  RETURN VALUE
1001
    Name of time zone as pointer to String object
1002
*/
1003
const String *
1004
Time_zone_offset::get_name() const
1005
{
1006
  return &name;
1007
}
1008
1009
1010
static Time_zone_utc tz_UTC;
1011
static Time_zone_system tz_SYSTEM;
1012
static Time_zone_offset tz_OFFSET0(0);
1013
1014
Time_zone *my_tz_SYSTEM= &tz_SYSTEM;
1015
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1016
class Tz_names_entry: public memory::SqlAlloc
1 by brian
clean slate
1017
{
1018
public:
1019
  String name;
1020
  Time_zone *tz;
1021
};
1022
1023
1024
/*
1025
  Initialize time zone support infrastructure.
1026
1027
  SYNOPSIS
1028
    my_tz_init()
520.1.22 by Brian Aker
Second pass of thd cleanup
1029
      session            - current thread object
1 by brian
clean slate
1030
      default_tzname - default time zone or 0 if none.
1031
      bootstrap      - indicates whenever we are in bootstrap mode
1032
1033
  DESCRIPTION
1034
    This function will init memory structures needed for time zone support,
1035
    it will register mandatory SYSTEM time zone in them. It will try to open
1036
    mysql.time_zone* tables and load information about default time zone and
1037
    information which further will be shared among all time zones loaded.
1038
    If system tables with time zone descriptions don't exist it won't fail
1039
    (unless default_tzname is time zone from tables). If bootstrap parameter
1040
    is true then this routine assumes that we are in bootstrap mode and won't
1041
    load time zone descriptions unless someone specifies default time zone
1042
    which is supposedly stored in those tables.
1043
    It'll also set default time zone if it is specified.
1044
1045
  RETURN VALUES
1046
    0 - ok
1047
    1 - Error
1048
*/
53.1.1 by Brian Aker
First pass through removing timezone. Left infrastructure for possible call
1049
bool
520.1.22 by Brian Aker
Second pass of thd cleanup
1050
my_tz_init(Session *session, const char *default_tzname)
1 by brian
clean slate
1051
{
1052
  if (default_tzname)
1053
  {
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
1054
    String tmp_tzname2(default_tzname, &my_charset_utf8_general_ci);
1 by brian
clean slate
1055
    /*
1056
      Time zone tables may be open here, and my_tz_find() may open
1057
      most of them once more, but this is OK for system tables open
1058
      for READ.
1059
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
1060
    if (!(global_system_variables.time_zone= my_tz_find(session, &tmp_tzname2)))
1 by brian
clean slate
1061
    {
755.2.1 by Mark Atwood
replace sql_print_error etc with errmsg_print
1062
      errmsg_printf(ERRMSG_LVL_ERROR,
1063
                    _("Fatal error: Illegal or unknown default time zone '%s'"),
1064
                    default_tzname);
53.1.1 by Brian Aker
First pass through removing timezone. Left infrastructure for possible call
1065
      return true;
1 by brian
clean slate
1066
    }
1067
  }
1068
53.1.1 by Brian Aker
First pass through removing timezone. Left infrastructure for possible call
1069
  return false;
1 by brian
clean slate
1070
}
1071
1072
/*
1073
  Get Time_zone object for specified time zone.
1074
53.1.1 by Brian Aker
First pass through removing timezone. Left infrastructure for possible call
1075
  Not implemented yet. This needs to hook into some sort of OS system call.
1 by brian
clean slate
1076
1077
*/
1078
Time_zone *
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
1079
my_tz_find(Session *,
1080
           const String *)
1 by brian
clean slate
1081
{
53.1.1 by Brian Aker
First pass through removing timezone. Left infrastructure for possible call
1082
  return NULL;
1083
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1084
1085
} /* namespace drizzled */