activesupport 4.2.0 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +54 -21
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration.rb +326 -30
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,13 +1,14 @@
1
- require 'tzinfo'
2
- require 'thread_safe'
3
- require 'active_support/core_ext/object/blank'
4
- require 'active_support/core_ext/object/try'
1
+ # frozen_string_literal: true
2
+
3
+ require "tzinfo"
4
+ require "concurrent/map"
5
+ require "active_support/core_ext/object/blank"
5
6
 
6
7
  module ActiveSupport
7
8
  # The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
8
9
  # It allows us to do the following:
9
10
  #
10
- # * Limit the set of zones provided by TZInfo to a meaningful subset of 146
11
+ # * Limit the set of zones provided by TZInfo to a meaningful subset of 134
11
12
  # zones.
12
13
  # * Retrieve and display zones with a friendlier name
13
14
  # (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
@@ -23,19 +24,13 @@ module ActiveSupport
23
24
  # config.time_zone = 'Eastern Time (US & Canada)'
24
25
  # end
25
26
  #
26
- # Time.zone # => #<TimeZone:0x514834...>
27
+ # Time.zone # => #<ActiveSupport::TimeZone:0x514834...>
27
28
  # Time.zone.name # => "Eastern Time (US & Canada)"
28
29
  # Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00
29
- #
30
- # The version of TZInfo bundled with Active Support only includes the
31
- # definitions necessary to support the zones defined by the TimeZone class.
32
- # If you need to use zones that aren't defined by TimeZone, you'll need to
33
- # install the TZInfo gem (if a recent version of the gem is installed locally,
34
- # this will be used instead of the bundled version.)
35
30
  class TimeZone
36
31
  # Keys are Rails TimeZone names, values are TZInfo identifiers.
37
32
  MAPPING = {
38
- "International Date Line West" => "Pacific/Midway",
33
+ "International Date Line West" => "Etc/GMT+12",
39
34
  "Midway Island" => "Pacific/Midway",
40
35
  "American Samoa" => "Pacific/Pago_Pago",
41
36
  "Hawaii" => "Pacific/Honolulu",
@@ -66,6 +61,7 @@ module ActiveSupport
66
61
  "Buenos Aires" => "America/Argentina/Buenos_Aires",
67
62
  "Montevideo" => "America/Montevideo",
68
63
  "Georgetown" => "America/Guyana",
64
+ "Puerto Rico" => "America/Puerto_Rico",
69
65
  "Greenland" => "America/Godthab",
70
66
  "Mid-Atlantic" => "Atlantic/South_Georgia",
71
67
  "Azores" => "Atlantic/Azores",
@@ -92,7 +88,8 @@ module ActiveSupport
92
88
  "Paris" => "Europe/Paris",
93
89
  "Amsterdam" => "Europe/Amsterdam",
94
90
  "Berlin" => "Europe/Berlin",
95
- "Bern" => "Europe/Berlin",
91
+ "Bern" => "Europe/Zurich",
92
+ "Zurich" => "Europe/Zurich",
96
93
  "Rome" => "Europe/Rome",
97
94
  "Stockholm" => "Europe/Stockholm",
98
95
  "Vienna" => "Europe/Vienna",
@@ -111,9 +108,11 @@ module ActiveSupport
111
108
  "Jerusalem" => "Asia/Jerusalem",
112
109
  "Harare" => "Africa/Harare",
113
110
  "Pretoria" => "Africa/Johannesburg",
111
+ "Kaliningrad" => "Europe/Kaliningrad",
114
112
  "Moscow" => "Europe/Moscow",
115
113
  "St. Petersburg" => "Europe/Moscow",
116
- "Volgograd" => "Europe/Moscow",
114
+ "Volgograd" => "Europe/Volgograd",
115
+ "Samara" => "Europe/Samara",
117
116
  "Kuwait" => "Asia/Kuwait",
118
117
  "Riyadh" => "Asia/Riyadh",
119
118
  "Nairobi" => "Africa/Nairobi",
@@ -170,6 +169,7 @@ module ActiveSupport
170
169
  "Guam" => "Pacific/Guam",
171
170
  "Port Moresby" => "Pacific/Port_Moresby",
172
171
  "Magadan" => "Asia/Magadan",
172
+ "Srednekolymsk" => "Asia/Srednekolymsk",
173
173
  "Solomon Is." => "Pacific/Guadalcanal",
174
174
  "New Caledonia" => "Pacific/Noumea",
175
175
  "Fiji" => "Pacific/Fiji",
@@ -183,26 +183,27 @@ module ActiveSupport
183
183
  "Samoa" => "Pacific/Apia"
184
184
  }
185
185
 
186
- UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
187
- UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(':', '')
186
+ UTC_OFFSET_WITH_COLON = "%s%02d:%02d"
187
+ UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(":", "")
188
188
 
189
- @lazy_zones_map = ThreadSafe::Cache.new
189
+ @lazy_zones_map = Concurrent::Map.new
190
+ @country_zones = Concurrent::Map.new
190
191
 
191
192
  class << self
192
193
  # Assumes self represents an offset from UTC in seconds (as returned from
193
194
  # Time#utc_offset) and turns this into an +HH:MM formatted string.
194
195
  #
195
- # TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
196
+ # ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
196
197
  def seconds_to_utc_offset(seconds, colon = true)
197
198
  format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
198
- sign = (seconds < 0 ? '-' : '+')
199
+ sign = (seconds < 0 ? "-" : "+")
199
200
  hours = seconds.abs / 3600
200
201
  minutes = (seconds.abs % 3600) / 60
201
202
  format % [sign, hours, minutes]
202
203
  end
203
204
 
204
205
  def find_tzinfo(name)
205
- TZInfo::TimezoneProxy.new(MAPPING[name] || name)
206
+ TZInfo::Timezone.new(MAPPING[name] || name)
206
207
  end
207
208
 
208
209
  alias_method :create, :new
@@ -221,13 +222,6 @@ module ActiveSupport
221
222
  @zones ||= zones_map.values.sort
222
223
  end
223
224
 
224
- def zones_map
225
- @zones_map ||= begin
226
- MAPPING.each_key {|place| self[place]} # load all the zones
227
- @lazy_zones_map
228
- end
229
- end
230
-
231
225
  # Locate a specific time zone object. If the argument is a string, it
232
226
  # is interpreted to mean the name of the timezone to locate. If it is a
233
227
  # numeric value it is either the hour offset, or the second offset, of the
@@ -235,25 +229,60 @@ module ActiveSupport
235
229
  # Returns +nil+ if no such time zone is known to the system.
236
230
  def [](arg)
237
231
  case arg
238
- when String
232
+ when String
239
233
  begin
240
- @lazy_zones_map[arg] ||= create(arg).tap { |tz| tz.utc_offset }
234
+ @lazy_zones_map[arg] ||= create(arg)
241
235
  rescue TZInfo::InvalidTimezoneIdentifier
242
236
  nil
243
237
  end
244
- when Numeric, ActiveSupport::Duration
245
- arg *= 3600 if arg.abs <= 13
246
- all.find { |z| z.utc_offset == arg.to_i }
247
- else
248
- raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
238
+ when Numeric, ActiveSupport::Duration
239
+ arg *= 3600 if arg.abs <= 13
240
+ all.find { |z| z.utc_offset == arg.to_i }
241
+ else
242
+ raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
249
243
  end
250
244
  end
251
245
 
252
246
  # A convenience method for returning a collection of TimeZone objects
253
247
  # for time zones in the USA.
254
248
  def us_zones
255
- @us_zones ||= all.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ }
249
+ country_zones(:us)
250
+ end
251
+
252
+ # A convenience method for returning a collection of TimeZone objects
253
+ # for time zones in the country specified by its ISO 3166-1 Alpha2 code.
254
+ def country_zones(country_code)
255
+ code = country_code.to_s.upcase
256
+ @country_zones[code] ||= load_country_zones(code)
257
+ end
258
+
259
+ def clear #:nodoc:
260
+ @lazy_zones_map = Concurrent::Map.new
261
+ @country_zones = Concurrent::Map.new
262
+ @zones = nil
263
+ @zones_map = nil
256
264
  end
265
+
266
+ private
267
+ def load_country_zones(code)
268
+ country = TZInfo::Country.get(code)
269
+ country.zone_identifiers.map do |tz_id|
270
+ if MAPPING.value?(tz_id)
271
+ MAPPING.inject([]) do |memo, (key, value)|
272
+ memo << self[key] if value == tz_id
273
+ memo
274
+ end
275
+ else
276
+ create(tz_id, nil, TZInfo::Timezone.new(tz_id))
277
+ end
278
+ end.flatten(1).sort!
279
+ end
280
+
281
+ def zones_map
282
+ @zones_map ||= MAPPING.each_with_object({}) do |(name, _), zones|
283
+ zones[name] = self[name]
284
+ end
285
+ end
257
286
  end
258
287
 
259
288
  include Comparable
@@ -268,7 +297,6 @@ module ActiveSupport
268
297
  @name = name
269
298
  @utc_offset = utc_offset
270
299
  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
271
- @current_period = nil
272
300
  end
273
301
 
274
302
  # Returns the offset of this time zone from UTC in seconds.
@@ -276,14 +304,17 @@ module ActiveSupport
276
304
  if @utc_offset
277
305
  @utc_offset
278
306
  else
279
- @current_period ||= tzinfo.current_period if tzinfo
280
- @current_period.utc_offset if @current_period
307
+ tzinfo.current_period.utc_offset if tzinfo && tzinfo.current_period
281
308
  end
282
309
  end
283
310
 
284
- # Returns the offset of this time zone as a formatted string, of the
285
- # format "+HH:MM".
286
- def formatted_offset(colon=true, alternate_utc_string = nil)
311
+ # Returns a formatted string of the offset from UTC, or an alternative
312
+ # string if the time zone is already UTC.
313
+ #
314
+ # zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
315
+ # zone.formatted_offset # => "-06:00"
316
+ # zone.formatted_offset(false) # => "-0600"
317
+ def formatted_offset(colon = true, alternate_utc_string = nil)
287
318
  utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
288
319
  end
289
320
 
@@ -327,6 +358,41 @@ module ActiveSupport
327
358
  Time.at(secs).utc.in_time_zone(self)
328
359
  end
329
360
 
361
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
362
+ # of +self+ from an ISO 8601 string.
363
+ #
364
+ # Time.zone = 'Hawaii' # => "Hawaii"
365
+ # Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
366
+ #
367
+ # If the time components are missing then they will be set to zero.
368
+ #
369
+ # Time.zone = 'Hawaii' # => "Hawaii"
370
+ # Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
371
+ #
372
+ # If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
373
+ # which usually returns +nil+ when given an invalid date string.
374
+ def iso8601(str)
375
+ parts = Date._iso8601(str)
376
+
377
+ raise ArgumentError, "invalid date" if parts.empty?
378
+
379
+ time = Time.new(
380
+ parts.fetch(:year),
381
+ parts.fetch(:mon),
382
+ parts.fetch(:mday),
383
+ parts.fetch(:hour, 0),
384
+ parts.fetch(:min, 0),
385
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
386
+ parts.fetch(:offset, 0)
387
+ )
388
+
389
+ if parts[:offset]
390
+ TimeWithZone.new(time.utc, self)
391
+ else
392
+ TimeWithZone.new(nil, self, time)
393
+ end
394
+ end
395
+
330
396
  # Method for creating new ActiveSupport::TimeWithZone instance in time zone
331
397
  # of +self+ from parsed string.
332
398
  #
@@ -343,25 +409,64 @@ module ActiveSupport
343
409
  # components are supplied, then the day of the month defaults to 1:
344
410
  #
345
411
  # Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
346
- def parse(str, now=now())
347
- parts = Date._parse(str, false)
348
- return if parts.empty?
412
+ #
413
+ # If the string is invalid then an +ArgumentError+ could be raised.
414
+ def parse(str, now = now())
415
+ parts_to_time(Date._parse(str, false), now)
416
+ end
417
+
418
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
419
+ # of +self+ from an RFC 3339 string.
420
+ #
421
+ # Time.zone = 'Hawaii' # => "Hawaii"
422
+ # Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
423
+ #
424
+ # If the time or zone components are missing then an +ArgumentError+ will
425
+ # be raised. This is much stricter than either +parse+ or +iso8601+ which
426
+ # allow for missing components.
427
+ #
428
+ # Time.zone = 'Hawaii' # => "Hawaii"
429
+ # Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
430
+ def rfc3339(str)
431
+ parts = Date._rfc3339(str)
432
+
433
+ raise ArgumentError, "invalid date" if parts.empty?
349
434
 
350
435
  time = Time.new(
351
- parts.fetch(:year, now.year),
352
- parts.fetch(:mon, now.month),
353
- parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
354
- parts.fetch(:hour, 0),
355
- parts.fetch(:min, 0),
356
- parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
357
- parts.fetch(:offset, 0)
436
+ parts.fetch(:year),
437
+ parts.fetch(:mon),
438
+ parts.fetch(:mday),
439
+ parts.fetch(:hour),
440
+ parts.fetch(:min),
441
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
442
+ parts.fetch(:offset)
358
443
  )
359
444
 
360
- if parts[:offset]
361
- TimeWithZone.new(time.utc, self)
362
- else
363
- TimeWithZone.new(nil, self, time)
364
- end
445
+ TimeWithZone.new(time.utc, self)
446
+ end
447
+
448
+ # Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
449
+ #
450
+ # Assumes that +str+ is a time in the time zone +self+,
451
+ # unless +format+ includes an explicit time zone.
452
+ # (This is the same behavior as +parse+.)
453
+ # In either case, the returned TimeWithZone has the timezone of +self+.
454
+ #
455
+ # Time.zone = 'Hawaii' # => "Hawaii"
456
+ # Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
457
+ #
458
+ # If upper components are missing from the string, they are supplied from
459
+ # TimeZone#now:
460
+ #
461
+ # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
462
+ # Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
463
+ #
464
+ # However, if the date component is not provided, but any other upper
465
+ # components are supplied, then the day of the month defaults to 1:
466
+ #
467
+ # Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
468
+ def strptime(str, format, now = now())
469
+ parts_to_time(DateTime._strptime(str, format), now)
365
470
  end
366
471
 
367
472
  # Returns an ActiveSupport::TimeWithZone instance representing the current
@@ -373,7 +478,7 @@ module ActiveSupport
373
478
  time_now.utc.in_time_zone(self)
374
479
  end
375
480
 
376
- # Return the current date in this time zone.
481
+ # Returns the current date in this time zone.
377
482
  def today
378
483
  tzinfo.now.to_date
379
484
  end
@@ -397,7 +502,7 @@ module ActiveSupport
397
502
 
398
503
  # Adjust the given time to the simultaneous time in UTC. Returns a
399
504
  # Time.utc() instance.
400
- def local_to_utc(time, dst=true)
505
+ def local_to_utc(time, dst = true)
401
506
  tzinfo.local_to_utc(time, dst)
402
507
  end
403
508
 
@@ -409,15 +514,49 @@ module ActiveSupport
409
514
 
410
515
  # Available so that TimeZone instances respond like TZInfo::Timezone
411
516
  # instances.
412
- def period_for_local(time, dst=true)
413
- tzinfo.period_for_local(time, dst)
517
+ def period_for_local(time, dst = true)
518
+ tzinfo.period_for_local(time, dst) { |periods| periods.last }
414
519
  end
415
520
 
416
521
  def periods_for_local(time) #:nodoc:
417
522
  tzinfo.periods_for_local(time)
418
523
  end
419
524
 
525
+ def init_with(coder) #:nodoc:
526
+ initialize(coder["name"])
527
+ end
528
+
529
+ def encode_with(coder) #:nodoc:
530
+ coder.tag = "!ruby/object:#{self.class}"
531
+ coder.map = { "name" => tzinfo.name }
532
+ end
533
+
420
534
  private
535
+ def parts_to_time(parts, now)
536
+ raise ArgumentError, "invalid date" if parts.nil?
537
+ return if parts.empty?
538
+
539
+ if parts[:seconds]
540
+ time = Time.at(parts[:seconds])
541
+ else
542
+ time = Time.new(
543
+ parts.fetch(:year, now.year),
544
+ parts.fetch(:mon, now.month),
545
+ parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
546
+ parts.fetch(:hour, 0),
547
+ parts.fetch(:min, 0),
548
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
549
+ parts.fetch(:offset, 0)
550
+ )
551
+ end
552
+
553
+ if parts[:offset] || parts[:seconds]
554
+ TimeWithZone.new(time.utc, self)
555
+ else
556
+ TimeWithZone.new(nil, self, time)
557
+ end
558
+ end
559
+
421
560
  def time_now
422
561
  Time.now
423
562
  end
@@ -1,4 +1,6 @@
1
- require_relative 'gem_version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "gem_version"
2
4
 
3
5
  module ActiveSupport
4
6
  # Returns the version of the currently loaded ActiveSupport as a <tt>Gem::Version</tt>
@@ -1,9 +1,11 @@
1
- require 'time'
2
- require 'base64'
3
- require 'bigdecimal'
4
- require 'active_support/core_ext/module/delegation'
5
- require 'active_support/core_ext/string/inflections'
6
- require 'active_support/core_ext/date_time/calculations'
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+ require "base64"
5
+ require "bigdecimal"
6
+ require "active_support/core_ext/module/delegation"
7
+ require "active_support/core_ext/string/inflections"
8
+ require "active_support/core_ext/date_time/calculations"
7
9
 
8
10
  module ActiveSupport
9
11
  # = XmlMini
@@ -20,11 +22,11 @@ module ActiveSupport
20
22
  attr_writer :original_filename, :content_type
21
23
 
22
24
  def original_filename
23
- @original_filename || 'untitled'
25
+ @original_filename || "untitled"
24
26
  end
25
27
 
26
28
  def content_type
27
- @content_type || 'application/octet-stream'
29
+ @content_type || "application/octet-stream"
28
30
  end
29
31
  end
30
32
 
@@ -32,20 +34,25 @@ module ActiveSupport
32
34
  "binary" => "base64"
33
35
  } unless defined?(DEFAULT_ENCODINGS)
34
36
 
35
- TYPE_NAMES = {
36
- "Symbol" => "symbol",
37
- "Fixnum" => "integer",
38
- "Bignum" => "integer",
39
- "BigDecimal" => "decimal",
40
- "Float" => "float",
41
- "TrueClass" => "boolean",
42
- "FalseClass" => "boolean",
43
- "Date" => "date",
44
- "DateTime" => "dateTime",
45
- "Time" => "dateTime",
46
- "Array" => "array",
47
- "Hash" => "hash"
48
- } unless defined?(TYPE_NAMES)
37
+ unless defined?(TYPE_NAMES)
38
+ TYPE_NAMES = {
39
+ "Symbol" => "symbol",
40
+ "Integer" => "integer",
41
+ "BigDecimal" => "decimal",
42
+ "Float" => "float",
43
+ "TrueClass" => "boolean",
44
+ "FalseClass" => "boolean",
45
+ "Date" => "date",
46
+ "DateTime" => "dateTime",
47
+ "Time" => "dateTime",
48
+ "Array" => "array",
49
+ "Hash" => "hash"
50
+ }
51
+
52
+ # No need to map these on Ruby 2.4+
53
+ TYPE_NAMES["Fixnum"] = "integer" unless 0.class == Integer
54
+ TYPE_NAMES["Bignum"] = "integer" unless 0.class == Integer
55
+ end
49
56
 
50
57
  FORMATTING = {
51
58
  "symbol" => Proc.new { |symbol| symbol.to_s },
@@ -63,10 +70,20 @@ module ActiveSupport
63
70
  "datetime" => Proc.new { |time| Time.xmlschema(time).utc rescue ::DateTime.parse(time).utc },
64
71
  "integer" => Proc.new { |integer| integer.to_i },
65
72
  "float" => Proc.new { |float| float.to_f },
66
- "decimal" => Proc.new { |number| BigDecimal(number) },
73
+ "decimal" => Proc.new do |number|
74
+ if String === number
75
+ begin
76
+ BigDecimal(number)
77
+ rescue ArgumentError
78
+ BigDecimal("0")
79
+ end
80
+ else
81
+ BigDecimal(number)
82
+ end
83
+ end,
67
84
  "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.to_s.strip) },
68
85
  "string" => Proc.new { |string| string.to_s },
69
- "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
86
+ "yaml" => Proc.new { |yaml| YAML.load(yaml) rescue yaml },
70
87
  "base64Binary" => Proc.new { |bin| ::Base64.decode64(bin) },
71
88
  "binary" => Proc.new { |bin, entity| _parse_binary(bin, entity) },
72
89
  "file" => Proc.new { |file, entity| _parse_file(file, entity) }
@@ -78,7 +95,10 @@ module ActiveSupport
78
95
  )
79
96
  end
80
97
 
81
- delegate :parse, :to => :backend
98
+ attr_accessor :depth
99
+ self.depth = 100
100
+
101
+ delegate :parse, to: :backend
82
102
 
83
103
  def backend
84
104
  current_thread_backend || @backend
@@ -100,7 +120,7 @@ module ActiveSupport
100
120
 
101
121
  def to_tag(key, value, options)
102
122
  type_name = options.delete(:type)
103
- merged_options = options.merge(:root => key, :skip_instruct => true)
123
+ merged_options = options.merge(root: key, skip_instruct: true)
104
124
 
105
125
  if value.is_a?(::Method) || value.is_a?(::Proc)
106
126
  if value.arity == 1
@@ -118,7 +138,7 @@ module ActiveSupport
118
138
 
119
139
  key = rename_key(key.to_s, options)
120
140
 
121
- attributes = options[:skip_types] || type_name.nil? ? { } : { :type => type_name }
141
+ attributes = options[:skip_types] || type_name.nil? ? {} : { type: type_name }
122
142
  attributes[:nil] = true if value.nil?
123
143
 
124
144
  encoding = options[:encoding] || DEFAULT_ENCODINGS[type_name]
@@ -141,33 +161,31 @@ module ActiveSupport
141
161
  key
142
162
  end
143
163
 
144
- protected
145
-
146
- def _dasherize(key)
147
- # $2 must be a non-greedy regex for this to work
148
- left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1,3]
149
- "#{left}#{middle.tr('_ ', '--')}#{right}"
150
- end
164
+ private
151
165
 
152
- # TODO: Add support for other encodings
153
- def _parse_binary(bin, entity) #:nodoc:
154
- case entity['encoding']
155
- when 'base64'
156
- ::Base64.decode64(bin)
157
- else
158
- bin
166
+ def _dasherize(key)
167
+ # $2 must be a non-greedy regex for this to work
168
+ left, middle, right = /\A(_*)(.*?)(_*)\Z/.match(key.strip)[1, 3]
169
+ "#{left}#{middle.tr('_ ', '--')}#{right}"
159
170
  end
160
- end
161
171
 
162
- def _parse_file(file, entity)
163
- f = StringIO.new(::Base64.decode64(file))
164
- f.extend(FileLike)
165
- f.original_filename = entity['name']
166
- f.content_type = entity['content_type']
167
- f
168
- end
172
+ # TODO: Add support for other encodings
173
+ def _parse_binary(bin, entity)
174
+ case entity["encoding"]
175
+ when "base64"
176
+ ::Base64.decode64(bin)
177
+ else
178
+ bin
179
+ end
180
+ end
169
181
 
170
- private
182
+ def _parse_file(file, entity)
183
+ f = StringIO.new(::Base64.decode64(file))
184
+ f.extend(FileLike)
185
+ f.original_filename = entity["name"]
186
+ f.content_type = entity["content_type"]
187
+ f
188
+ end
171
189
 
172
190
  def current_thread_backend
173
191
  Thread.current[:xml_mini_backend]
@@ -187,5 +205,5 @@ module ActiveSupport
187
205
  end
188
206
  end
189
207
 
190
- XmlMini.backend = 'REXML'
208
+ XmlMini.backend = "REXML"
191
209
  end