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