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