~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/tztime.cc

pandora-build v0.71. Added check for avahi.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
#ifdef USE_PRAGMA_IMPLEMENTATION
17
 
#pragma implementation                          // gcc: Class implementation
18
 
#endif
 
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
 */
 
19
 
19
20
 
20
21
#include <drizzled/server_includes.h>
21
 
#include "tzfile.h"
 
22
#include <drizzled/tzfile.h>
 
23
#include <drizzled/tztime.h>
 
24
#include <drizzled/gettext.h>
 
25
#include <drizzled/session.h>
22
26
 
23
27
/* Structure describing local time type (e.g. Moscow summer time (MSD)) */
24
28
typedef struct ttinfo
25
29
{
26
30
  long tt_gmtoff; // Offset from UTC in seconds
27
 
  uint tt_isdst;   // Is daylight saving time or not. Used to set tm_isdst
28
 
  uint tt_abbrind; // Index of start of abbreviation for this time type.
 
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.
29
33
  /*
30
34
    We don't use tt_ttisstd and tt_ttisgmt members of original elsie-code
31
35
    struct since we don't support POSIX-style TZ descriptions in variables.
35
39
/* Structure describing leap-second corrections. */
36
40
typedef struct lsinfo
37
41
{
38
 
  my_time_t ls_trans; // Transition time
 
42
  time_t ls_trans; // Transition time
39
43
  long      ls_corr;  // Correction to apply
40
44
} LS_INFO;
41
45
 
42
46
/*
43
 
  Structure with information describing ranges of my_time_t shifted to local
44
 
  time (my_time_t + offset). Used for local DRIZZLE_TIME -> my_time_t conversion.
 
47
  Structure with information describing ranges of time_t shifted to local
 
48
  time (time_t + offset). Used for local DRIZZLE_TIME -> time_t conversion.
45
49
  See comments for TIME_to_gmt_sec() for more info.
46
50
*/
47
51
typedef struct revtinfo
48
52
{
49
53
  long rt_offset; // Offset of local time from UTC in seconds
50
 
  uint rt_type;    // Type of period 0 - Normal period. 1 - Spring time-gap
 
54
  uint32_t rt_type;    // Type of period 0 - Normal period. 1 - Spring time-gap
51
55
} REVT_INFO;
52
56
 
53
 
#ifdef TZNAME_MAX
54
 
#define MY_TZNAME_MAX   TZNAME_MAX
55
 
#endif
56
 
#ifndef TZNAME_MAX
57
 
#define MY_TZNAME_MAX   255
58
 
#endif
59
57
 
60
58
/*
61
59
  Structure which fully describes time zone which is
63
61
*/
64
62
typedef struct st_time_zone_info
65
63
{
66
 
  uint leapcnt;  // Number of leap-second corrections
67
 
  uint timecnt;  // Number of transitions between time types
68
 
  uint typecnt;  // Number of local time types
69
 
  uint charcnt;  // Number of characters used for abbreviations
70
 
  uint revcnt;   // Number of transition descr. for TIME->my_time_t conversion
 
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->time_t conversion
71
69
  /* The following are dynamical arrays are allocated in MEM_ROOT */
72
 
  my_time_t *ats;       // Times of transitions between time types
73
 
  uchar *types; // Local time types for transitions
 
70
  time_t *ats;       // Times of transitions between time types
 
71
  unsigned char *types; // Local time types for transitions
74
72
  TRAN_TYPE_INFO *ttis; // Local time types descriptions
75
73
  /* Storage for local time types abbreviations. They are stored as ASCIIZ */
76
74
  char *chars;
80
78
  */
81
79
  LS_INFO *lsis;
82
80
  /*
83
 
    Starting points and descriptions of shifted my_time_t (my_time_t + offset)
84
 
    ranges on which shifted my_time_t -> my_time_t mapping is linear or undefined.
85
 
    Used for tm -> my_time_t conversion.
 
81
    Starting points and descriptions of shifted time_t (time_t + offset)
 
82
    ranges on which shifted time_t -> time_t mapping is linear or undefined.
 
83
    Used for tm -> time_t conversion.
86
84
  */
87
 
  my_time_t *revts;
 
85
  time_t *revts;
88
86
  REVT_INFO *revtis;
89
87
  /*
90
88
    Time type which is used for times smaller than first transition or if
97
95
 
98
96
#if !defined(TZINFO2SQL)
99
97
 
100
 
static const uint mon_lengths[2][MONS_PER_YEAR]=
 
98
static const uint32_t mon_lengths[2][MONS_PER_YEAR]=
101
99
{
102
100
  { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
103
101
  { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
104
102
};
105
103
 
106
 
static const uint mon_starts[2][MONS_PER_YEAR]=
 
104
static const uint32_t mon_starts[2][MONS_PER_YEAR]=
107
105
{
108
106
  { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
109
107
  { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
110
108
};
111
109
 
112
 
static const uint year_lengths[2]=
 
110
static const uint32_t year_lengths[2]=
113
111
{
114
112
  DAYS_PER_NYEAR, DAYS_PER_LYEAR
115
113
};
118
116
 
119
117
 
120
118
/*
121
 
  Converts time from my_time_t representation (seconds in UTC since Epoch)
 
119
  Converts time from time_t representation (seconds in UTC since Epoch)
122
120
  to broken down representation using given local time zone offset.
123
121
 
124
122
  SYNOPSIS
125
123
    sec_to_TIME()
126
124
      tmp    - pointer to structure for broken down representation
127
 
      t      - my_time_t value to be converted
 
125
      t      - time_t value to be converted
128
126
      offset - local time zone offset
129
127
 
130
128
  DESCRIPTION
131
 
    Convert my_time_t with offset to DRIZZLE_TIME struct. Differs from timesub
 
129
    Convert time_t with offset to DRIZZLE_TIME struct. Differs from timesub
132
130
    (from elsie code) because doesn't contain any leap correction and
133
131
    TM_GMTOFF and is_dst setting and contains some MySQL specific
134
132
    initialization. Funny but with removing of these we almost have
135
133
    glibc's offtime function.
136
134
*/
137
135
static void
138
 
sec_to_TIME(DRIZZLE_TIME * tmp, my_time_t t, long offset)
 
136
sec_to_TIME(DRIZZLE_TIME * tmp, time_t t, long offset)
139
137
{
140
138
  long days;
141
139
  long rem;
142
140
  int y;
143
141
  int yleap;
144
 
  const uint *ip;
 
142
  const uint32_t *ip;
145
143
 
146
144
  days= (long) (t / SECS_PER_DAY);
147
145
  rem=  (long) (t % SECS_PER_DAY);
148
146
 
149
147
  /*
150
148
    We do this as separate step after dividing t, because this
151
 
    allows us handle times near my_time_t bounds without overflows.
 
149
    allows us handle times near time_t bounds without overflows.
152
150
  */
153
151
  rem+= offset;
154
152
  while (rem < 0)
161
159
    rem -= SECS_PER_DAY;
162
160
    days++;
163
161
  }
164
 
  tmp->hour= (uint)(rem / SECS_PER_HOUR);
 
162
  tmp->hour= (uint32_t)(rem / SECS_PER_HOUR);
165
163
  rem= rem % SECS_PER_HOUR;
166
 
  tmp->minute= (uint)(rem / SECS_PER_MIN);
 
164
  tmp->minute= (uint32_t)(rem / SECS_PER_MIN);
167
165
  /*
168
166
    A positive leap second requires a special
169
167
    representation.  This uses "... ??:59:60" et seq.
170
168
  */
171
 
  tmp->second= (uint)(rem % SECS_PER_MIN);
 
169
  tmp->second= (uint32_t)(rem % SECS_PER_MIN);
172
170
 
173
171
  y= EPOCH_YEAR;
174
172
  while (days < 0 || days >= (long)year_lengths[yleap= isleap(y)])
189
187
  for (tmp->month= 0; days >= (long) ip[tmp->month]; tmp->month++)
190
188
    days= days - (long) ip[tmp->month];
191
189
  tmp->month++;
192
 
  tmp->day= (uint)(days + 1);
 
190
  tmp->day= (uint32_t)(days + 1);
193
191
 
194
192
  /* filling MySQL specific DRIZZLE_TIME members */
195
193
  tmp->neg= 0; tmp->second_part= 0;
198
196
 
199
197
 
200
198
/*
201
 
  Find time range wich contains given my_time_t value
 
199
  Find time range wich contains given time_t value
202
200
 
203
201
  SYNOPSIS
204
202
    find_time_range()
205
 
      t                - my_time_t value for which we looking for range
 
203
      t                - time_t value for which we looking for range
206
204
      range_boundaries - sorted array of range starts.
207
205
      higher_bound     - number of ranges
208
206
 
209
207
  DESCRIPTION
210
 
    Performs binary search for range which contains given my_time_t value.
211
 
    It has sense if number of ranges is greater than zero and my_time_t value
 
208
    Performs binary search for range which contains given time_t value.
 
209
    It has sense if number of ranges is greater than zero and time_t value
212
210
    is greater or equal than beginning of first range. It also assumes that
213
 
    t belongs to some range specified or end of last is MY_TIME_T_MAX.
 
211
    t belongs to some range specified.
214
212
 
215
213
    With this localtime_r on real data may takes less time than with linear
216
214
    search (I've seen 30% speed up).
219
217
    Index of range to which t belongs
220
218
*/
221
219
static uint
222
 
find_time_range(my_time_t t, const my_time_t *range_boundaries,
223
 
                uint higher_bound)
 
220
find_time_range(time_t t, const time_t *range_boundaries,
 
221
                uint32_t higher_bound)
224
222
{
225
 
  uint i, lower_bound= 0;
 
223
  uint32_t i, lower_bound= 0;
226
224
 
227
225
  /*
228
226
    Function will work without this assertion but result would be meaningless.
248
246
}
249
247
 
250
248
/*
251
 
  Find local time transition for given my_time_t.
 
249
  Find local time transition for given time_t.
252
250
 
253
251
  SYNOPSIS
254
252
    find_transition_type()
255
 
      t   - my_time_t value to be converted
 
253
      t   - time_t value to be converted
256
254
      sp  - pointer to struct with time zone description
257
255
 
258
256
  RETURN VALUE
259
257
    Pointer to structure in time zone description describing
260
 
    local time type for given my_time_t.
 
258
    local time type for given time_t.
261
259
*/
262
260
static
263
261
const TRAN_TYPE_INFO *
264
 
find_transition_type(my_time_t t, const TIME_ZONE_INFO *sp)
 
262
find_transition_type(time_t t, const TIME_ZONE_INFO *sp)
265
263
{
266
264
  if (unlikely(sp->timecnt == 0 || t < sp->ats[0]))
267
265
  {
282
280
 
283
281
 
284
282
/*
285
 
  Converts time in my_time_t representation (seconds in UTC since Epoch) to
 
283
  Converts time in time_t representation (seconds in UTC since Epoch) to
286
284
  broken down DRIZZLE_TIME representation in local time zone.
287
285
 
288
286
  SYNOPSIS
289
287
    gmt_sec_to_TIME()
290
288
      tmp          - pointer to structure for broken down represenatation
291
 
      sec_in_utc   - my_time_t value to be converted
 
289
      sec_in_utc   - time_t value to be converted
292
290
      sp           - pointer to struct with time zone description
293
291
 
294
292
  TODO
298
296
    (60th and 61st second, look how we calculate them as "hit" in this
299
297
    function).
300
298
    Under realistic assumptions about frequency of transitions the same array
301
 
    can be used fot DRIZZLE_TIME -> my_time_t conversion. For this we need to
 
299
    can be used for DRIZZLE_TIME -> time_t conversion. For this we need to
302
300
    implement tweaked binary search which will take into account that some
303
 
    DRIZZLE_TIME has two matching my_time_t ranges and some of them have none.
 
301
    DRIZZLE_TIME has two matching time_t ranges and some of them have none.
304
302
*/
305
303
static void
306
 
gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t sec_in_utc, const TIME_ZONE_INFO *sp)
 
304
gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t sec_in_utc, const TIME_ZONE_INFO *sp)
307
305
{
308
306
  const TRAN_TYPE_INFO *ttisp;
309
307
  const LS_INFO *lp;
359
357
 
360
358
/*
361
359
  Converts local time in broken down representation to local
362
 
  time zone analog of my_time_t represenation.
 
360
  time zone analog of time_t represenation.
363
361
 
364
362
  SYNOPSIS
365
363
    sec_since_epoch()
366
364
      year, mon, mday, hour, min, sec - broken down representation.
367
365
 
368
366
  DESCRIPTION
369
 
    Converts time in broken down representation to my_time_t representation
 
367
    Converts time in broken down representation to time_t representation
370
368
    ignoring time zone. Note that we cannot convert back some valid _local_
371
 
    times near ends of my_time_t range because of my_time_t  overflow. But we
 
369
    times near ends of time_t range because of time_t overflow. But we
372
370
    ignore this fact now since MySQL will never pass such argument.
373
371
 
374
372
  RETURN VALUE
375
373
    Seconds since epoch time representation.
376
374
*/
377
 
static my_time_t
 
375
static time_t
378
376
sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec)
379
377
{
380
 
  /* Guard against my_time_t overflow(on system with 32 bit my_time_t) */
 
378
  /* Guard against time_t overflow (on system with 32 bit time_t) */
381
379
  assert(!(year == TIMESTAMP_MAX_YEAR && mon == 1 && mday > 17));
382
380
#ifndef WE_WANT_TO_HANDLE_UNORMALIZED_DATES
383
381
  /*
405
403
}
406
404
 
407
405
/*
408
 
  Converts local time in broken down DRIZZLE_TIME representation to my_time_t
 
406
  Converts local time in broken down DRIZZLE_TIME representation to time_t
409
407
  representation.
410
408
 
411
409
  SYNOPSIS
423
421
      has two answers it will give the smaller one
424
422
    - If we are in spring time gap then it will return
425
423
      beginning of the gap
426
 
    - It can give wrong results near the ends of my_time_t due to
 
424
    - It can give wrong results near the ends of time_t due to
427
425
      overflows, but we are safe since in MySQL we will never
428
426
      call this function for such dates (its restriction for year
429
427
      between 1970 and 2038 gives us several days of reserve).
447
445
 
448
446
    We use completely different approach. It is better since it is both
449
447
    faster than iterative implementations and fully determenistic. If you
450
 
    look at my_time_t to DRIZZLE_TIME conversion then you'll find that it consist
 
448
    look at time_t to DRIZZLE_TIME conversion then you'll find that it consist
451
449
    of two steps:
452
 
    The first is calculating shifted my_time_t value and the second - TIME
453
 
    calculation from shifted my_time_t value (well it is a bit simplified
454
 
    picture). The part in which we are interested in is my_time_t -> shifted
455
 
    my_time_t conversion. It is piecewise linear function which is defined
 
450
    The first is calculating shifted time_t value and the second - TIME
 
451
    calculation from shifted time_t value (well it is a bit simplified
 
452
    picture). The part in which we are interested in is time_t -> shifted
 
453
    time_t conversion. It is piecewise linear function which is defined
456
454
    by combination of transition times as break points and times offset
457
455
    as changing function parameter. The possible inverse function for this
458
456
    converison would be ambiguos but with MySQL's restrictions we can use
459
457
    some function which is the same as inverse function on unambigiuos
460
458
    ranges and coincides with one of branches of inverse function in
461
459
    other ranges. Thus we just need to build table which will determine
462
 
    this shifted my_time_t -> my_time_t conversion similar to existing
463
 
    (my_time_t -> shifted my_time_t table). We do this in
 
460
    this shifted time_t -> time_t conversion similar to existing
 
461
    (time_t -> shifted time_t table). We do this in
464
462
    prepare_tz_info function.
465
463
 
466
464
  TODO
476
474
    Seconds in UTC since Epoch.
477
475
    0 in case of error.
478
476
*/
479
 
static my_time_t
 
477
static time_t
480
478
TIME_to_gmt_sec(const DRIZZLE_TIME *t, const TIME_ZONE_INFO *sp,
481
479
                bool *in_dst_time_gap)
482
480
{
483
 
  my_time_t local_t;
484
 
  uint saved_seconds;
485
 
  uint i;
 
481
  time_t local_t;
 
482
  uint32_t saved_seconds;
 
483
  uint32_t i;
486
484
  int shift= 0;
487
485
 
488
486
  if (!validate_timestamp_range(t))
496
494
    saved_seconds= t->second;
497
495
 
498
496
  /*
499
 
    NOTE: to convert full my_time_t range we do a shift of the
500
 
    boundary dates here to avoid overflow of my_time_t.
 
497
    NOTE: to convert full time_t range we do a shift of the
 
498
    boundary dates here to avoid overflow of time_t.
501
499
    We use alike approach in my_system_gmt_sec().
502
500
 
503
501
    However in that function we also have to take into account
528
526
  if (local_t < sp->revts[0] || local_t > sp->revts[sp->revcnt])
529
527
  {
530
528
    /*
531
 
      This means that source time can't be represented as my_time_t due to
532
 
      limited my_time_t range.
 
529
      This means that source time can't be represented as time_t due to
 
530
      limited time_t range.
533
531
    */
534
532
    return(0);
535
533
  }
544
542
  */
545
543
  if (shift)
546
544
  {
547
 
    if (local_t > (my_time_t) (TIMESTAMP_MAX_VALUE - shift * SECS_PER_DAY +
548
 
                               sp->revtis[i].rt_offset - saved_seconds))
 
545
    if (local_t > (time_t) (TIMESTAMP_MAX_VALUE - shift * SECS_PER_DAY +
 
546
                            sp->revtis[i].rt_offset - saved_seconds))
549
547
    {
550
 
      return(0);                           /* my_time_t overflow */
 
548
      return(0);                           /* time_t overflow */
551
549
    }
552
550
    local_t+= shift * SECS_PER_DAY;
553
551
  }
557
555
    /*
558
556
      Oops! We are in spring time gap.
559
557
      May be we should return error here?
560
 
      Now we are returning my_time_t value corresponding to the
 
558
      Now we are returning time_t value corresponding to the
561
559
      beginning of the gap.
562
560
    */
563
561
    *in_dst_time_gap= 1;
583
581
/*
584
582
  String with names of SYSTEM time zone.
585
583
*/
586
 
static const String tz_SYSTEM_name("SYSTEM", 6, &my_charset_latin1);
 
584
static const String tz_SYSTEM_name("SYSTEM", 6, &my_charset_utf8_general_ci);
587
585
 
588
586
 
589
587
/*
600
598
{
601
599
public:
602
600
  Time_zone_system() {}                       /* Remove gcc warning */
603
 
  virtual my_time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
 
601
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
604
602
                                    bool *in_dst_time_gap) const;
605
 
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const;
 
603
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
606
604
  virtual const String * get_name() const;
607
605
};
608
606
 
609
607
 
610
608
/*
611
609
  Converts local time in system time zone in DRIZZLE_TIME representation
612
 
  to its my_time_t representation.
 
610
  to its time_t representation.
613
611
 
614
612
  SYNOPSIS
615
613
    TIME_to_gmt_sec()
621
619
 
622
620
  DESCRIPTION
623
621
    This method uses system function (localtime_r()) for conversion
624
 
    local time in system time zone in DRIZZLE_TIME structure to its my_time_t
 
622
    local time in system time zone in DRIZZLE_TIME structure to its time_t
625
623
    representation. Unlike the same function for Time_zone_db class
626
624
    it it won't handle unnormalized input properly. Still it will
627
 
    return lowest possible my_time_t in case of ambiguity or if we
 
625
    return lowest possible time_t in case of ambiguity or if we
628
626
    provide time corresponding to the time-gap.
629
627
 
630
628
    You should call init_time() function before using this function.
631
629
 
632
630
  RETURN VALUE
633
 
    Corresponding my_time_t value or 0 in case of error
 
631
    Corresponding time_t value or 0 in case of error
634
632
*/
635
 
my_time_t
 
633
time_t
636
634
Time_zone_system::TIME_to_gmt_sec(const DRIZZLE_TIME *t, bool *in_dst_time_gap) const
637
635
{
638
636
  long not_used;
641
639
 
642
640
 
643
641
/*
644
 
  Converts time from UTC seconds since Epoch (my_time_t) representation
 
642
  Converts time from UTC seconds since Epoch (time_t) representation
645
643
  to system local time zone broken-down representation.
646
644
 
647
645
  SYNOPSIS
648
646
    gmt_sec_to_TIME()
649
647
      tmp - pointer to DRIZZLE_TIME structure to fill-in
650
 
      t   - my_time_t value to be converted
 
648
      t   - time_t value to be converted
651
649
 
652
650
  NOTE
653
651
    We assume that value passed to this function will fit into time_t range
657
655
    the 1902 easily.
658
656
*/
659
657
void
660
 
Time_zone_system::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const
 
658
Time_zone_system::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
661
659
{
662
660
  struct tm tmp_tm;
663
661
  time_t tmp_t= (time_t)t;
687
685
/*
688
686
  Instance of this class represents UTC time zone. It uses system gmtime_r
689
687
  function for conversions and is always available. It is used only for
690
 
  my_time_t -> DRIZZLE_TIME conversions in various UTC_...  functions, it is not
691
 
  intended for DRIZZLE_TIME -> my_time_t conversions and shouldn't be exposed to user.
 
688
  time_t -> DRIZZLE_TIME conversions in various UTC_...  functions, it is not
 
689
  intended for DRIZZLE_TIME -> time_t conversions and shouldn't be exposed to user.
692
690
*/
693
691
class Time_zone_utc : public Time_zone
694
692
{
695
693
public:
696
694
  Time_zone_utc() {}                          /* Remove gcc warning */
697
 
  virtual my_time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
 
695
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
698
696
                                    bool *in_dst_time_gap) const;
699
 
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const;
 
697
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
700
698
  virtual const String * get_name() const;
701
699
};
702
700
 
703
701
 
704
702
/*
705
 
  Convert UTC time from DRIZZLE_TIME representation to its my_time_t representation.
 
703
  Convert UTC time from DRIZZLE_TIME representation to its time_t representation.
706
704
 
707
705
  SYNOPSIS
708
706
    TIME_to_gmt_sec()
713
711
                        spring time-gap) and is not touched otherwise.
714
712
 
715
713
  DESCRIPTION
716
 
    Since Time_zone_utc is used only internally for my_time_t -> TIME
 
714
    Since Time_zone_utc is used only internally for time_t -> TIME
717
715
    conversions, this function of Time_zone interface is not implemented for
718
716
    this class and should not be called.
719
717
 
720
718
  RETURN VALUE
721
719
    0
722
720
*/
723
 
my_time_t
724
 
Time_zone_utc::TIME_to_gmt_sec(const DRIZZLE_TIME *t __attribute__((unused)),
725
 
                               bool *in_dst_time_gap __attribute__((unused))) const
 
721
time_t
 
722
Time_zone_utc::TIME_to_gmt_sec(const DRIZZLE_TIME *,
 
723
                               bool *) const
726
724
{
727
725
  /* Should be never called */
728
726
  assert(0);
731
729
 
732
730
 
733
731
/*
734
 
  Converts time from UTC seconds since Epoch (my_time_t) representation
 
732
  Converts time from UTC seconds since Epoch (time_t) representation
735
733
  to broken-down representation (also in UTC).
736
734
 
737
735
  SYNOPSIS
738
736
    gmt_sec_to_TIME()
739
737
      tmp - pointer to DRIZZLE_TIME structure to fill-in
740
 
      t   - my_time_t value to be converted
 
738
      t   - time_t value to be converted
741
739
 
742
740
  NOTE
743
741
    See note for apropriate Time_zone_system method.
744
742
*/
745
743
void
746
 
Time_zone_utc::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const
 
744
Time_zone_utc::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
747
745
{
748
746
  struct tm tmp_tm;
749
747
  time_t tmp_t= (time_t)t;
784
782
{
785
783
public:
786
784
  Time_zone_db(TIME_ZONE_INFO *tz_info_arg, const String * tz_name_arg);
787
 
  virtual my_time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
 
785
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
788
786
                                    bool *in_dst_time_gap) const;
789
 
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const;
 
787
  virtual void gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
790
788
  virtual const String * get_name() const;
791
789
private:
792
790
  TIME_ZONE_INFO *tz_info;
816
814
 
817
815
/*
818
816
  Converts local time in time zone described from TIME
819
 
  representation to its my_time_t representation.
 
817
  representation to its time_t representation.
820
818
 
821
819
  SYNOPSIS
822
820
    TIME_to_gmt_sec()
831
829
    parameter restrictions.
832
830
 
833
831
  RETURN VALUE
834
 
    Corresponding my_time_t value or 0 in case of error
 
832
    Corresponding time_t value or 0 in case of error
835
833
*/
836
 
my_time_t
 
834
time_t
837
835
Time_zone_db::TIME_to_gmt_sec(const DRIZZLE_TIME *t, bool *in_dst_time_gap) const
838
836
{
839
837
  return ::TIME_to_gmt_sec(t, tz_info, in_dst_time_gap);
841
839
 
842
840
 
843
841
/*
844
 
  Converts time from UTC seconds since Epoch (my_time_t) representation
 
842
  Converts time from UTC seconds since Epoch (time_t) representation
845
843
  to local time zone described in broken-down representation.
846
844
 
847
845
  SYNOPSIS
848
846
    gmt_sec_to_TIME()
849
847
      tmp - pointer to DRIZZLE_TIME structure to fill-in
850
 
      t   - my_time_t value to be converted
 
848
      t   - time_t value to be converted
851
849
*/
852
850
void
853
 
Time_zone_db::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const
 
851
Time_zone_db::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
854
852
{
855
853
  ::gmt_sec_to_TIME(tmp, t, tz_info);
856
854
}
880
878
{
881
879
public:
882
880
  Time_zone_offset(long tz_offset_arg);
883
 
  virtual my_time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
 
881
  virtual time_t TIME_to_gmt_sec(const DRIZZLE_TIME *t,
884
882
                                    bool *in_dst_time_gap) const;
885
 
  virtual void   gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const;
 
883
  virtual void   gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const;
886
884
  virtual const String * get_name() const;
887
885
  /*
888
886
    This have to be public because we want to be able to access it from
907
905
Time_zone_offset::Time_zone_offset(long tz_offset_arg):
908
906
  offset(tz_offset_arg)
909
907
{
910
 
  uint hours= abs((int)(offset / SECS_PER_HOUR));
911
 
  uint minutes= abs((int)(offset % SECS_PER_HOUR / SECS_PER_MIN));
 
908
  uint32_t hours= abs((int)(offset / SECS_PER_HOUR));
 
909
  uint32_t minutes= abs((int)(offset % SECS_PER_HOUR / SECS_PER_MIN));
912
910
  ulong length= snprintf(name_buff, sizeof(name_buff), "%s%02d:%02d",
913
911
                         (offset>=0) ? "+" : "-", hours, minutes);
914
 
  name.set(name_buff, length, &my_charset_latin1);
 
912
  name.set(name_buff, length, &my_charset_utf8_general_ci);
915
913
}
916
914
 
917
915
 
918
916
/*
919
917
  Converts local time in time zone described as offset from UTC
920
 
  from DRIZZLE_TIME representation to its my_time_t representation.
 
918
  from DRIZZLE_TIME representation to its time_t representation.
921
919
 
922
920
  SYNOPSIS
923
921
    TIME_to_gmt_sec()
930
928
                        It is not really used in this class.
931
929
 
932
930
  RETURN VALUE
933
 
    Corresponding my_time_t value or 0 in case of error
 
931
    Corresponding time_t value or 0 in case of error
934
932
*/
935
 
my_time_t
 
933
time_t
936
934
Time_zone_offset::TIME_to_gmt_sec(const DRIZZLE_TIME *t,
937
 
                                  bool *in_dst_time_gap __attribute__((unused))) const
 
935
                                  bool *) const
938
936
{
939
 
  my_time_t local_t;
 
937
  time_t local_t;
940
938
  int shift= 0;
941
939
 
942
940
  /*
948
946
 
949
947
  /*
950
948
    Do a temporary shift of the boundary dates to avoid
951
 
    overflow of my_time_t if the time value is near it's
 
949
    overflow of time_t if the time value is near it's
952
950
    maximum range
953
951
  */
954
952
  if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4)
973
971
 
974
972
 
975
973
/*
976
 
  Converts time from UTC seconds since Epoch (my_time_t) representation
 
974
  Converts time from UTC seconds since Epoch (time_t) representation
977
975
  to local time zone described as offset from UTC and in broken-down
978
976
  representation.
979
977
 
980
978
  SYNOPSIS
981
979
    gmt_sec_to_TIME()
982
980
      tmp - pointer to DRIZZLE_TIME structure to fill-in
983
 
      t   - my_time_t value to be converted
 
981
      t   - time_t value to be converted
984
982
*/
985
983
void
986
 
Time_zone_offset::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, my_time_t t) const
 
984
Time_zone_offset::gmt_sec_to_TIME(DRIZZLE_TIME *tmp, time_t t) const
987
985
{
988
986
  sec_to_TIME(tmp, t, offset);
989
987
}
1009
1007
static Time_zone_system tz_SYSTEM;
1010
1008
static Time_zone_offset tz_OFFSET0(0);
1011
1009
 
1012
 
Time_zone *my_tz_OFFSET0= &tz_OFFSET0;
1013
 
Time_zone *my_tz_UTC= &tz_UTC;
1014
1010
Time_zone *my_tz_SYSTEM= &tz_SYSTEM;
1015
1011
 
1016
1012
class Tz_names_entry: public Sql_alloc
1026
1022
 
1027
1023
  SYNOPSIS
1028
1024
    my_tz_init()
1029
 
      thd            - current thread object
 
1025
      session            - current thread object
1030
1026
      default_tzname - default time zone or 0 if none.
1031
1027
      bootstrap      - indicates whenever we are in bootstrap mode
1032
1028
 
1047
1043
    1 - Error
1048
1044
*/
1049
1045
bool
1050
 
my_tz_init(THD *thd, const char *default_tzname,
1051
 
           bool bootstrap __attribute__((unused)))
 
1046
my_tz_init(Session *session, const char *default_tzname)
1052
1047
{
1053
1048
  if (default_tzname)
1054
1049
  {
1055
 
    String tmp_tzname2(default_tzname, &my_charset_latin1);
 
1050
    String tmp_tzname2(default_tzname, &my_charset_utf8_general_ci);
1056
1051
    /*
1057
1052
      Time zone tables may be open here, and my_tz_find() may open
1058
1053
      most of them once more, but this is OK for system tables open
1059
1054
      for READ.
1060
1055
    */
1061
 
    if (!(global_system_variables.time_zone= my_tz_find(thd, &tmp_tzname2)))
 
1056
    if (!(global_system_variables.time_zone= my_tz_find(session, &tmp_tzname2)))
1062
1057
    {
1063
 
      sql_print_error(_("Fatal error: Illegal or unknown default time zone '%s'"),
1064
 
                      default_tzname);
 
1058
      errmsg_printf(ERRMSG_LVL_ERROR,
 
1059
                    _("Fatal error: Illegal or unknown default time zone '%s'"),
 
1060
                    default_tzname);
1065
1061
      return true;
1066
1062
    }
1067
1063
  }
1069
1065
  return false;
1070
1066
}
1071
1067
 
1072
 
 
1073
 
/*
1074
 
  Free resources used by time zone support infrastructure.
1075
 
*/
1076
 
 
1077
 
void my_tz_free()
1078
 
{
1079
 
}
1080
 
 
1081
 
 
1082
 
/*
1083
 
  Parse string that specifies time zone as offset from UTC.
1084
 
 
1085
 
  SYNOPSIS
1086
 
    str_to_offset()
1087
 
      str    - pointer to string which contains offset
1088
 
      length - length of string
1089
 
      offset - out parameter for storing found offset in seconds.
1090
 
 
1091
 
  DESCRIPTION
1092
 
    This function parses string which contains time zone offset
1093
 
    in form similar to '+10:00' and converts found value to
1094
 
    seconds from UTC form (east is positive).
1095
 
 
1096
 
  RETURN VALUE
1097
 
    0 - Ok
1098
 
    1 - String doesn't contain valid time zone offset
1099
 
*/
1100
 
bool
1101
 
str_to_offset(const char *str, uint length, long *offset)
1102
 
{
1103
 
  const char *end= str + length;
1104
 
  bool negative;
1105
 
  ulong number_tmp;
1106
 
  long offset_tmp;
1107
 
 
1108
 
  if (length < 4)
1109
 
    return 1;
1110
 
 
1111
 
  if (*str == '+')
1112
 
    negative= 0;
1113
 
  else if (*str == '-')
1114
 
    negative= 1;
1115
 
  else
1116
 
    return 1;
1117
 
  str++;
1118
 
 
1119
 
  number_tmp= 0;
1120
 
 
1121
 
  while (str < end && my_isdigit(&my_charset_latin1, *str))
1122
 
  {
1123
 
    number_tmp= number_tmp*10 + *str - '0';
1124
 
    str++;
1125
 
  }
1126
 
 
1127
 
  if (str + 1 >= end || *str != ':')
1128
 
    return 1;
1129
 
  str++;
1130
 
 
1131
 
  offset_tmp = number_tmp * MINS_PER_HOUR; number_tmp= 0;
1132
 
 
1133
 
  while (str < end && my_isdigit(&my_charset_latin1, *str))
1134
 
  {
1135
 
    number_tmp= number_tmp * 10 + *str - '0';
1136
 
    str++;
1137
 
  }
1138
 
 
1139
 
  if (str != end)
1140
 
    return 1;
1141
 
 
1142
 
  offset_tmp= (offset_tmp + number_tmp) * SECS_PER_MIN;
1143
 
 
1144
 
  if (negative)
1145
 
    offset_tmp= -offset_tmp;
1146
 
 
1147
 
  /*
1148
 
    Check if offset is in range prescribed by standard
1149
 
    (from -12:59 to 13:00).
1150
 
  */
1151
 
 
1152
 
  if (number_tmp > 59 || offset_tmp < -13 * SECS_PER_HOUR + 1 ||
1153
 
      offset_tmp > 13 * SECS_PER_HOUR)
1154
 
    return 1;
1155
 
 
1156
 
  *offset= offset_tmp;
1157
 
 
1158
 
  return 0;
1159
 
}
1160
 
 
1161
 
 
1162
1068
/*
1163
1069
  Get Time_zone object for specified time zone.
1164
1070
 
1166
1072
 
1167
1073
*/
1168
1074
Time_zone *
1169
 
my_tz_find(THD *thd __attribute__((unused)),
1170
 
           const String *name __attribute__((unused)))
 
1075
my_tz_find(Session *,
 
1076
           const String *)
1171
1077
{
1172
1078
  return NULL;
1173
1079
}