swissmatch-location 0.0.1

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.
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ require 'swissmatch/loaderror'
6
+
7
+
8
+
9
+ module SwissMatch
10
+
11
+ # Used to indicate an error while loading the swissmatch data.
12
+ class LoadError < StandardError
13
+
14
+ # Data associated with the error
15
+ attr_reader :data
16
+
17
+ # @param [String] message
18
+ # Same as Exception#initialize, the message of the exception
19
+ # @param [Object] data
20
+ # Arbitrary data
21
+ def initialize(message, data)
22
+ super(message)
23
+ @data = data
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ # Require this file to automatically load swissmatch location data
4
+ # It will try to load from a try the directory in SWISSMATCH_DATA
5
+ # If the env variable SWISSMATCH_DATA is not set, it'll try the data dir in the gem.
6
+
7
+ require 'swissmatch/location'
8
+ SwissMatch.load
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ # This file provides a couple of ruby monkey patches.
3
+
4
+ module Enumerable
5
+ unless method_defined?(:last) then
6
+
7
+ # @example
8
+ # ary.last -> obj or nil
9
+ # ary.last(n) -> new_ary
10
+ #
11
+ # @return
12
+ # The last element(s) of self. If the enumerable is empty, the first form returns
13
+ # nil, the second an empty Array.
14
+ # The method is optimized to make use of reverse_each if present.
15
+ def last(n=nil)
16
+ reverse_each_method = method(:reverse_each)
17
+ has_reverse_each = reverse_each_method && reverse_each_method.owner != Enumerable # native reverse_each needed
18
+ if n then
19
+ return_value = []
20
+ if has_reverse_each then
21
+ reverse_each { |val|
22
+ return_value.unshift(val)
23
+ return return_value if return_value.size == n
24
+ }
25
+ else
26
+ each { |val|
27
+ return_value.push(val)
28
+ return_value.shift if return_value.size > n
29
+ }
30
+ end
31
+ else
32
+ if has_reverse_each then
33
+ reverse_each { |value| return value }
34
+ else
35
+ return_value = nil
36
+ each { |value| return_value = value }
37
+ end
38
+ end
39
+
40
+ return_value
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'rubygems/version' # newer rubygems use this
5
+ rescue LoadError
6
+ require 'gem/version' # older rubygems use this
7
+ end
8
+
9
+ module SwissMatch
10
+ module Location
11
+
12
+ # The version of the swissmatch-location gem.
13
+ Version = Gem::Version.new("0.0.1")
14
+ end
15
+ end
@@ -0,0 +1,249 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ require 'date'
6
+ require 'swissmatch/canton'
7
+ require 'swissmatch/cantons'
8
+ require 'swissmatch/communities'
9
+ require 'swissmatch/community'
10
+ require 'swissmatch/datafiles'
11
+ require 'swissmatch/location/ruby'
12
+ require 'swissmatch/location/version'
13
+ require 'swissmatch/zipcode'
14
+ require 'swissmatch/zipcodes'
15
+
16
+
17
+
18
+ # From SwissMatch::Location
19
+ # Deal with swiss zip codes, cities, communities and cantons.
20
+ #
21
+ # @note
22
+ # All strings passed to SwissMatch are expected to be utf-8. All strings
23
+ # returned by SwissMatch are also in utf-8.
24
+ #
25
+ # @example Load the data
26
+ # require 'swissmatch'
27
+ # SwissMatch.load
28
+ # # alternatively, just require 'swissmatch/location/autoload'
29
+ #
30
+ # @example Get the ONRP for a given zip-code + city
31
+ # require 'swissmatch/location/autoload'
32
+ # SwissMatch.zip_code(8000, 'Zürich').ordering_number # => 4384
33
+ # SwissMatch.zip_code(4384).name # => "Zürich"(de, 0)
34
+ module SwissMatch
35
+
36
+ # This module only contains the version of the swissmatch-location gem
37
+ module Location
38
+ end
39
+
40
+ @data = nil
41
+ class <<self
42
+ # @return [SwissMatch::DataFiles, nil] The data source used
43
+ attr_reader :data
44
+ end
45
+
46
+ # @param [String] name_or_plate
47
+ # The name or license_tag of the canton
48
+ #
49
+ # @return [SwissMatch::Canton]
50
+ # The canton with the given name or license_tag
51
+ def self.canton(name_or_plate)
52
+ @data.cantons[name_or_plate]
53
+ end
54
+
55
+ # @return [SwissMatch::Cantons]
56
+ # All known cantons
57
+ def self.cantons
58
+ @data.cantons
59
+ end
60
+
61
+ # @param [Integer] key
62
+ # The community number of the community
63
+ #
64
+ # @return [SwissMatch::Community]
65
+ # The community with the community number
66
+ def self.community(key)
67
+ @data.communities.by_community_number(key)
68
+ end
69
+
70
+ # @param [String] name
71
+ # The name of the communities
72
+ #
73
+ # @return [SwissMatch::Communities]
74
+ # All communities, or those matching the given name
75
+ def self.communities(name=nil)
76
+ name ? @data.communities.by_name(name) : @data.communities
77
+ end
78
+
79
+ # @param [String, Integer] code_or_name
80
+ # Either the 4 digit zip code as Integer or String, or the city name as a String in
81
+ # utf-8.
82
+ #
83
+ # @return [Array<SwissMatch::ZipCode>]
84
+ # A list of zip codes with the given code or name.
85
+ def self.zip_codes(code_or_name=nil)
86
+ case code_or_name
87
+ when Integer, /\A\d{4}\z/
88
+ @data.zip_codes.by_code(code_or_name.to_i)
89
+ when String
90
+ @data.zip_codes.by_name(code_or_name)
91
+ when nil
92
+ @data.zip_codes
93
+ else
94
+ raise ArgumentError, "Invalid argument, must be a ZipCode#code (Integer or String) or ZipCode#name (String)"
95
+ end
96
+ end
97
+
98
+ # Returns a single zip code. A zip code can be uniquely identified by any of:
99
+ # * Its ordering_number (ONRP, a 4 digit Integer)
100
+ # * Its zip code (4 digit Integer) and add-on (2 digit Integer)
101
+ # * Its zip code (4 digit Integer) and any official name (String)
102
+ # The data can be passed in different ways, e.g. all numbers can be passed either
103
+ # as a String or as an Integer. The identification by zip code and add-on can be done
104
+ # by either using a combined 6 digit number (e.g. 800000 for "8000 Zürich"), or by
105
+ # passing 2 arguments, passing the zip code and the add-on separately.
106
+ #
107
+ # === IMPORTANT
108
+ # You must be aware, that passing a single 4-digit code to SwissMatch::zip_code uses
109
+ # the ONRP, and NOT the zip-code. The 4 digit zip code alone does NOT uniquely identify
110
+ # a zip code.
111
+ #
112
+ #
113
+ # @example Get a zip code by ONRP
114
+ # SwissMatch.zip_code(4384) # => #<SwissMatch::ZipCode:003ff996cf8d3c 8000 Zürich>
115
+ #
116
+ # @example Get a zip code by 4-digit code and add-on
117
+ # SwissMatch.zip_code(8000, 0) # => #<SwissMatch::ZipCode:003ff996cf8d3c 8000 Zürich>
118
+ # SwissMatch.zip_code("8000", "00") # => #<SwissMatch::ZipCode:003ff996cf8d3c 8000 Zürich>
119
+ # SwissMatch.zip_code(800000) # => #<SwissMatch::ZipCode:003ff996cf8d3c 8000 Zürich>
120
+ # SwissMatch.zip_code("800000") # => #<SwissMatch::ZipCode:003ff996cf8d3c 8000 Zürich>
121
+ #
122
+ # @example Get a zip code by 4-digit code and name
123
+ # SwissMatch.zip_code(8000, "Zürich") # => #<SwissMatch::ZipCode:003ff996cf8d3c 8000 Zürich>
124
+ # SwissMatch.zip_code(8000, "Zurigo") # => #<SwissMatch::ZipCode:003ff996cf8d3c 8000 Zürich>
125
+ #
126
+ #
127
+ # @param [String, Integer] code
128
+ # The 4 digit zip code as Integer or String
129
+ # @param [String, Integer] city_or_add_on
130
+ # Either the 2 digit zip-code add-on as string or integer, or the city name as a
131
+ # String in utf-8.
132
+ #
133
+ # @return [SwissMatch::ZipCode]
134
+ # The zip codes with the given code and the given add-on or name.
135
+ def self.zip_code(code, city_or_add_on=nil)
136
+ case city_or_add_on
137
+ when nil
138
+ @data.zip_codes.by_ordering_number(code.to_i)
139
+ when Integer, /\A\d\d\z/
140
+ @data.zip_codes.by_code_and_add_on(code.to_i, city_or_add_on.to_i)
141
+ when String
142
+ @data.zip_codes.by_code_and_name(code.to_i, city_or_add_on)
143
+ else
144
+ raise ArgumentError, "Invalid second argument, must be nil, ZipCode#add_on or ZipCode#name"
145
+ end
146
+ end
147
+
148
+ # @param [String] name
149
+ # The name for which to return matching zip codes
150
+ #
151
+ # @return [Array<SwissMatch::ZipCode>]
152
+ # Zip codes whose name equals the given name
153
+ def self.city(name)
154
+ @data.zip_codes.by_name(name)
155
+ end
156
+
157
+ # @param [String, Integer] code
158
+ # The 4 digit zip code
159
+ # @param [nil, Array<Integer>] only_types
160
+ # An array of zip code types (see ZipCode#type) which the returned zip codes must match.
161
+ # @param [nil, Symbol] locale
162
+ # Return the names in the given locale, defaults to nil/:native (nil and :native are
163
+ # treated the same and will return the native names)
164
+ #
165
+ # @return [Array<String>]
166
+ # A list of unique names matching the parameters (4 digit code, type, locale).
167
+ def self.cities_for_zip_code(code, only_types=nil, locale=nil)
168
+ codes = @data.zip_codes.by_code(code.to_i)
169
+ return [] unless codes
170
+ codes = codes.select { |code| only_types.include?(code.type) } if only_types
171
+ names = case locale
172
+ when :native,nil then codes.map(&:name)
173
+ when :de then codes.map(&:name_de)
174
+ when :fr then codes.map(&:name_fr)
175
+ when :it then codes.map(&:name_it)
176
+ when :rt then codes.map(&:name_rt)
177
+ else raise ArgumentError, "Invalid locale #{locale}"
178
+ end
179
+
180
+ names.uniq
181
+ end
182
+
183
+ # Loads the swissmatch data
184
+ #
185
+ # @param [DataFiles] data_source
186
+ # A valid data-source.
187
+ #
188
+ # @return [self]
189
+ # Returns self
190
+ def self.load(data_source=nil)
191
+ @data = data_source || DataFiles.new
192
+ @data.load!
193
+
194
+ self
195
+ end
196
+
197
+ # @private
198
+ # Used to transliterate city names
199
+ Transliteration1 = {
200
+ "à" => "a",
201
+ "â" => "a",
202
+ "ä" => "a",
203
+ "è" => "e",
204
+ "é" => "e",
205
+ "ê" => "e",
206
+ "ë" => "e",
207
+ "ì" => "i",
208
+ "î" => "i",
209
+ "ï" => "i",
210
+ "ô" => "o",
211
+ "ö" => "o",
212
+ "ù" => "u",
213
+ "ü" => "u",
214
+ }
215
+
216
+ # @private
217
+ # Used to transliterate city names
218
+ Transliteration2 = Transliteration1.merge({
219
+ "ä" => "ae",
220
+ "ö" => "oe",
221
+ "ü" => "ue",
222
+ })
223
+
224
+ # @private
225
+ # Used to transliterate city names
226
+ TransMatch1 = /#{Transliteration1.keys.map { |k| Regexp.escape(k) }.join("|")}/
227
+
228
+ # @private
229
+ # Used to transliterate city names
230
+ TransMatch2 = /#{Transliteration2.keys.map { |k| Regexp.escape(k) }.join("|")}/
231
+
232
+ # @private
233
+ # Used to transliterate city names
234
+ def self.transliterate1(word)
235
+ word.gsub(TransMatch1, Transliteration1).delete("^ A-Za-z").downcase
236
+ end
237
+
238
+ # @private
239
+ # Used to transliterate city names
240
+ def self.transliterate2(word)
241
+ word.gsub(TransMatch2, Transliteration2).delete("^ A-Za-z").downcase
242
+ end
243
+
244
+ # @private
245
+ # Transliterates a string into the unique transliterated (1 & 2) word list
246
+ def self.transliterated_words(string)
247
+ "#{transliterate1(string)} #{transliterate2(string)}".split(" ").uniq
248
+ end
249
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ module SwissMatch
6
+
7
+ # Adds a couple of properties to the String class.
8
+ # These properties are relevant to the naming of Cantons, Communities and
9
+ # ZipCodes. They provide information about the language in which the name is,
10
+ # and which sequence number that name has.
11
+ class Name < ::String
12
+
13
+ # @return [Integer] The sequence number of this name
14
+ attr_reader :sequence_number
15
+
16
+ # @return [Symbol] The language of this name (:de, :fr, :it or :rt)
17
+ attr_reader :language
18
+
19
+ # @param [String] name
20
+ # The name (self)
21
+ # @param [Symbol] language
22
+ # The language this name is in (:de, :fr, :it or :rt)
23
+ # @param [Integer] sequence_number
24
+ # The sequence number of this name
25
+ def initialize(name, language, sequence_number=0)
26
+ @language = language
27
+ @sequence_number = sequence_number
28
+ super(name.to_s)
29
+ end
30
+
31
+ # @return [Hash]
32
+ # All properties of the name as a hash.
33
+ def to_hash
34
+ {
35
+ :name => to_s,
36
+ :language => @language,
37
+ :sequence_number => @sequence_number,
38
+ }
39
+ end
40
+
41
+ # @private
42
+ # @see Object#inspect
43
+ def inspect
44
+ "#{super}(#{@language}, #{@sequence_number})"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ # As it seems, some zip files delivered by the post are corrupt as per rubyzips standard.
2
+ # This file contains a patch to handle the corruption.
3
+ # As it seems, the zipfiles don't report the "\n" in the zipfile-comment
4
+
5
+ begin
6
+ require 'zip/zip'
7
+ rescue LoadError
8
+ raise "To update the swissmatch datafiles, the rubyzip gem is required, `gem install rubyzip` or add it to your Gemfile."
9
+ end
10
+
11
+ # @private
12
+ # Patching the rubyzip gem
13
+ module Zip
14
+
15
+ # @private
16
+ # Patching the rubyzip gem
17
+ class ZipCentralDirectory
18
+
19
+ # @private
20
+ # Patching the rubyzip gem
21
+ def read_e_o_c_d(io) #:nodoc:
22
+ buf = get_e_o_c_d(io)
23
+ @numberOfThisDisk = ZipEntry::read_zip_short(buf)
24
+ @numberOfDiskWithStartOfCDir = ZipEntry::read_zip_short(buf)
25
+ @totalNumberOfEntriesInCDirOnThisDisk = ZipEntry::read_zip_short(buf)
26
+ @size = ZipEntry::read_zip_short(buf)
27
+ @sizeInBytes = ZipEntry::read_zip_long(buf)
28
+ @cdirOffset = ZipEntry::read_zip_long(buf)
29
+ commentLength = ZipEntry::read_zip_short(buf)
30
+ @comment = buf.read(commentLength)
31
+
32
+ # ORIGINAL
33
+ # raise ZipError, "Zip consistency problem while reading eocd structure" unless buf.size == 0
34
+
35
+ # PATCH, doing it in a similar fashion as Archive::Zip in perl does
36
+ raise ZipError, "Zip consistency problem while reading eocd structure" if @comment.bytesize != commentLength
37
+ # /PATCH
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,303 @@
1
+ # encoding: utf-8
2
+
3
+
4
+
5
+ require 'swissmatch/name'
6
+
7
+
8
+
9
+ module SwissMatch
10
+
11
+ # Represents an area, commonly identified by zip-code and city-name.
12
+ # A unique zip code is determined by any of these:
13
+ # * the postal ordering number
14
+ # * zip code + zip code add on
15
+ # * zip code + name (city)
16
+ class ZipCode
17
+
18
+ # @return [Integer]
19
+ # The postal ordering number, also known as ONRP
20
+ attr_reader :ordering_number # onrp
21
+
22
+ # Described under "PLZ light", as field "PLZ-Typ"
23
+ # * 10 = Domizil- und Fachadressen
24
+ # * 20 = Nur Domiziladressen
25
+ # * 30 = Nur Fach-PLZ
26
+ # * 40 = Firmen-PLZ
27
+ # * 80 = Postinterne PLZ (Angabe Zustellpoststelle auf Bundzetteln oder auf Sackanschriften)
28
+ #
29
+ # @return [Integer]
30
+ # The type of the zip code in a numeric code, one of the values 10, 20, 30, 40 or 80.
31
+ attr_reader :type
32
+
33
+ # Described under "PLZ light", as field "Postleitzahl"
34
+ #
35
+ # @return [Integer]
36
+ # The 4 digit numeric zip code
37
+ attr_reader :code
38
+
39
+ # @return [Integer]
40
+ # The 2 digit numeric code addition, to distinguish zip codes with the same 4 digit code.
41
+ attr_reader :add_on
42
+
43
+ # @return [Integer]
44
+ # The 6 digit numeric zip code and add-on (first 4 digits are the code, last 2
45
+ # digits the add-on).
46
+ attr_reader :full_code
47
+
48
+ # @return [SwissMatch::Canton]
49
+ # The canton this zip code belongs to
50
+ attr_reader :canton
51
+
52
+ # @return [SwissMatch::Name]
53
+ # The official name of this zip code (max. 27 characters)
54
+ attr_reader :name
55
+
56
+ # @return [SwissMatch::Name]
57
+ # The official name of this zip code (max. 18 characters)
58
+ attr_reader :name_short
59
+
60
+ # @return [Symbol]
61
+ # The main language in the area of this zip code. One of :de, :fr, :it or :rt.
62
+ attr_reader :language
63
+
64
+ # @return [SwissMatch::Canton]
65
+ # The second most used language in the area of this zip code. One of :de, :fr, :it or :rt.
66
+ attr_reader :language_alternative
67
+
68
+ # @return [Boolean]
69
+ # Whether this ZipCode instance is included in the MAT[CH]sort sortfile
70
+ attr_reader :sortfile_member
71
+
72
+ # @return [SwissMatch::ZipCode]
73
+ # By which postal office delivery of letters is usually taken care of.
74
+ attr_reader :delivery_by
75
+
76
+ # @return [SwissMatch::Community]
77
+ # The community this zip code belongs to.
78
+ attr_reader :community
79
+
80
+ # @return [Date, nil]
81
+ # The date from which on this zip code starts to be in use
82
+ #
83
+ # @see #in_use?
84
+ attr_reader :valid_from
85
+
86
+ # @return [Date, nil]
87
+ # The date until which on this zip code is in use
88
+ #
89
+ # @see #in_use?
90
+ attr_reader :valid_until
91
+
92
+ def initialize(
93
+ ordering_number,
94
+ type,
95
+ code,
96
+ add_on,
97
+ name,
98
+ names,
99
+ name_short,
100
+ names_short,
101
+ region_names,
102
+ region_names_short,
103
+ canton,
104
+ language,
105
+ language_alternative,
106
+ sortfile_member,
107
+ delivery_by,
108
+ community,
109
+ valid_from,
110
+ valid_until = nil
111
+ )
112
+ @ordering_number = ordering_number
113
+ @type = type
114
+ @code = code
115
+ @add_on = add_on
116
+ @full_code = code*100 + add_on
117
+ @language = language
118
+ @language_alternative = language_alternative
119
+ @name = name.is_a?(Name) ? name : Name.new(name, language)
120
+ @name_short = name_short.is_a?(Name) ? name_short : Name.new(name_short, language)
121
+ @names = (names || [@name]).sort_by(&:sequence_number)
122
+ @names_short = (names_short || [@name_short]).sort_by(&:sequence_number)
123
+ @region_names = region_names
124
+ @region_names_short = region_names_short
125
+ @canton = canton
126
+ @sortfile_member = sortfile_member
127
+ @delivery_by = delivery_by == :self ? self : delivery_by
128
+ @community = community
129
+ @valid_from = valid_from
130
+ @valid_until = valid_until
131
+ end
132
+
133
+ # @return [Array<String>]
134
+ # The name of this zip code in all languages and normalizations (only unique values)
135
+ def transliterated_names
136
+ names.flat_map { |name, ary|
137
+ name = name.to_s # convert from SwissMatch::Name
138
+ [
139
+ SwissMatch.transliterate1(name),
140
+ SwissMatch.transliterate2(name) # TODO: use transliterate gem
141
+ ]
142
+ }.uniq
143
+ end
144
+
145
+ # Since a zip code can - for any given language - have no name, exactly one name,
146
+ # or even multiple names, it is sometimes difficult to write good code to
147
+ # automatically provide well localized addresses. This method helps with that, in that
148
+ # it guarantees a single name, as well chosen as possible.
149
+ # It returns the name for the given language, and with the lowest running number, if
150
+ # no name can be found for the given language, the primary name (@see #name) is
151
+ # returned.
152
+ #
153
+ # @param [Symbol, nil] language
154
+ # One of nil, :de, :fr, :it or :rt
155
+ #
156
+ # @return [SwissMatch::Name]
157
+ # A single name for the zip code, chosen by a 'best fit' algorithm.
158
+ def suggested_name(language=nil)
159
+ (language && @names.find { |name| name.language == language }) || @name
160
+ end
161
+
162
+
163
+ # Since a zip code can - for any given language - have no name, exactly one name,
164
+ # or even multiple names, it is sometimes difficult to write good code to
165
+ # automatically provide well localized addresses. This method helps with that, in that
166
+ # it guarantees a single name, as well chosen as possible.
167
+ # It returns the name for the given language, and with the lowest running number, if
168
+ # no name can be found for the given language, the primary name (@see #name) is
169
+ # returned.
170
+ #
171
+ # @param [Symbol, nil] language
172
+ # One of nil, :de, :fr, :it or :rt
173
+ #
174
+ # @return [SwissMatch::Name]
175
+ # A single short name for the zip code, chosen by a 'best fit' algorithm.
176
+ def suggested_short_name(language=nil)
177
+ (language && @short_name.find { |name| name.language == language }) || @short_name
178
+ end
179
+
180
+ # @param [Symbol, nil] language
181
+ # One of nil, :de, :fr, :it or :rt
182
+ #
183
+ # @return [Array<SwissMatch::Name>]
184
+ # All official names (max. 27 chars) of this zip code.
185
+ def names(language=nil)
186
+ language ? @names.select { |name| name.language == language } : @names
187
+ end
188
+
189
+ # @param [Symbol, nil] language
190
+ # One of nil, :de, :fr, :it or :rt
191
+ #
192
+ # @return [Array<SwissMatch::Name>]
193
+ # All official short names (max. 18 chars) of this zip code.
194
+ def names_short(language=nil)
195
+ language ? @names_short.select { |name| name.language == language } : @names_short
196
+ end
197
+
198
+ # A region name is a name that can be used along a zip code and city, but must not replace
199
+ # the city. For more information, read the section about the PLZ_P2 file, "Bezeichnungstyp"
200
+ # with value "3".
201
+ #
202
+ # @param [Symbol, nil] language
203
+ # One of nil, :de, :fr, :it or :rt
204
+ #
205
+ # @return [Array<SwissMatch::Name>]
206
+ # All official region names (max. 27 chars) of this zip code.
207
+ def region_names(language=nil)
208
+ language ? @region_names.select { |name| name.language == language } : @region_names
209
+ end
210
+
211
+ # A region name is a name that can be used along a zip code and city, but must not replace
212
+ # the city. For more information, read the section about the PLZ_P2 file, "Bezeichnungstyp"
213
+ # with value "3".
214
+ #
215
+ # @param [Symbol, nil] language
216
+ # One of nil, :de, :fr, :it or :rt
217
+ #
218
+ # @return [Array<SwissMatch::Name>]
219
+ # All official short region names (max. 18 chars) of this zip code.
220
+ def region_names_short(language=nil)
221
+ language ? @region_names_short.select { |name| name.language == language } : @region_names_short
222
+ end
223
+
224
+ # Compare two zip codes by their ordering number (ONRP)
225
+ #
226
+ # @return [Integer]
227
+ # Returns -1, 0 or 1.
228
+ def <=>(other)
229
+ @ordering_number <=> other.ordering_number
230
+ end
231
+
232
+ # @param [Date] at
233
+ # The date for which to check the
234
+ #
235
+ # @return [Boolean]
236
+ # Whether the zip code is in active use at the given date.
237
+ def in_use?(at=Date.today)
238
+ if @valid_from then
239
+ if @valid_until then
240
+ at.between?(@valid_from, @valid_until)
241
+ else
242
+ at >= @valid_from
243
+ end
244
+ elsif @valid_until
245
+ at <= @valid_until
246
+ else
247
+ true
248
+ end
249
+ end
250
+
251
+ # @param [Boolean] retain_references
252
+ # If set to false, :delivery_by will be set to the ordering number,
253
+ # :community to the community_number and :canton to the canton's license_tag.
254
+ #
255
+ # @return [Hash]
256
+ # All properties of the zip code as a hash.
257
+ def to_hash(retain_references=false)
258
+ delivery_by = retain_references ? @delivery_by : (@delivery_by && @delivery_by.ordering_number)
259
+ community = retain_references ? @community : (@community && @community.community_number)
260
+ canton = retain_references ? @canton : (@canton && @canton.license_tag)
261
+ {
262
+ :ordering_number => @ordering_number,
263
+ :type => @type,
264
+ :code => @code,
265
+ :add_on => @add_on,
266
+ :name => @name,
267
+ :name_short => @name_short,
268
+ :canton => canton,
269
+ :language => @language,
270
+ :language_alternative => @language_alternative,
271
+ :sortfile_member => @sortfile_member,
272
+ :delivery_by => delivery_by,
273
+ :community => community,
274
+ :valid_from => @valid_from,
275
+ :valid_until => @valid_until,
276
+ }
277
+ end
278
+
279
+ # @private
280
+ # @see Object#hash
281
+ def hash
282
+ [self.class, @ordering_number].hash
283
+ end
284
+
285
+ # @private
286
+ # @see Object#eql?
287
+ def eql?(other)
288
+ self.class == other.class && @ordering_number == other.ordering_number
289
+ end
290
+
291
+ # @return [String]
292
+ # The 4 digit code, followed by the name
293
+ def to_s
294
+ "#{@code} #{@name}"
295
+ end
296
+
297
+ # @return [String]
298
+ # @see Object#inspect
299
+ def inspect
300
+ sprintf "\#<%s:%014x %s>", self.class, object_id, self
301
+ end
302
+ end
303
+ end