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
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
67
65
uint32_t timecnt; // Number of transitions between time types
68
66
uint32_t typecnt; // Number of local time types
69
67
uint32_t charcnt; // Number of characters used for abbreviations
70
uint32_t revcnt; // Number of transition descr. for TIME->my_time_t conversion
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
70
time_t *ats; // Times of transitions between time types
73
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
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)
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)])
189
187
for (tmp->month= 0; days >= (long) ip[tmp->month]; tmp->month++)
190
188
days= days - (long) ip[tmp->month];
192
tmp->day= (uint)(days + 1);
190
tmp->day= (uint32_t)(days + 1);
194
192
/* filling MySQL specific DRIZZLE_TIME members */
195
193
tmp->neg= 0; tmp->second_part= 0;
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,
223
221
uint32_t higher_bound)
225
223
uint32_t i, lower_bound= 0;
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;
831
829
parameter restrictions.
834
Corresponding my_time_t value or 0 in case of error
832
Corresponding time_t value or 0 in case of error
837
835
Time_zone_db::TIME_to_gmt_sec(const DRIZZLE_TIME *t, bool *in_dst_time_gap) const
839
837
return ::TIME_to_gmt_sec(t, tz_info, in_dst_time_gap);
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
930
928
It is not really used in this class.
933
Corresponding my_time_t value or 0 in case of error
931
Corresponding time_t value or 0 in case of error
936
934
Time_zone_offset::TIME_to_gmt_sec(const DRIZZLE_TIME *t,
937
bool *in_dst_time_gap __attribute__((unused))) const
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);
1058
1055
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)))
1058
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'"),
1060
errmsg_printf(ERRMSG_LVL_ERROR,
1061
_("Fatal error: Illegal or unknown default time zone '%s'"),