TimezoneParser 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25ef86372b8861bf6e4971ca261cf3f3c4d820e63d59c242a6a9f253910ac2c2
4
- data.tar.gz: 0a858e6277137ac2cdb158dfbf82318bf0446d4818438dea1fa1702e18c48e29
3
+ metadata.gz: 3142c5391513b96c7862dc7220c1ccd85e4288366a361935054113cc22629594
4
+ data.tar.gz: 5435d8f578bebcdb8ac8cba258b0a295e6c1b9bb6e0f3c1cdd2c32146150b70f
5
5
  SHA512:
6
- metadata.gz: 36277f05b9a6334c8b838bc333422b570e3984b034cf2d0d44493123ac21e30ee5836142e951028ddb26e530af1178585f361aa756ed26735d2d4d50048a58d5
7
- data.tar.gz: 6489d950773033d0d4c1ece559051c3e8e593a0a26fde08708255d63726819b7f2ca184adeedc5f24c5af293495450d9532e11ac796d8d5190d530cd116ec9a1
6
+ metadata.gz: ea39d10652896a5a4c21dca7943f6fc03493206e5286ba06b1ca993112557cf0aa2851470681f45468f676d4740659d5f5ab69cbe9ed40a58f1d276c0d7afce4
7
+ data.tar.gz: afab3a15077508cc496337d72af6d4d9f9bcf8c86decefa64ba2cd571ba081315b46d318a93ccaa00f4c905c317a5fb77bb10a625a186ae0d3ca1de633e57533
data/.gitignore CHANGED
@@ -16,4 +16,4 @@ test/tmp
16
16
  test/version_tmp
17
17
  vendor/
18
18
  tmp
19
- /data/*.dat
19
+ /data/*.db
data/README.md CHANGED
@@ -102,7 +102,6 @@ code coverage will also be generated
102
102
  ## Code status
103
103
  [![Gem Version](https://badge.fury.io/rb/TimezoneParser.png)](http://badge.fury.io/rb/TimezoneParser)
104
104
  [![Build Status](https://travis-ci.org/davispuh/TimezoneParser.png?branch=master)](https://travis-ci.org/davispuh/TimezoneParser)
105
- [![Dependency Status](https://gemnasium.com/davispuh/TimezoneParser.png)](https://gemnasium.com/davispuh/TimezoneParser)
106
105
  [![Coverage Status](https://coveralls.io/repos/davispuh/TimezoneParser/badge.png?branch=master)](https://coveralls.io/r/davispuh/TimezoneParser?branch=master)
107
106
  [![Code Climate](https://codeclimate.com/github/davispuh/TimezoneParser.png)](https://codeclimate.com/github/davispuh/TimezoneParser)
108
107
 
data/Rakefile CHANGED
@@ -5,6 +5,7 @@ require 'yard'
5
5
  require 'yaml'
6
6
  require 'pathname'
7
7
  require 'timezone_parser/data'
8
+ require 'timezone_parser/data/exporter'
8
9
 
9
10
  desc 'Default: run specs.'
10
11
  task :default => :spec
@@ -206,10 +207,7 @@ end
206
207
 
207
208
  desc 'Export data'
208
209
  task 'export' do
209
- ['abbreviations.yaml', 'timezones.yaml', 'countries.yaml', 'metazones.yaml',
210
- 'windows_zonenames.yaml', 'windows_timezones.yaml', 'windows_offsets.yaml',
211
- 'rails.yaml', 'rails_i18n.yaml'].each do |name|
212
- path = data_location + name
213
- Marshal.dump(YAML.load_file(path), File.open(path.dirname + (path.basename('.*').to_s + '.dat'), 'wb'))
214
- end
210
+ exporter = TimezoneParser::Data::Exporter.new(data_location)
211
+ exporter.exportDatabase
215
212
  end
213
+
@@ -16,11 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files`.split($/)
17
17
  spec.files.delete_if { |name| name[-4, 4] == '.yaml' }
18
18
  spec.files << 'data/version.yaml'
19
- ['abbreviations.dat', 'countries.dat', 'metazones.dat',
20
- 'rails.dat', 'rails_i18n.dat', 'timezones.dat',
21
- 'windows_offsets.dat', 'windows_timezones.dat', 'windows_zonenames.dat'].each do |name|
22
- spec.files << 'data/' + name
23
- end
19
+ spec.files << 'data/timezones.db'
24
20
 
25
21
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
26
22
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
@@ -28,6 +24,7 @@ Gem::Specification.new do |spec|
28
24
 
29
25
  spec.add_runtime_dependency 'tzinfo'
30
26
  spec.add_runtime_dependency 'insensitive_hash'
27
+ spec.add_runtime_dependency 'sqlite3'
31
28
 
32
29
  spec.add_development_dependency 'bundler', '>= 1.3'
33
30
  spec.add_development_dependency 'rake'
@@ -0,0 +1,164 @@
1
+
2
+ CREATE TABLE Timezones (`ID` INTEGER PRIMARY KEY,
3
+ `Name` TEXT NOT NULL COLLATE NOCASE);
4
+ CREATE UNIQUE INDEX IDX_Timezones ON Timezones (`Name`);
5
+
6
+
7
+ CREATE TABLE Territories (`ID` INTEGER PRIMARY KEY,
8
+ `Territory` TEXT NOT NULL COLLATE NOCASE);
9
+ CREATE UNIQUE INDEX IDX_Territories ON Territories (`Territory`);
10
+
11
+
12
+ CREATE TABLE TerritoryContainment (`ID` INTEGER PRIMARY KEY,
13
+ `Parent` INTEGER NOT NULL,
14
+ `Territory` INTEGER NOT NULL,
15
+ FOREIGN KEY(`Parent`) REFERENCES Territories(`ID`),
16
+ FOREIGN KEY(`Territory`) REFERENCES Territories(`ID`));
17
+ CREATE UNIQUE INDEX IDX_TerritoryContainment ON TerritoryContainment (`Parent`, `Territory`);
18
+
19
+
20
+ CREATE TABLE TimezoneTerritories (`ID` INTEGER PRIMARY KEY,
21
+ `Timezone` INTEGER NOT NULL,
22
+ `Territory` INTEGER NOT NULL,
23
+ FOREIGN KEY(`Territory`) REFERENCES Territories(`ID`));
24
+ CREATE UNIQUE INDEX IDX_TimezoneTerritories ON TimezoneTerritories (`Timezone`, `Territory`);
25
+
26
+
27
+ CREATE TABLE Locales (`ID` INTEGER PRIMARY KEY,
28
+ `Name` TEXT NOT NULL COLLATE NOCASE,
29
+ `Parent` INTEGER);
30
+ CREATE UNIQUE INDEX IDX_Locales ON Locales (`Name`);
31
+
32
+
33
+ CREATE TABLE TimezoneNames (`ID` INTEGER PRIMARY KEY,
34
+ `Locale` INTEGER NOT NULL,
35
+ `Name` TEXT NOT NULL COLLATE BINARY,
36
+ `NameLowercase` TEXT NOT NULL COLLATE NOCASE,
37
+ `Types` INTEGER,
38
+ FOREIGN KEY(`Locale`) REFERENCES Locales(`ID`));
39
+ CREATE UNIQUE INDEX IDX_TimezoneNames ON TimezoneNames (`Locale`, `Name`);
40
+ CREATE INDEX IDX_TimezoneNamesLowercase ON TimezoneNames (`NameLowercase`);
41
+
42
+
43
+ CREATE TABLE Metazones (`ID` INTEGER PRIMARY KEY,
44
+ `Name` TEXT NOT NULL COLLATE NOCASE);
45
+ CREATE UNIQUE INDEX IDX_Metazones ON Metazones (`Name`);
46
+
47
+
48
+ CREATE TABLE MetazonePeriods (`ID` INTEGER PRIMARY KEY,
49
+ `Metazone` INTEGER NOT NULL,
50
+ `From` TEXT,
51
+ `To` TEXT,
52
+ FOREIGN KEY(`Metazone`) REFERENCES Metazones(`ID`));
53
+ CREATE UNIQUE INDEX IDX_MetazonePeriods ON MetazonePeriods (`Metazone`, `From`, `To`);
54
+
55
+
56
+ CREATE TABLE MetazonePeriod_Timezones (`ID` INTEGER PRIMARY KEY,
57
+ `MetazonePeriod` INTEGER NOT NULL,
58
+ `Timezone` INTEGER NOT NULL,
59
+ FOREIGN KEY(`MetazonePeriod`) REFERENCES MetazonePeriods(`ID`),
60
+ FOREIGN KEY(`Timezone`) REFERENCES Timezones(`ID`));
61
+ CREATE UNIQUE INDEX IDX_MetazonePeriod_Timezones ON MetazonePeriod_Timezones (`MetazonePeriod`, `Timezone`);
62
+
63
+
64
+ CREATE TABLE TimezoneName_Timezones (`ID` INTEGER PRIMARY KEY,
65
+ `Name` INTEGER NOT NULL,
66
+ `Timezone` INTEGER NOT NULL,
67
+ FOREIGN KEY(`Name`) REFERENCES TimezoneNames(`ID`),
68
+ FOREIGN KEY(`Timezone`) REFERENCES Timezones(`ID`));
69
+ CREATE UNIQUE INDEX IDX_TimezoneName_Timezones ON TimezoneName_Timezones (`Name`, `Timezone`);
70
+
71
+
72
+ CREATE TABLE TimezoneName_Metazones (`ID` INTEGER PRIMARY KEY,
73
+ `Name` INTEGER NOT NULL,
74
+ `Metazone` INTEGER NOT NULL,
75
+ FOREIGN KEY(`Name`) REFERENCES TimezoneNames(`ID`),
76
+ FOREIGN KEY(`Metazone`) REFERENCES Metazones(`ID`));
77
+ CREATE UNIQUE INDEX IDX_TimezoneName_Metazones ON TimezoneName_Metazones (`Name`, `Metazone`);
78
+
79
+
80
+ CREATE TABLE Abbreviations (`ID` INTEGER PRIMARY KEY,
81
+ `Name` TEXT NOT NULL COLLATE BINARY,
82
+ `NameLowercase` TEXT NOT NULL COLLATE NOCASE);
83
+ CREATE UNIQUE INDEX IDX_Abbreviations ON Abbreviations (`Name`);
84
+ CREATE UNIQUE INDEX IDX_AbbreviationsLowercase ON Abbreviations (`NameLowercase`);
85
+
86
+
87
+ CREATE TABLE AbbreviationOffsets (`ID` INTEGER PRIMARY KEY,
88
+ `Abbreviation` INTEGER NOT NULL,
89
+ `Offset` INTEGER,
90
+ `Types` INTEGER,
91
+ `From` TEXT,
92
+ `To` TEXT,
93
+ FOREIGN KEY(`Abbreviation`) REFERENCES Abbreviations(`ID`));
94
+ CREATE UNIQUE INDEX IDX_AbbreviationOffsets ON AbbreviationOffsets (`Abbreviation`, `Offset`, `From`, `To`);
95
+
96
+
97
+ CREATE TABLE AbbreviationOffset_Timezones (`ID` INTEGER PRIMARY KEY,
98
+ `Offset` INTEGER NOT NULL,
99
+ `Timezone` INTEGER NOT NULL,
100
+ FOREIGN KEY(`Offset`) REFERENCES AbbreviationOffsets(`ID`),
101
+ FOREIGN KEY(`Timezone`) REFERENCES Timezones(`ID`));
102
+ CREATE UNIQUE INDEX IDX_AbbreviationOffset_Timezones ON AbbreviationOffset_Timezones (`Offset`, `Timezone`);
103
+
104
+
105
+ CREATE TABLE AbbreviationOffset_Metazones (`ID` INTEGER PRIMARY KEY,
106
+ `Offset` INTEGER NOT NULL,
107
+ `Metazone` INTEGER NOT NULL,
108
+ FOREIGN KEY(`Offset`) REFERENCES AbbreviationOffsets(`ID`),
109
+ FOREIGN KEY(`Metazone`) REFERENCES Metazones(`ID`));
110
+ CREATE UNIQUE INDEX IDX_AbbreviationOffset_Metazones ON AbbreviationOffset_Metazones (`Offset`, `Metazone`);
111
+
112
+
113
+ CREATE TABLE RailsTimezones (`ID` INTEGER PRIMARY KEY,
114
+ `Name` TEXT NOT NULL COLLATE NOCASE,
115
+ `Timezone` INTEGER NOT NULL,
116
+ FOREIGN KEY(`Timezone`) REFERENCES Timezones(`ID`));
117
+ CREATE UNIQUE INDEX IDX_RailsTimezones ON RailsTimezones (`Name`);
118
+
119
+
120
+ CREATE TABLE RailsI18N (`ID` INTEGER PRIMARY KEY,
121
+ `Locale` INTEGER NOT NULL,
122
+ `Name` TEXT NOT NULL COLLATE BINARY,
123
+ `NameLowercase` TEXT NOT NULL COLLATE NOCASE,
124
+ `Zone` INTEGER NOT NULL,
125
+ FOREIGN KEY(`Locale`) REFERENCES Locales(`ID`),
126
+ FOREIGN KEY(`Zone`) REFERENCES RailsTimezones(`ID`));
127
+ CREATE UNIQUE INDEX IDX_RailsI18N ON RailsI18N (`Locale`, `Name`);
128
+ CREATE INDEX IDX_RailsI18NName ON RailsI18N (`NameLowercase`);
129
+
130
+
131
+ CREATE TABLE WindowsZones (`ID` INTEGER PRIMARY KEY,
132
+ `Name` TEXT NOT NULL COLLATE NOCASE,
133
+ `Standard` INTEGER NOT NULL,
134
+ `Daylight` INTEGER NOT NULL);
135
+ CREATE UNIQUE INDEX IDX_WindowsZones ON WindowsZones (`Name`);
136
+
137
+
138
+ CREATE TABLE WindowsZone_Timezones (`ID` INTEGER PRIMARY KEY,
139
+ `Zone` INTEGER NOT NULL,
140
+ `Territory` INTEGER NOT NULL,
141
+ `Timezone` INTEGER NOT NULL,
142
+ FOREIGN KEY(`Zone`) REFERENCES WindowsZones(`ID`),
143
+ FOREIGN KEY(`Territory`) REFERENCES Territories(`ID`),
144
+ FOREIGN KEY(`Timezone`) REFERENCES Timezones(`ID`));
145
+ CREATE UNIQUE INDEX IDX_WindowsZone_Timezones ON WindowsZone_Timezones (`Zone`, `Territory`, `Timezone`);
146
+
147
+
148
+ CREATE TABLE WindowsZoneNames (`ID` INTEGER PRIMARY KEY,
149
+ `Locale` INTEGER NOT NULL,
150
+ `Name` TEXT NOT NULL COLLATE BINARY,
151
+ `NameLowercase` TEXT NOT NULL COLLATE NOCASE,
152
+ `Types` INTEGER,
153
+ FOREIGN KEY(`Locale`) REFERENCES Locales(`ID`));
154
+ CREATE UNIQUE INDEX IDX_WindowsZoneNames ON WindowsZoneNames (`Locale`, `Name`);
155
+ CREATE INDEX IDX_WindowsZoneNamesLowercase ON WindowsZoneNames (`NameLowercase`);
156
+
157
+
158
+ CREATE TABLE WindowsZoneName_Zones (`ID` INTEGER PRIMARY KEY,
159
+ `Name` INTEGER NOT NULL,
160
+ `Zone` INTEGER NOT NULL,
161
+ FOREIGN KEY(`Name`) REFERENCES WindowsZoneNames(`ID`),
162
+ FOREIGN KEY(`Zone`) REFERENCES WindowsZones(`ID`));
163
+ CREATE UNIQUE INDEX IDX_WindowsZoneName_Zones ON WindowsZoneName_Zones (`Name`, `Zone`);
164
+
@@ -49,17 +49,6 @@ module TimezoneParser
49
49
  @@Locales
50
50
  end
51
51
 
52
- # Load Timezone data in memory from files
53
- #
54
- # If no modules are specified it will load default modules
55
- # @param modules [Array<Symbol>] list of modules
56
- # @see Modules
57
- # @see AllModules
58
- def self.preload(modules = @@Modules)
59
- modules = AllModules if modules.nil? or modules.empty?
60
- Data::Storage.preload(modules)
61
- end
62
-
63
52
  # Check if given Timezone name is a valid timezone
64
53
  # @param name [String] either Timezone name or abbreviation
65
54
  # @param locales [Array<String>] check only for these locales
@@ -112,13 +101,13 @@ module TimezoneParser
112
101
  offsets += Abbreviation::getOffsets(name, toTime, fromTime, regions, type) if modules.include?(:Abbreviations)
113
102
  return offsets.to_a if not all and not offsets.empty?
114
103
 
115
- offsets += Timezone::getOffsets(name, toTime, fromTime, locales, regions, all) if modules.include?(:Timezones)
104
+ offsets += Timezone::getOffsets(name, toTime, fromTime, locales, regions) if modules.include?(:Timezones)
116
105
  return offsets.to_a if not all and not offsets.empty?
117
106
 
118
- offsets += WindowsZone::getOffsets(name, locales, all) if modules.include?(:WindowsZones)
107
+ offsets += WindowsZone::getOffsets(name, locales) if modules.include?(:WindowsZones)
119
108
  return offsets.to_a if not all and not offsets.empty?
120
109
 
121
- offsets += RailsZone::getOffsets(name, toTime, fromTime, locales, all) if modules.include?(:RailsZones)
110
+ offsets += RailsZone::getOffsets(name, toTime, fromTime, locales) if modules.include?(:RailsZones)
122
111
  offsets.to_a
123
112
  end
124
113
 
@@ -146,13 +135,13 @@ module TimezoneParser
146
135
  timezones += Abbreviation::getTimezones(name, toTime, fromTime, regions, type) if modules.include?(:Abbreviations)
147
136
  return timezones.to_a if not all and not timezones.empty?
148
137
 
149
- timezones += Timezone::getTimezones(name, toTime, fromTime, locales, regions, all) if modules.include?(:Timezones)
138
+ timezones += Timezone::getTimezones(name, toTime, fromTime, locales, regions) if modules.include?(:Timezones)
150
139
  return timezones.to_a if not all and not timezones.empty?
151
140
 
152
- timezones += WindowsZone::getTimezones(name, locales, regions, all) if modules.include?(:WindowsZones)
141
+ timezones += WindowsZone::getTimezones(name, locales, regions) if modules.include?(:WindowsZones)
153
142
  return timezones.to_a if not all and not timezones.empty?
154
143
 
155
- timezones += RailsZone::getTimezones(name, locales, all) if modules.include?(:RailsZones)
144
+ timezones += RailsZone::getTimezones(name, locales) if modules.include?(:RailsZones)
156
145
  timezones.to_a
157
146
  end
158
147
  end
@@ -23,7 +23,6 @@ module TimezoneParser
23
23
  # @param abbreviation [String] Timezone abbreviation
24
24
  def initialize(abbreviation)
25
25
  @Abbreviation = abbreviation
26
- @Data = Data.new
27
26
  setTime
28
27
  set(@@Regions.dup, nil)
29
28
  end
@@ -42,59 +41,25 @@ module TimezoneParser
42
41
  # Check if abbreviation is valid
43
42
  # @return [Boolean] whether abbreviation is valid
44
43
  def isValid?
45
- Data::Storage.Abbreviations.has_key?(@Abbreviation)
46
- end
47
-
48
- # Abbreviation data
49
- # @return [Data] data
50
- def getData
51
- unless @Loaded
52
- @Loaded = true
53
- if isValid?
54
- data = Data::Storage.Abbreviations[@Abbreviation]
55
- if data.count == 1
56
- @Data.processEntry(data.first, @ToTime, @FromTime, @Regions)
57
- return @Data
58
- end
59
- entries = Data.filterData(data, @ToTime, @FromTime, @Type, @Regions)
60
- entries.each do |entry|
61
- @Data.processEntry(entry, @ToTime, @FromTime, @Regions)
62
- end
63
- return @Data
64
- end
65
- end
66
- @Data
67
- end
68
-
69
- # Get UTC offsets in seconds
70
- # @return [Array<Fixnum>] list of timezone offsets in seconds
71
- def getOffsets
72
- unless @Offsets
73
- @Offsets = getData.Offsets.to_a
74
- if @Offsets.empty? and not getTimezones.empty?
75
- types = nil
76
- types = [@Type] if @Type
77
- @Offsets = @Data.findOffsets(@ToTime, @FromTime, @Regions, types).to_a
78
- end
44
+ if @Valid.nil?
45
+ sql = 'SELECT 1 FROM `Abbreviations` WHERE `Name` = ? LIMIT 1'
46
+ @Valid = Data::Storage.getStatement(sql).execute(@Abbreviation).count > 0
79
47
  end
80
- @Offsets
48
+ @Valid
81
49
  end
82
50
 
83
51
  # Check if given Timezone abbreviation (case-sensitive) is a valid timezone
84
52
  # @param abbreviation [String] Timezone abbreviation
85
53
  # @return [Boolean] whether Timezone is valid
86
54
  def self.isValid?(abbreviation)
87
- Data::Storage.Abbreviations.has_key?(abbreviation)
55
+ Data::Storage.getStatement('SELECT 1 FROM `Abbreviations` WHERE `Name` = ? LIMIT 1').execute(abbreviation).count > 0
88
56
  end
89
57
 
90
58
  # Check if given Timezone abbreviation (case-insensitive) could be a valid timezone
91
59
  # @param abbreviation [String] Timezone abbreviation to check for
92
60
  # @return [Boolean] whether Timezone is valid
93
61
  def self.couldBeValid?(abbreviation)
94
- Data::Storage.Abbreviations.each_key do |abbr|
95
- return true if abbr.casecmp(abbreviation).zero?
96
- end
97
- false
62
+ Data::Storage.getStatement('SELECT 1 FROM `Abbreviations` WHERE `NameLowercase` = ? LIMIT 1').execute(abbreviation.downcase).count > 0
98
63
  end
99
64
 
100
65
  # Get UTC offsets in seconds for given Timezone abbreviation
@@ -126,5 +91,111 @@ module TimezoneParser
126
91
  def self.getMetazones(abbreviation)
127
92
  self.new(abbreviation).getMetazones
128
93
  end
94
+
95
+ protected
96
+
97
+ def getFilteredData(dataType)
98
+ types = nil
99
+ types = [@Type] if @Type
100
+
101
+ params = [@Abbreviation.downcase]
102
+ column = nil
103
+ joins = ' INNER JOIN `AbbreviationOffsets` AS O ON O.Abbreviation = A.ID'
104
+ regionJoins = ''
105
+ useMetazonePeriodFilter = false
106
+ case dataType
107
+ when :Offsets, :Timezones
108
+ column = '`Timezones`.`Name`'
109
+ if dataType == :Offsets
110
+ column = 'O.`Offset`, `Timezones`.`Name`, O.`Types`'
111
+ end
112
+ joins += ' LEFT JOIN `AbbreviationOffset_Timezones` AS T ON T.Offset = O.ID'
113
+ joins += ' LEFT JOIN `AbbreviationOffset_Metazones` AS M ON M.Offset = O.ID'
114
+ joins += ' LEFT JOIN `MetazonePeriods` MP ON M.Metazone = MP.Metazone'
115
+ joins += ' LEFT JOIN `MetazonePeriod_Timezones` MPT ON MPT.MetazonePeriod = MP.ID'
116
+ joins += ' LEFT JOIN `Timezones` ON (T.Timezone = Timezones.ID OR MPT.Timezone = Timezones.ID)'
117
+ regionJoins += ' LEFT JOIN `TimezoneTerritories` ON (TimezoneTerritories.Timezone = T.Timezone OR TimezoneTerritories.Timezone = MPT.Timezone)'
118
+ regionJoins += ' LEFT JOIN `Territories` ON TimezoneTerritories.Territory = Territories.ID'
119
+ useMetazonePeriodFilter = true
120
+ when :Metazones
121
+ column = '`Metazones`.`Name`'
122
+ joins += ' INNER JOIN `AbbreviationOffset_Metazones` AS M ON M.Offset = O.ID'
123
+ joins += ' INNER JOIN `Metazones` ON M.Metazone = Metazones.ID'
124
+ regionJoins += ' LEFT JOIN `AbbreviationOffset_Timezones` AS T ON T.Offset = O.ID'
125
+ regionJoins += ' LEFT JOIN `TimezoneTerritories` ON TimezoneTerritories.Timezone = T.Timezone'
126
+ regionJoins += ' LEFT JOIN `Territories` ON TimezoneTerritories.Territory = Territories.ID'
127
+ when :Types
128
+ column = 'O.`Types`'
129
+ else
130
+ raise StandardError, "Unkown dataType '#{dataType}'"
131
+ end
132
+ sql = 'SELECT DISTINCT ' + column + ' FROM `Abbreviations` AS A'
133
+ sql += joins
134
+ if not @Regions.nil? and not @Regions.empty?
135
+ sql += regionJoins
136
+ end
137
+ sql += ' WHERE A.`NameLowercase` = ?'
138
+ if not types.nil?
139
+ if types.include?(:standard) and not types.include?(:daylight)
140
+ sql += ' AND (O.`Types` & ?) > 0'
141
+ params << TIMEZONE_TYPE_STANDARD
142
+
143
+ else
144
+ sql += ' AND (O.`Types` & ?) > 0'
145
+ params << TIMEZONE_TYPE_DAYLIGHT
146
+ end
147
+ end
148
+ unless @FromTime.nil?
149
+ fromsql = '((O.`From` IS NULL AND O.`To` > ?) OR (O.`To` IS NULL AND O.`From` <= ?) OR (O.`From` <= ? AND O.`To` > ?) OR (O.`From` IS NULL AND O.`To` IS NULL))'
150
+ params += Array.new(4, @FromTime.to_s)
151
+ if useMetazonePeriodFilter
152
+ fromsql = '(' + fromsql + ' AND ((MP.`From` IS NULL AND MP.`To` > ?) OR (MP.`To` IS NULL AND MP.`From` <= ?) OR (MP.`From` <= ? AND MP.`To` > ?) OR (MP.`From` IS NULL AND MP.`To` IS NULL)))'
153
+ params += Array.new(4, @FromTime.to_s)
154
+ end
155
+ if @ToTime.nil?
156
+ sql += ' AND ' + fromsql
157
+ end
158
+ end
159
+ unless @ToTime.nil?
160
+ tosql = '((O.`From` IS NULL AND O.`To` >= ?) OR (O.`To` IS NULL AND O.`From` < ?) OR (O.`From` < ? AND O.`To` >= ?) OR (O.`From` IS NULL AND O.`To` IS NULL))'
161
+ params += Array.new(4, @ToTime.to_s)
162
+ if useMetazonePeriodFilter
163
+ tosql = '(' + tosql + ' AND ((MP.`From` IS NULL AND MP.`To` >= ?) OR (MP.`To` IS NULL AND MP.`From` < ?) OR (MP.`From` < ? AND MP.`To` >= ?) OR (MP.`From` IS NULL AND MP.`To` IS NULL)))'
164
+ params += Array.new(4, @ToTime.to_s)
165
+ end
166
+ if not @FromTime.nil?
167
+ sql += ' AND ((' + fromsql + ') OR (' + tosql + '))'
168
+ else
169
+ sql += ' AND ' + tosql
170
+ end
171
+ end
172
+ if not @Regions.nil? and not @Regions.empty?
173
+ sql += ' AND Territories.Territory IN (' + Array.new(@Regions.count, '?').join(',') + ')'
174
+ params += @Regions
175
+ end
176
+ sql += ' ORDER BY ' + column
177
+ if dataType == :Offsets
178
+ result = Set.new
179
+ timezonesTypes = []
180
+ Data::Storage.getStatement(sql).execute(*params).each do |row|
181
+ if row.first.nil?
182
+ timezonesTypes << [row[1], row[2]]
183
+ else
184
+ result << row.first
185
+ end
186
+ end
187
+
188
+ result += self.class.findOffsetsFromTimezonesTypes(timezonesTypes, @ToTime, @FromTime, types) if result.empty?
189
+
190
+ result = result.sort
191
+ else
192
+ result = Data::Storage.getStatement(sql).execute(*params).collect { |row| row.first }
193
+ if dataType == :Types
194
+ result = self.class.convertTypes(result)
195
+ end
196
+ end
197
+ result
198
+ end
199
+
129
200
  end
130
201
  end