~drizzle-trunk/drizzle/development

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