rails_client_timezone 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,163 @@
1
+ module RailsClientTimezone
2
+ # ActiveSupport class for mapping tz info identifiers to rails identifiers
3
+ class ActiveSupportExt
4
+ TIMEZONE_MAPPING = {
5
+ "Pacific/Midway"=>"International Date Line West",
6
+ "Pacific/Midway"=>"Midway Island",
7
+ "Pacific/Pago_Pago"=>"American Samoa",
8
+ "Pacific/Honolulu"=>"Hawaii",
9
+ "America/Juneau"=>"Alaska",
10
+ "America/Los_Angeles"=>"Pacific Time (US & Canada)",
11
+ "America/Tijuana"=>"Tijuana",
12
+ "America/Denver"=>"Mountain Time (US & Canada)",
13
+ "America/Phoenix"=>"Arizona",
14
+ "America/Chihuahua"=>"Chihuahua",
15
+ "America/Mazatlan"=>"Mazatlan",
16
+ "America/Chicago"=>"Central Time (US & Canada)",
17
+ "America/Regina"=>"Saskatchewan",
18
+ "America/Mexico_City"=>"Mexico City",
19
+ "America/Monterrey"=>"Monterrey",
20
+ "America/Guatemala"=>"Central America",
21
+ "America/New_York"=>"Eastern Time (US & Canada)",
22
+ "America/Indianapolis"=>"Indiana (East)",
23
+ "America/Indiana/Indianapolis"=>"Indiana (East)",
24
+ "America/Bogota"=>"Bogota",
25
+ "America/Lima"=>"Quito",
26
+ "America/Halifax"=>"Atlantic Time (Canada)",
27
+ "America/Caracas"=>"Caracas",
28
+ "America/La_Paz"=>"La Paz",
29
+ "America/Santiago"=>"Santiago",
30
+ "America/Santo_Domingo"=>"Santiago",
31
+ "America/St_Johns"=>"Newfoundland",
32
+ "America/Sao_Paulo"=>"Brasilia",
33
+ "America/Argentina/Buenos_Aires"=>"Buenos Aires",
34
+ "America/Montevideo"=>"Montevideo",
35
+ "America/Argentina/San_Juan"=>"Georgetown",
36
+ "America/Guyana"=>"Georgetown",
37
+ "America/Godthab"=>"Greenland",
38
+ "Atlantic/South_Georgia"=>"Mid-Atlantic",
39
+ "Atlantic/Azores"=>"Azores",
40
+ "Atlantic/Cape_Verde"=>"Cape Verde Is.",
41
+ "Europe/Dublin"=>"Dublin",
42
+ "Europe/London"=>"London",
43
+ "Europe/Lisbon"=>"Lisbon",
44
+ "Africa/Casablanca"=>"Casablanca",
45
+ "Africa/Monrovia"=>"Monrovia",
46
+ "Etc/UTC"=>"UTC",
47
+ "Europe/Belgrade"=>"Belgrade",
48
+ "Europe/Bratislava"=>"Bratislava",
49
+ "Europe/Budapest"=>"Budapest",
50
+ "Europe/Ljubljana"=>"Ljubljana",
51
+ "Europe/Prague"=>"Prague",
52
+ "Europe/Sarajevo"=>"Sarajevo",
53
+ "Europe/Skopje"=>"Skopje",
54
+ "Europe/Warsaw"=>"Warsaw",
55
+ "Europe/Zagreb"=>"Zagreb",
56
+ "Europe/Brussels"=>"Brussels",
57
+ "Europe/Copenhagen"=>"Copenhagen",
58
+ "Europe/Madrid"=>"Madrid",
59
+ "Europe/Paris"=>"Paris",
60
+ "Europe/Amsterdam"=>"Amsterdam",
61
+ "Europe/Berlin"=>"Bern",
62
+ "Europe/Rome"=>"Rome",
63
+ "Europe/Stockholm"=>"Stockholm",
64
+ "Europe/Vienna"=>"Vienna",
65
+ "Africa/Algiers"=>"West Central Africa",
66
+ "Europe/Bucharest"=>"Bucharest",
67
+ "Africa/Cairo"=>"Cairo",
68
+ "Africa/Kinshasa"=>"West Central Africa",
69
+ "Europe/Helsinki"=>"Helsinki",
70
+ "Europe/Kiev"=>"Kyev",
71
+ "Europe/Riga"=>"Riga",
72
+ "Europe/Sofia"=>"Sofia",
73
+ "Europe/Tallinn"=>"Tallinn",
74
+ "Europe/Vilnius"=>"Vilnius",
75
+ "Europe/Athens"=>"Athens",
76
+ "Europe/Istanbul"=>"Istanbul",
77
+ "Europe/Minsk"=>"Minsk",
78
+ "Asia/Jerusalem"=>"Jerusalem",
79
+ "Africa/Harare"=>"Harare",
80
+ "Africa/Johannesburg"=>"Pretoria",
81
+ "Europe/Kaliningrad"=>"Kaliningrad",
82
+ "Europe/Moscow"=>"Moscow",
83
+ "Europe/Volgograd"=>"Volgograd",
84
+ "Europe/Samara"=>"Samara",
85
+ "Asia/Kuwait"=>"Kuwait",
86
+ "Asia/Riyadh"=>"Riyadh",
87
+ "Africa/Nairobi"=>"Nairobi",
88
+ "Asia/Baghdad"=>"Baghdad",
89
+ "Asia/Tehran"=>"Tehran",
90
+ "Asia/Muscat"=>"Abu Dhabi",
91
+ "Asia/Muscat"=>"Muscat",
92
+ "Asia/Baku"=>"Baku",
93
+ "Asia/Tbilisi"=>"Tbilisi",
94
+ "Asia/Yerevan"=>"Yerevan",
95
+ "Asia/Kabul"=>"Kabul",
96
+ "Asia/Yekaterinburg"=>"Ekaterinburg",
97
+ "Asia/Karachi"=>"Karachi",
98
+ "Asia/Tashkent"=>"Tashkent",
99
+ "Asia/Kolkata"=>"Chennai",
100
+ "Asia/Calcutta"=>"New Delhi",
101
+ "Asia/Kathmandu"=>"Kathmandu",
102
+ "Asia/Katmandu"=>"Kathmandu",
103
+ "Asia/Dhaka"=>"Dhaka",
104
+ "Asia/Colombo"=>"Sri Jayawardenepura",
105
+ "Asia/Almaty"=>"Almaty",
106
+ "Asia/Qyzylorda"=>"Almaty",
107
+ "Asia/Novosibirsk"=>"Novosibirsk",
108
+ "Asia/Bangkok"=>"Bangkok",
109
+ "Asia/Jakarta"=>"Jakarta",
110
+ "Asia/Krasnoyarsk"=>"Krasnoyarsk",
111
+ "Asia/Shanghai"=>"Beijing",
112
+ "Asia/Chongqing"=>"Chongqing",
113
+ "Asia/Hong_Kong"=>"Hong Kong",
114
+ "Asia/Urumqi"=>"Urumqi",
115
+ "Asia/Kuala_Lumpur"=>"Kuala Lumpur",
116
+ "Asia/Rangoon"=>"Rangoon",
117
+ "Asia/Singapore"=>"Singapore",
118
+ "Asia/Taipei"=>"Taipei",
119
+ "Asia/Irkutsk"=>"Irkutsk",
120
+ "Asia/Ulaanbaatar"=>"Ulaanbaatar",
121
+ "Asia/Seoul"=>"Seoul",
122
+ "Asia/Tokyo"=>"Tokyo",
123
+ "Asia/Yakutsk"=>"Yakutsk",
124
+ "Australia/Darwin"=>"Darwin",
125
+ "Australia/Adelaide"=>"Adelaide",
126
+ "Australia/Melbourne"=>"Melbourne",
127
+ "Australia/Lord_Howe"=>"Melbourne",
128
+ "Australia/Queensland"=>"Brisbane",
129
+ "Australia/Victoria"=>"Melbourne",
130
+ "Australia/NSW"=>"Melbourne",
131
+ "Australia/Sydney"=>"Sydney",
132
+ "Australia/Brisbane"=>"Brisbane",
133
+ "Australia/Hobart"=>"Hobart",
134
+ "Australia/Currie"=>"Melbourne",
135
+ "Australia/Broken_Hill"=>"Adelaide",
136
+ "Australia/Lindeman"=>"Brisbane",
137
+ "Australia/Perth"=>"Perth",
138
+ "Australia/Eucla"=>"Perth",
139
+ "Asia/Vladivostok"=>"Vladivostok",
140
+ "Pacific/Guam"=>"Guam",
141
+ "Pacific/Port_Moresby"=>"Port Moresby",
142
+ "Asia/Magadan"=>"Magadan",
143
+ "Asia/Srednekolymsk"=>"Srednekolymsk",
144
+ "Pacific/Guadalcanal"=>"Solomon Is.",
145
+ "Pacific/Noumea"=>"New Caledonia",
146
+ "Pacific/Fiji"=>"Fiji",
147
+ "Asia/Kamchatka"=>"Kamchatka",
148
+ "Pacific/Majuro"=>"Marshall Is.",
149
+ "Pacific/Auckland"=>"Auckland",
150
+ "Pacific/Auckland"=>"Wellington",
151
+ "Pacific/Tongatapu"=>"Nuku'alofa",
152
+ "Pacific/Fakaofo"=>"Tokelau Is.",
153
+ "Pacific/Chatham"=>"Chatham Is.",
154
+ "Pacific/Pago_Pago"=>"Samoa",
155
+ "Pacific/Galapagos"=>"Samoa",
156
+ "Pacific/Apia"=>"Samoa"
157
+ }
158
+
159
+ def self.format(zone)
160
+ TIMEZONE_MAPPING[zone] || nil
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,60 @@
1
+ # Runs the controller code in the user's time zone which is determined through the offsets passed via cookies.
2
+ module RailsClientTimezone
3
+ class Filter
4
+
5
+ def self.filter(controller, &block)
6
+ cookies = controller.send(:cookies)
7
+
8
+ current_time_zone = if Setting.mode == :browser
9
+ get_time_zone_by_browser_offset(cookies[:utc_offset_summer], cookies[:utc_offset_winter], cookies[:last_known_tz])
10
+ elsif Setting.mode == :ip
11
+ get_time_zone_by_ip(controller, cookies[:last_known_tz])
12
+ else
13
+ get_time_zone_by_smart(controller, cookies[:utc_offset_summer], cookies[:utc_offset_winter], cookies[:last_known_tz])
14
+ end
15
+ controller.response.set_cookie(:last_known_tz, {:path => "/", :value => current_time_zone.name})
16
+
17
+ Time.use_zone(current_time_zone) do
18
+ yield
19
+ end
20
+ end
21
+
22
+ # Returns the time zone based on parsed *utc_offset_summer* and *utc_offset_winter*
23
+ # Returns the default TimeZone if none is resolved
24
+ def self.get_time_zone_by_browser_offset(utc_offset_summer, utc_offset_winter, last_known_tz)
25
+ # ActiveSupport::TimeZone[offset] - will return the first time zone that matches the offset.
26
+ # But, we need to get the exact time zone inorder to reflect the daylight savings.
27
+ # So, we get the user's time zone exactly by matching the summer offset and winter offset both.
28
+ [ActiveSupport::TimeZone[last_known_tz.to_s], ActiveSupport::TimeZone.all].flatten.compact.detect(ifnone = Time.method(:zone_default)) do |zone|
29
+ Time.use_zone(zone.name) do
30
+ if utc_offset_summer.present? && utc_offset_winter.present?
31
+ (Time.zone.parse(Setting.mid_summer_date_str).utc_offset == utc_offset_summer.to_i && Time.zone.parse(Setting.mid_winter_date_str).utc_offset == utc_offset_winter.to_i)
32
+ else
33
+ (Time.zone.name == last_known_tz.to_s)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ # Returns the time zone based on IP address
40
+ # Returns the default TimeZone if none is resolved
41
+ def self.get_time_zone_by_ip(controller, last_known_tz = nil)
42
+ return ActiveSupport::TimeZone[last_known_tz] if last_known_tz && ActiveSupport::TimeZone[last_known_tz]
43
+ begin
44
+ ip_addr = controller.request.remote_ip
45
+ geo_timezone = GeoIP.new(Setting.geoip_data_path).city(ip_addr) ? GeoIP.new(Setting.geoip_data_path).city(ip_addr).timezone : nil
46
+ timezone_name = geo_timezone && ActiveSupportExt.format(geo_timezone) ? ActiveSupportExt.format(geo_timezone) : Time.zone_default.name
47
+ rescue Exception => e
48
+ ActiveSupport::TimeZone[Time.zone_default.name]
49
+ end
50
+ ActiveSupport::TimeZone[timezone_name]
51
+ end
52
+
53
+ # Returns the time zone using both ip address and browser offset
54
+ # Returns the default TimeZone if none is resolved
55
+ def self.get_time_zone_by_smart(controller, utc_offset_summer, utc_offset_winter, last_known_tz)
56
+ last_known_tz_val = last_known_tz ? last_known_tz : get_time_zone_by_ip(controller).name
57
+ get_time_zone_by_browser_offset(utc_offset_summer, utc_offset_winter, last_known_tz_val)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,34 @@
1
+ module RailsClientTimezone
2
+ class Setting
3
+ class << self
4
+ attr_writer :baseline_year
5
+ attr_writer :mode
6
+ attr_writer :geoip_data_path
7
+
8
+ #Possible mode values - :ip, :browser, :smart
9
+ def mode
10
+ @mode ||= :smart
11
+ end
12
+
13
+ def geoip_data_path
14
+ @geoip_data_path ||= File.expand_path(File.join(File.dirname(__FILE__), '../..', 'data/geoip', 'GeoLiteCity.dat'))
15
+ end
16
+
17
+ def baseline_year
18
+ @baseline_year ||= 2011
19
+ end
20
+
21
+ def mid_summer_date_str
22
+ "#{year}-6-21"
23
+ end
24
+
25
+ def mid_winter_date_str
26
+ "#{year}-12-21"
27
+ end
28
+
29
+ def year
30
+ (baseline_year.to_sym == :current) ? Time.zone.now.year : baseline_year
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module RailsClientTimezone
2
+ VERSION = "0.7.0"
3
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rails_client_timezone/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rails_client_timezone"
7
+ s.version = RailsClientTimezone::VERSION
8
+ s.authors = ["Udaya Kiran", "Yamini Devarajan"]
9
+ s.email = ["udaykiran.vit@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Rails Browser Timezone client gem}
12
+ s.description = %q{Simple code to detect browser time zone and handle it in rails app}
13
+
14
+ s.rubyforge_project = "rails_client_timezone"
15
+
16
+ s.files = %w[
17
+ Gemfile
18
+ README.md
19
+ lib/rails_client_timezone/filter.rb
20
+ lib/rails_client_timezone/version.rb
21
+ lib/rails_client_timezone/setting.rb
22
+ lib/rails_client_timezone/active_support_ext.rb
23
+ lib/geoip.rb
24
+ rails_client_timezone.gemspec
25
+ ]
26
+ s.require_paths = ["lib"]
27
+
28
+ s.add_runtime_dependency "activesupport", '> 2'
29
+ s.add_runtime_dependency "geoip", '1.6.1'
30
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_client_timezone
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.0
5
+ platform: ruby
6
+ authors:
7
+ - Udaya Kiran
8
+ - Yamini Devarajan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-01-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">"
19
+ - !ruby/object:Gem::Version
20
+ version: '2'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">"
26
+ - !ruby/object:Gem::Version
27
+ version: '2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: geoip
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '='
33
+ - !ruby/object:Gem::Version
34
+ version: 1.6.1
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '='
40
+ - !ruby/object:Gem::Version
41
+ version: 1.6.1
42
+ description: Simple code to detect browser time zone and handle it in rails app
43
+ email:
44
+ - udaykiran.vit@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - Gemfile
50
+ - README.md
51
+ - lib/geoip.rb
52
+ - lib/rails_client_timezone/active_support_ext.rb
53
+ - lib/rails_client_timezone/filter.rb
54
+ - lib/rails_client_timezone/setting.rb
55
+ - lib/rails_client_timezone/version.rb
56
+ - rails_client_timezone.gemspec
57
+ homepage: ''
58
+ licenses: []
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project: rails_client_timezone
76
+ rubygems_version: 2.4.5.1
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Rails Browser Timezone client gem
80
+ test_files: []