telephone_number 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ module TelephoneNumber
2
+ class TimeZoneDataImporter
3
+ def self.load_data!
4
+ master_data = {}
5
+ File.open('data/timezones/map_data.txt', 'rb').each do |row|
6
+ number_prefix, timezone = row.split('|').map(&:strip)
7
+ master_data[number_prefix] = timezone
8
+ end
9
+
10
+ File.open('data/timezones/map_data.dat', 'wb') { |file| file << Marshal.dump(master_data) }
11
+ end
12
+ end
13
+ end
@@ -8,13 +8,15 @@ module TelephoneNumber
8
8
  autoload :Country, 'telephone_number/country'
9
9
  autoload :Formatter, 'telephone_number/formatter'
10
10
  autoload :GeoLocator, 'telephone_number/geo_locator'
11
+ autoload :GeoLocationDataImporter, 'importers/geo_location_data_importer'
11
12
  autoload :Number, 'telephone_number/number'
12
13
  autoload :NumberFormat, 'telephone_number/number_format'
13
14
  autoload :NumberValidation, 'telephone_number/number_validation'
14
15
  autoload :Parser, 'telephone_number/parser'
15
- autoload :GeoLocationDataImporter, 'importers/geo_location_data_importer'
16
16
  autoload :PhoneDataImporter, 'importers/phone_data_importer'
17
17
  autoload :TestDataImporter, 'importers/test_data_importer'
18
+ autoload :TimeZoneDataImporter, 'importers/time_zone_data_importer'
19
+ autoload :TimeZoneDetector, 'telephone_number/time_zone_detector'
18
20
 
19
21
  extend ClassMethods
20
22
  end
@@ -1,26 +1,25 @@
1
1
  module TelephoneNumber
2
2
  class Country
3
- attr_reader :country_code, :national_prefix, :national_prefix_formatting_rule,
4
- :national_prefix_for_parsing, :national_prefix_transform_rule, :international_prefix,
5
- :formats, :validations, :mobile_token, :country_id, :general_validation, :main_country_for_code
3
+ attr_reader :country_code, :national_prefix, :national_prefix_for_parsing,
4
+ :national_prefix_transform_rule, :international_prefix, :formats,
5
+ :validations, :mobile_token, :country_id, :general_validation, :main_country_for_code
6
6
 
7
7
  MOBILE_TOKEN_COUNTRIES = { AR: '9' }.freeze
8
8
 
9
9
  def initialize(data_hash)
10
10
  @country_code = data_hash[:country_code]
11
11
  @country_id = data_hash[:id]
12
- @formats = data_hash.fetch(:formats, []).map { |format| NumberFormat.new(format) }
13
12
  @general_validation = NumberValidation.new(:general_desc, data_hash[:validations][:general_desc]) if data_hash.fetch(:validations, {})[:general_desc]
14
13
  @international_prefix = Regexp.new(data_hash[:international_prefix]) if data_hash[:international_prefix]
15
14
  @main_country_for_code = data_hash[:main_country_for_code] == 'true'
16
15
  @mobile_token = MOBILE_TOKEN_COUNTRIES[@country_id.to_sym]
17
16
  @national_prefix = data_hash[:national_prefix]
18
- @national_prefix_formatting_rule = data_hash[:national_prefix_formatting_rule]
19
17
  @national_prefix_for_parsing = Regexp.new(data_hash[:national_prefix_for_parsing]) if data_hash[:national_prefix_for_parsing]
20
18
  @national_prefix_transform_rule = data_hash[:national_prefix_transform_rule]
21
19
  @validations = data_hash.fetch(:validations, {})
22
20
  .except(:general_desc, :area_code_optional)
23
21
  .map { |name, data| NumberValidation.new(name, data) }
22
+ @formats = data_hash.fetch(:formats, []).map { |format| NumberFormat.new(format, data_hash[:national_prefix_formatting_rule]) }
24
23
  end
25
24
 
26
25
  def detect_format(number)
@@ -35,13 +35,12 @@ module TelephoneNumber
35
35
 
36
36
  def build_national_number(formatted: true)
37
37
  captures = normalized_number.match(number_format.pattern).captures
38
- national_prefix_formatting_rule = number_format.national_prefix_formatting_rule || country.national_prefix_formatting_rule
39
38
 
40
39
  formatted_string = format(ruby_format_string(number_format.format), *captures)
41
40
  captures.delete(country.mobile_token)
42
41
 
43
- if national_prefix_formatting_rule
44
- national_prefix_string = national_prefix_formatting_rule.dup
42
+ if number_format.national_prefix_formatting_rule
43
+ national_prefix_string = number_format.national_prefix_formatting_rule.dup
45
44
  national_prefix_string.gsub!(/\$NP/, country.national_prefix)
46
45
  national_prefix_string.gsub!(/\$FG/, captures[0])
47
46
  formatted_string.sub!(captures[0], national_prefix_string)
@@ -1,6 +1,6 @@
1
1
  module TelephoneNumber
2
2
  class GeoLocator
3
- attr_accessor :phone_number, :normalized_number, :location, :locale
3
+ attr_reader :phone_number, :normalized_number, :location, :locale
4
4
 
5
5
  # initialize with a phone_number object
6
6
  def initialize(phone_number, locale)
@@ -10,7 +10,6 @@ module TelephoneNumber
10
10
  end
11
11
 
12
12
  def location
13
- return unless phone_number.valid?
14
13
  @location ||= find_location
15
14
  end
16
15
 
@@ -2,7 +2,7 @@ module TelephoneNumber
2
2
  class Number
3
3
  extend Forwardable
4
4
 
5
- attr_reader :country, :parser, :formatter, :original_number, :geo_locator
5
+ attr_reader :country, :parser, :formatter, :original_number, :geo_locator, :time_zone_detector
6
6
 
7
7
  delegate [:valid?, :valid_types, :normalized_number] => :parser
8
8
  delegate [:national_number, :e164_number, :international_number] => :formatter
@@ -15,21 +15,29 @@ module TelephoneNumber
15
15
  end
16
16
 
17
17
  def location(locale = :en)
18
+ return if !country || !valid?
18
19
  @geo_locator ||= GeoLocator.new(self, locale)
19
20
  @geo_locator.location
20
21
  end
21
22
 
23
+ def timezone
24
+ return if !country || !valid?
25
+ @time_zone_detector ||= TimeZoneDetector.new(self)
26
+ @time_zone_detector.detect_timezone
27
+ end
28
+
22
29
  private
23
30
 
24
- def detect_country
31
+ def eligible_countries
25
32
  # note that it is entirely possible for two separate countries to use the same
26
33
  # validation scheme. Take Italy and Vatican City for example.
27
- eligible_countries = Country.all_countries.select do |country|
34
+ Country.all_countries.select do |country|
28
35
  original_number.start_with?(country.country_code) && self.class.new(original_number, country.country_id).valid?
29
36
  end
37
+ end
30
38
 
31
- detected_country = eligible_countries.detect(&:main_country_for_code) || eligible_countries.first
32
- Country.find(detected_country.country_id.to_sym) if detected_country
39
+ def detect_country
40
+ eligible_countries.detect(&:main_country_for_code) || eligible_countries.first
33
41
  end
34
42
  end
35
43
  end
@@ -3,12 +3,12 @@ module TelephoneNumber
3
3
 
4
4
  attr_reader :pattern, :leading_digits, :format, :national_prefix_formatting_rule, :intl_format
5
5
 
6
- def initialize(data_hash)
6
+ def initialize(data_hash, country_prefix_formatting_rule)
7
7
  @pattern = Regexp.new(data_hash[:pattern]) if data_hash[:pattern]
8
8
  @leading_digits = Regexp.new(data_hash[:leading_digits]) if data_hash[:leading_digits]
9
9
  @format = data_hash[:format]
10
10
  @intl_format = data_hash[:intl_format]
11
- @national_prefix_formatting_rule = data_hash[:national_prefix_formatting_rule]
11
+ @national_prefix_formatting_rule = data_hash[:national_prefix_formatting_rule] || country_prefix_formatting_rule
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,35 @@
1
+ module TelephoneNumber
2
+ class TimeZoneDetector
3
+ attr_reader :phone_number, :timezone
4
+
5
+ def initialize(phone_number)
6
+ @phone_number = phone_number
7
+ end
8
+
9
+ def detect_timezone
10
+ normalized_number = build_normalized_number.dup
11
+ timezone = nil
12
+ (normalized_number.length - 2).times { break if timezone = data[normalized_number.chop!] }
13
+ timezone.to_s.split('&').join(', ')
14
+ end
15
+
16
+ def data
17
+ @data ||= Marshal.load(File.binread(File.expand_path('../../../data/timezones/map_data.dat', __FILE__)))
18
+ end
19
+
20
+ private
21
+
22
+ # Google's geocoding data is odd in that it uses a non-standard format for lookups
23
+ # on countries that have a mobile token. While I don't believe that this is used right now
24
+ # it will be if/when Google adds more specific data for Argentina. This method safe guards
25
+ # against that.
26
+ def build_normalized_number
27
+ return phone_number.e164_number(formatted: false) unless mobile_token = phone_number.country.mobile_token
28
+ if phone_number.parser.normalized_number.start_with?(mobile_token)
29
+ phone_number.e164_number(formatted: false).sub(mobile_token, '')
30
+ else
31
+ phone_number.e164_number(formatted: false)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,3 @@
1
1
  module TelephoneNumber
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: telephone_number
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - MOBI Wireless Management
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-10-21 00:00:00.000000000 Z
11
+ date: 2017-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -373,6 +373,8 @@ files:
373
373
  - data/geocoding/en/592.txt
374
374
  - data/geocoding/en/599.dat
375
375
  - data/geocoding/en/599.txt
376
+ - data/geocoding/en/61.dat
377
+ - data/geocoding/en/61.txt
376
378
  - data/geocoding/en/62.dat
377
379
  - data/geocoding/en/62.txt
378
380
  - data/geocoding/en/64.dat
@@ -581,10 +583,13 @@ files:
581
583
  - data/geocoding/zh_Hant/886.txt
582
584
  - data/telephone_number_data_file.dat
583
585
  - data/telephone_number_data_file.xml
586
+ - data/timezones/map_data.dat
587
+ - data/timezones/map_data.txt
584
588
  - lib/active_model/telephone_number_validator.rb
585
589
  - lib/importers/geo_location_data_importer.rb
586
590
  - lib/importers/phone_data_importer.rb
587
591
  - lib/importers/test_data_importer.rb
592
+ - lib/importers/time_zone_data_importer.rb
588
593
  - lib/telephone_number.rb
589
594
  - lib/telephone_number/class_methods.rb
590
595
  - lib/telephone_number/country.rb
@@ -594,6 +599,7 @@ files:
594
599
  - lib/telephone_number/number_format.rb
595
600
  - lib/telephone_number/number_validation.rb
596
601
  - lib/telephone_number/parser.rb
602
+ - lib/telephone_number/time_zone_detector.rb
597
603
  - lib/telephone_number/version.rb
598
604
  - lib/utilities/hash.rb
599
605
  - telephone_number.gemspec