1
/* Copyright (C) 2004 MySQL AB
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.
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.
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 */
16
#ifdef USE_PRAGMA_IMPLEMENTATION
17
#pragma implementation // gcc: Class implementation
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
20
21
#include <drizzled/server_includes.h>
22
#include <drizzled/tzfile.h>
23
#include <drizzled/tztime.h>
24
#include <drizzled/gettext.h>
25
#include <drizzled/session.h>
23
27
/* Structure describing local time type (e.g. Moscow summer time (MSD)) */
24
28
typedef struct ttinfo
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.
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
38
my_time_t ls_trans; // Transition time
42
time_t ls_trans; // Transition time
39
43
long ls_corr; // Correction to apply
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.
47
51
typedef struct revtinfo
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
54
#define MY_TZNAME_MAX TZNAME_MAX
57
#define MY_TZNAME_MAX 255
61
59
Structure which fully describes time zone which is
64
62
typedef struct st_time_zone_info
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 */
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.
90
88
Time type which is used for times smaller than first transition or if
98
96
#if !defined(TZINFO2SQL)
100
static const uint mon_lengths[2][MONS_PER_YEAR]=
98
static const uint32_t mon_lengths[2][MONS_PER_YEAR]=
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 }
106
static const uint mon_starts[2][MONS_PER_YEAR]=
104
static const uint32_t mon_starts[2][MONS_PER_YEAR]=
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 }
112
static const uint year_lengths[2]=
110
static const uint32_t year_lengths[2]=
114
112
DAYS_PER_NYEAR, DAYS_PER_LYEAR
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.
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
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.
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)
146
144
days= (long) (t / SECS_PER_DAY);
147
145
rem= (long) (t % SECS_PER_DAY);
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.
161
159
rem -= SECS_PER_DAY;
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);
168
166
A positive leap second requires a special
169
167
representation. This uses "... ??:59:60" et seq.
171
tmp->second= (uint)(rem % SECS_PER_MIN);
169
tmp->second= (uint32_t)(rem % SECS_PER_MIN);
174
172
while (days < 0 || days >= (long)year_lengths[yleap= isleap(y)])
201
Find time range wich contains given my_time_t value
199
Find time range wich contains given time_t value
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
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.
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
222
find_time_range(my_time_t t, const my_time_t *range_boundaries,
220
find_time_range(time_t t, const time_t *range_boundaries,
221
uint32_t higher_bound)
225
uint i, lower_bound= 0;
223
uint32_t i, lower_bound= 0;
228
226
Function will work without this assertion but result would be meaningless.
251
Find local time transition for given my_time_t.
249
Find local time transition for given time_t.
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
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.
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)
266
264
if (unlikely(sp->timecnt == 0 || t < sp->ats[0]))
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.
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
298
296
(60th and 61st second, look how we calculate them as "hit" in this
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.
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)
308
306
const TRAN_TYPE_INFO *ttisp;
309
307
const LS_INFO *lp;
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.
365
363
sec_since_epoch()
366
364
year, mon, mday, hour, min, sec - broken down representation.
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.
375
373
Seconds since epoch time representation.
378
376
sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec)
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
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).
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
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.
496
494
saved_seconds= t->second;
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().
503
501
However in that function we also have to take into account
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))
550
return(0); /* my_time_t overflow */
548
return(0); /* time_t overflow */
552
550
local_t+= shift * SECS_PER_DAY;
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;
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.
615
613
TIME_to_gmt_sec()
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.
630
628
You should call init_time() function before using this function.
633
Corresponding my_time_t value or 0 in case of error
631
Corresponding time_t value or 0 in case of error
636
634
Time_zone_system::TIME_to_gmt_sec(const DRIZZLE_TIME *t, bool *in_dst_time_gap) const
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.
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
653
651
We assume that value passed to this function will fit into time_t range
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.
693
691
class Time_zone_utc : public Time_zone
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;
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.
708
706
TIME_to_gmt_sec()
713
711
spring time-gap) and is not touched otherwise.
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.
724
Time_zone_utc::TIME_to_gmt_sec(const DRIZZLE_TIME *t __attribute__((unused)),
725
bool *in_dst_time_gap __attribute__((unused))) const
722
Time_zone_utc::TIME_to_gmt_sec(const DRIZZLE_TIME *,
727
725
/* Should be never called */
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).
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
743
741
See note for apropriate Time_zone_system method.
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
748
746
struct tm tmp_tm;
749
747
time_t tmp_t= (time_t)t;
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;
792
790
TIME_ZONE_INFO *tz_info;
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.
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
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
855
853
::gmt_sec_to_TIME(tmp, t, tz_info);
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;
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)
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);
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.
923
921
TIME_to_gmt_sec()
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
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
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
988
986
sec_to_TIME(tmp, t, offset);
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)
1053
1048
if (default_tzname)
1055
String tmp_tzname2(default_tzname, &my_charset_latin1);
1050
String tmp_tzname2(default_tzname, &my_charset_utf8_general_ci);
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
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)))
1063
sql_print_error(_("Fatal error: Illegal or unknown default time zone '%s'"),
1058
errmsg_printf(ERRMSG_LVL_ERROR,
1059
_("Fatal error: Illegal or unknown default time zone '%s'"),
1074
Free resources used by time zone support infrastructure.
1083
Parse string that specifies time zone as offset from UTC.
1087
str - pointer to string which contains offset
1088
length - length of string
1089
offset - out parameter for storing found offset in seconds.
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).
1098
1 - String doesn't contain valid time zone offset
1101
str_to_offset(const char *str, uint length, long *offset)
1103
const char *end= str + length;
1113
else if (*str == '-')
1121
while (str < end && my_isdigit(&my_charset_latin1, *str))
1123
number_tmp= number_tmp*10 + *str - '0';
1127
if (str + 1 >= end || *str != ':')
1131
offset_tmp = number_tmp * MINS_PER_HOUR; number_tmp= 0;
1133
while (str < end && my_isdigit(&my_charset_latin1, *str))
1135
number_tmp= number_tmp * 10 + *str - '0';
1142
offset_tmp= (offset_tmp + number_tmp) * SECS_PER_MIN;
1145
offset_tmp= -offset_tmp;
1148
Check if offset is in range prescribed by standard
1149
(from -12:59 to 13:00).
1152
if (number_tmp > 59 || offset_tmp < -13 * SECS_PER_HOUR + 1 ||
1153
offset_tmp > 13 * SECS_PER_HOUR)
1156
*offset= offset_tmp;
1163
1069
Get Time_zone object for specified time zone.