activesupport 4.0.12 → 7.0.2.4

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 (295) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +249 -501
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  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 +41 -13
  9. data/lib/active_support/benchmarkable.rb +7 -15
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +96 -74
  12. data/lib/active_support/cache/mem_cache_store.rb +211 -103
  13. data/lib/active_support/cache/memory_store.rb +90 -58
  14. data/lib/active_support/cache/null_store.rb +19 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +468 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +86 -83
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  18. data/lib/active_support/cache.rb +580 -241
  19. data/lib/active_support/callbacks.rb +812 -425
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +103 -14
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
  23. data/lib/active_support/concurrency/share_lock.rb +226 -0
  24. data/lib/active_support/configurable.rb +21 -19
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +47 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +35 -44
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +26 -16
  32. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  34. data/lib/active_support/core_ext/array.rb +10 -7
  35. data/lib/active_support/core_ext/benchmark.rb +5 -3
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  37. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  38. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  40. data/lib/active_support/core_ext/class/subclasses.rb +25 -26
  41. data/lib/active_support/core_ext/class.rb +4 -4
  42. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  43. data/lib/active_support/core_ext/date/blank.rb +14 -0
  44. data/lib/active_support/core_ext/date/calculations.rb +31 -18
  45. data/lib/active_support/core_ext/date/conversions.rb +43 -32
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +5 -34
  48. data/lib/active_support/core_ext/date.rb +7 -4
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  53. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  54. data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  56. data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +8 -4
  59. data/lib/active_support/core_ext/digest/uuid.rb +79 -0
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +249 -17
  62. data/lib/active_support/core_ext/file/atomic.rb +41 -32
  63. data/lib/active_support/core_ext/file.rb +3 -1
  64. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +14 -5
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +39 -56
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -23
  72. data/lib/active_support/core_ext/hash.rb +10 -8
  73. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +11 -33
  76. data/lib/active_support/core_ext/integer.rb +5 -3
  77. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  80. data/lib/active_support/core_ext/kernel.rb +5 -4
  81. data/lib/active_support/core_ext/load_error.rb +5 -21
  82. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  83. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  84. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
  87. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  88. data/lib/active_support/core_ext/module/delegation.rb +172 -45
  89. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  90. data/lib/active_support/core_ext/module/introspection.rb +23 -38
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -10
  94. data/lib/active_support/core_ext/name_error.rb +45 -4
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  99. data/lib/active_support/core_ext/numeric.rb +6 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +70 -20
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  104. data/lib/active_support/core_ext/object/duplicable.rb +17 -47
  105. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +244 -0
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  110. data/lib/active_support/core_ext/object/try.rb +106 -26
  111. data/lib/active_support/core_ext/object/with_options.rb +64 -5
  112. data/lib/active_support/core_ext/object.rb +14 -12
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +18 -17
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  121. data/lib/active_support/core_ext/range.rb +7 -4
  122. data/lib/active_support/core_ext/regexp.rb +10 -1
  123. data/lib/active_support/core_ext/securerandom.rb +45 -0
  124. data/lib/active_support/core_ext/string/access.rb +42 -51
  125. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  126. data/lib/active_support/core_ext/string/conversions.rb +18 -13
  127. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  128. data/lib/active_support/core_ext/string/filters.rb +97 -7
  129. data/lib/active_support/core_ext/string/indent.rb +6 -4
  130. data/lib/active_support/core_ext/string/inflections.rb +106 -25
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +18 -9
  133. data/lib/active_support/core_ext/string/output_safety.rb +227 -54
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +6 -5
  136. data/lib/active_support/core_ext/string/zones.rb +4 -1
  137. data/lib/active_support/core_ext/string.rb +15 -13
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  141. data/lib/active_support/core_ext/time/calculations.rb +178 -116
  142. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  143. data/lib/active_support/core_ext/time/conversions.rb +37 -25
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +44 -42
  146. data/lib/active_support/core_ext/time.rb +8 -5
  147. data/lib/active_support/core_ext/uri.rb +4 -25
  148. data/lib/active_support/core_ext.rb +4 -2
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +3 -1
  152. data/lib/active_support/dependencies/interlock.rb +49 -0
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +71 -696
  155. data/lib/active_support/deprecation/behaviors.rb +65 -16
  156. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  159. data/lib/active_support/deprecation/method_wrappers.rb +62 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
  161. data/lib/active_support/deprecation/reporting.rb +81 -18
  162. data/lib/active_support/deprecation.rb +19 -11
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  166. data/lib/active_support/duration/iso8601_serializer.rb +67 -0
  167. data/lib/active_support/duration.rb +437 -39
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +117 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +170 -0
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +151 -0
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +8 -0
  178. data/lib/active_support/file_update_checker.rb +62 -37
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +17 -0
  181. data/lib/active_support/gzip.rb +7 -5
  182. data/lib/active_support/hash_with_indifferent_access.rb +207 -54
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +10 -6
  185. data/lib/active_support/i18n_railtie.rb +48 -19
  186. data/lib/active_support/inflections.rb +19 -12
  187. data/lib/active_support/inflector/inflections.rb +97 -37
  188. data/lib/active_support/inflector/methods.rb +192 -157
  189. data/lib/active_support/inflector/transliterate.rb +83 -33
  190. data/lib/active_support/inflector.rb +7 -5
  191. data/lib/active_support/isolated_execution_state.rb +64 -0
  192. data/lib/active_support/json/decoding.rb +37 -42
  193. data/lib/active_support/json/encoding.rb +93 -293
  194. data/lib/active_support/json.rb +4 -2
  195. data/lib/active_support/key_generator.rb +30 -47
  196. data/lib/active_support/lazy_load_hooks.rb +54 -21
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +10 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  200. data/lib/active_support/log_subscriber.rb +61 -18
  201. data/lib/active_support/logger.rb +40 -4
  202. data/lib/active_support/logger_silence.rb +17 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +69 -0
  204. data/lib/active_support/message_encryptor.rb +178 -55
  205. data/lib/active_support/message_verifier.rb +195 -26
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +45 -92
  210. data/lib/active_support/multibyte/unicode.rb +44 -377
  211. data/lib/active_support/multibyte.rb +5 -3
  212. data/lib/active_support/notifications/fanout.rb +177 -44
  213. data/lib/active_support/notifications/instrumenter.rb +117 -17
  214. data/lib/active_support/notifications.rb +106 -39
  215. data/lib/active_support/number_helper/number_converter.rb +181 -0
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  223. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  224. data/lib/active_support/number_helper.rb +152 -394
  225. data/lib/active_support/option_merger.rb +18 -5
  226. data/lib/active_support/ordered_hash.rb +8 -6
  227. data/lib/active_support/ordered_options.rb +43 -7
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +24 -11
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +10 -11
  232. data/lib/active_support/railtie.rb +118 -12
  233. data/lib/active_support/reloader.rb +130 -0
  234. data/lib/active_support/rescuable.rb +112 -57
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +38 -0
  238. data/lib/active_support/string_inquirer.rb +11 -4
  239. data/lib/active_support/subscriber.rb +109 -39
  240. data/lib/active_support/tagged_logging.rb +54 -17
  241. data/lib/active_support/test_case.rb +121 -37
  242. data/lib/active_support/testing/assertions.rb +177 -39
  243. data/lib/active_support/testing/autorun.rb +5 -3
  244. data/lib/active_support/testing/constant_lookup.rb +3 -6
  245. data/lib/active_support/testing/declarative.rb +10 -22
  246. data/lib/active_support/testing/deprecation.rb +65 -11
  247. data/lib/active_support/testing/file_fixtures.rb +38 -0
  248. data/lib/active_support/testing/isolation.rb +56 -87
  249. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  255. data/lib/active_support/testing/stream.rb +41 -0
  256. data/lib/active_support/testing/tagged_logging.rb +6 -4
  257. data/lib/active_support/testing/time_helpers.rb +246 -0
  258. data/lib/active_support/time.rb +13 -13
  259. data/lib/active_support/time_with_zone.rb +315 -90
  260. data/lib/active_support/values/time_zone.rb +306 -135
  261. data/lib/active_support/version.rb +6 -7
  262. data/lib/active_support/xml_mini/jdom.rb +117 -115
  263. data/lib/active_support/xml_mini/libxml.rb +22 -21
  264. data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
  265. data/lib/active_support/xml_mini/nokogiri.rb +19 -19
  266. data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
  267. data/lib/active_support/xml_mini/rexml.rb +25 -17
  268. data/lib/active_support/xml_mini.rb +67 -56
  269. data/lib/active_support.rb +58 -3
  270. metadata +125 -66
  271. data/lib/active_support/basic_object.rb +0 -11
  272. data/lib/active_support/buffered_logger.rb +0 -21
  273. data/lib/active_support/concurrency/latch.rb +0 -27
  274. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  275. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  276. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  277. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  278. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  279. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  280. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  281. data/lib/active_support/core_ext/logger.rb +0 -67
  282. data/lib/active_support/core_ext/marshal.rb +0 -21
  283. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  284. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  285. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  286. data/lib/active_support/core_ext/proc.rb +0 -17
  287. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  288. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  289. data/lib/active_support/core_ext/struct.rb +0 -6
  290. data/lib/active_support/core_ext/thread.rb +0 -79
  291. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  292. data/lib/active_support/file_watcher.rb +0 -36
  293. data/lib/active_support/json/variable.rb +0 -18
  294. data/lib/active_support/testing/pending.rb +0 -14
  295. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,11 +1,13 @@
1
- require 'active_support/core_ext/object/blank'
2
- require 'active_support/core_ext/object/try'
1
+ # frozen_string_literal: true
2
+
3
+ require "tzinfo"
4
+ require "concurrent/map"
3
5
 
4
6
  module ActiveSupport
5
7
  # The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
6
8
  # It allows us to do the following:
7
9
  #
8
- # * Limit the set of zones provided by TZInfo to a meaningful subset of 146
10
+ # * Limit the set of zones provided by TZInfo to a meaningful subset of 134
9
11
  # zones.
10
12
  # * Retrieve and display zones with a friendlier name
11
13
  # (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
@@ -21,19 +23,13 @@ module ActiveSupport
21
23
  # config.time_zone = 'Eastern Time (US & Canada)'
22
24
  # end
23
25
  #
24
- # Time.zone # => #<TimeZone:0x514834...>
26
+ # Time.zone # => #<ActiveSupport::TimeZone:0x514834...>
25
27
  # Time.zone.name # => "Eastern Time (US & Canada)"
26
28
  # Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00
27
- #
28
- # The version of TZInfo bundled with Active Support only includes the
29
- # definitions necessary to support the zones defined by the TimeZone class.
30
- # If you need to use zones that aren't defined by TimeZone, you'll need to
31
- # install the TZInfo gem (if a recent version of the gem is installed locally,
32
- # this will be used instead of the bundled version.)
33
29
  class TimeZone
34
30
  # Keys are Rails TimeZone names, values are TZInfo identifiers.
35
31
  MAPPING = {
36
- "International Date Line West" => "Pacific/Midway",
32
+ "International Date Line West" => "Etc/GMT+12",
37
33
  "Midway Island" => "Pacific/Midway",
38
34
  "American Samoa" => "Pacific/Pago_Pago",
39
35
  "Hawaii" => "Pacific/Honolulu",
@@ -64,6 +60,7 @@ module ActiveSupport
64
60
  "Buenos Aires" => "America/Argentina/Buenos_Aires",
65
61
  "Montevideo" => "America/Montevideo",
66
62
  "Georgetown" => "America/Guyana",
63
+ "Puerto Rico" => "America/Puerto_Rico",
67
64
  "Greenland" => "America/Godthab",
68
65
  "Mid-Atlantic" => "Atlantic/South_Georgia",
69
66
  "Azores" => "Atlantic/Azores",
@@ -90,7 +87,8 @@ module ActiveSupport
90
87
  "Paris" => "Europe/Paris",
91
88
  "Amsterdam" => "Europe/Amsterdam",
92
89
  "Berlin" => "Europe/Berlin",
93
- "Bern" => "Europe/Berlin",
90
+ "Bern" => "Europe/Zurich",
91
+ "Zurich" => "Europe/Zurich",
94
92
  "Rome" => "Europe/Rome",
95
93
  "Stockholm" => "Europe/Stockholm",
96
94
  "Vienna" => "Europe/Vienna",
@@ -109,9 +107,11 @@ module ActiveSupport
109
107
  "Jerusalem" => "Asia/Jerusalem",
110
108
  "Harare" => "Africa/Harare",
111
109
  "Pretoria" => "Africa/Johannesburg",
110
+ "Kaliningrad" => "Europe/Kaliningrad",
112
111
  "Moscow" => "Europe/Moscow",
113
112
  "St. Petersburg" => "Europe/Moscow",
114
- "Volgograd" => "Europe/Moscow",
113
+ "Volgograd" => "Europe/Volgograd",
114
+ "Samara" => "Europe/Samara",
115
115
  "Kuwait" => "Asia/Kuwait",
116
116
  "Riyadh" => "Asia/Riyadh",
117
117
  "Nairobi" => "Africa/Nairobi",
@@ -168,6 +168,7 @@ module ActiveSupport
168
168
  "Guam" => "Pacific/Guam",
169
169
  "Port Moresby" => "Pacific/Port_Moresby",
170
170
  "Magadan" => "Asia/Magadan",
171
+ "Srednekolymsk" => "Asia/Srednekolymsk",
171
172
  "Solomon Is." => "Pacific/Guadalcanal",
172
173
  "New Caledonia" => "Pacific/Noumea",
173
174
  "Fiji" => "Pacific/Fiji",
@@ -181,19 +182,112 @@ module ActiveSupport
181
182
  "Samoa" => "Pacific/Apia"
182
183
  }
183
184
 
184
- UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
185
- UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.sub(':', '')
185
+ UTC_OFFSET_WITH_COLON = "%s%02d:%02d" # :nodoc:
186
+ UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(":", "") # :nodoc:
187
+ private_constant :UTC_OFFSET_WITH_COLON, :UTC_OFFSET_WITHOUT_COLON
186
188
 
187
- # Assumes self represents an offset from UTC in seconds (as returned from
188
- # Time#utc_offset) and turns this into an +HH:MM formatted string.
189
- #
190
- # TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
191
- def self.seconds_to_utc_offset(seconds, colon = true)
192
- format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
193
- sign = (seconds < 0 ? '-' : '+')
194
- hours = seconds.abs / 3600
195
- minutes = (seconds.abs % 3600) / 60
196
- format % [sign, hours, minutes]
189
+ @lazy_zones_map = Concurrent::Map.new
190
+ @country_zones = Concurrent::Map.new
191
+
192
+ class << self
193
+ # Assumes self represents an offset from UTC in seconds (as returned from
194
+ # Time#utc_offset) and turns this into an +HH:MM formatted string.
195
+ #
196
+ # ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
197
+ def seconds_to_utc_offset(seconds, colon = true)
198
+ format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
199
+ sign = (seconds < 0 ? "-" : "+")
200
+ hours = seconds.abs / 3600
201
+ minutes = (seconds.abs % 3600) / 60
202
+ format % [sign, hours, minutes]
203
+ end
204
+
205
+ def find_tzinfo(name)
206
+ TZInfo::Timezone.get(MAPPING[name] || name)
207
+ end
208
+
209
+ alias_method :create, :new
210
+
211
+ # Returns a TimeZone instance with the given name, or +nil+ if no
212
+ # such TimeZone instance exists. (This exists to support the use of
213
+ # this class with the +composed_of+ macro.)
214
+ def new(name)
215
+ self[name]
216
+ end
217
+
218
+ # Returns an array of all TimeZone objects. There are multiple
219
+ # TimeZone objects per time zone, in many cases, to make it easier
220
+ # for users to find their own time zone.
221
+ def all
222
+ @zones ||= zones_map.values.sort
223
+ end
224
+
225
+ # Locate a specific time zone object. If the argument is a string, it
226
+ # is interpreted to mean the name of the timezone to locate. If it is a
227
+ # numeric value it is either the hour offset, or the second offset, of the
228
+ # timezone to find. (The first one with that offset will be returned.)
229
+ # Returns +nil+ if no such time zone is known to the system.
230
+ def [](arg)
231
+ case arg
232
+ when self
233
+ arg
234
+ when String
235
+ begin
236
+ @lazy_zones_map[arg] ||= create(arg)
237
+ rescue TZInfo::InvalidTimezoneIdentifier
238
+ nil
239
+ end
240
+ when TZInfo::Timezone
241
+ @lazy_zones_map[arg.name] ||= create(arg.name, nil, arg)
242
+ when Numeric, ActiveSupport::Duration
243
+ arg *= 3600 if arg.abs <= 13
244
+ all.find { |z| z.utc_offset == arg.to_i }
245
+ else
246
+ raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
247
+ end
248
+ end
249
+
250
+ # A convenience method for returning a collection of TimeZone objects
251
+ # for time zones in the USA.
252
+ def us_zones
253
+ country_zones(:us)
254
+ end
255
+
256
+ # A convenience method for returning a collection of TimeZone objects
257
+ # for time zones in the country specified by its ISO 3166-1 Alpha2 code.
258
+ def country_zones(country_code)
259
+ code = country_code.to_s.upcase
260
+ @country_zones[code] ||= load_country_zones(code)
261
+ end
262
+
263
+ def clear # :nodoc:
264
+ @lazy_zones_map = Concurrent::Map.new
265
+ @country_zones = Concurrent::Map.new
266
+ @zones = nil
267
+ @zones_map = nil
268
+ end
269
+
270
+ private
271
+ def load_country_zones(code)
272
+ country = TZInfo::Country.get(code)
273
+ country.zone_identifiers.flat_map do |tz_id|
274
+ if MAPPING.value?(tz_id)
275
+ MAPPING.inject([]) do |memo, (key, value)|
276
+ memo << self[key] if value == tz_id
277
+ memo
278
+ end
279
+ else
280
+ create(tz_id, nil, TZInfo::Timezone.get(tz_id))
281
+ end
282
+ end.sort!
283
+ end
284
+
285
+ def zones_map
286
+ @zones_map ||= MAPPING.each_with_object({}) do |(name, _), zones|
287
+ timezone = self[name]
288
+ zones[name] = timezone if timezone
289
+ end
290
+ end
197
291
  end
198
292
 
199
293
  include Comparable
@@ -205,27 +299,23 @@ module ActiveSupport
205
299
  # (GMT). Seconds were chosen as the offset unit because that is the unit
206
300
  # that Ruby uses to represent time zone offsets (see Time#utc_offset).
207
301
  def initialize(name, utc_offset = nil, tzinfo = nil)
208
- self.class.send(:require_tzinfo)
209
-
210
302
  @name = name
211
303
  @utc_offset = utc_offset
212
304
  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
213
- @current_period = nil
214
305
  end
215
306
 
216
307
  # Returns the offset of this time zone from UTC in seconds.
217
308
  def utc_offset
218
- if @utc_offset
219
- @utc_offset
220
- else
221
- @current_period ||= tzinfo.try(:current_period)
222
- @current_period.try(:utc_offset)
223
- end
309
+ @utc_offset || tzinfo&.current_period&.base_utc_offset
224
310
  end
225
311
 
226
- # Returns the offset of this time zone as a formatted string, of the
227
- # format "+HH:MM".
228
- def formatted_offset(colon=true, alternate_utc_string = nil)
312
+ # Returns a formatted string of the offset from UTC, or an alternative
313
+ # string if the time zone is already UTC.
314
+ #
315
+ # zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
316
+ # zone.formatted_offset # => "-06:00"
317
+ # zone.formatted_offset(false) # => "-0600"
318
+ def formatted_offset(colon = true, alternate_utc_string = nil)
229
319
  utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
230
320
  end
231
321
 
@@ -244,6 +334,13 @@ module ActiveSupport
244
334
  re === name || re === MAPPING[name]
245
335
  end
246
336
 
337
+ # Compare #name and TZInfo identifier to a supplied regexp, returning +true+
338
+ # if a match is found.
339
+ def match?(re)
340
+ (re == name) || (re == MAPPING[name]) ||
341
+ ((Regexp === re) && (re.match?(name) || re.match?(MAPPING[name])))
342
+ end
343
+
247
344
  # Returns a textual representation of this time zone.
248
345
  def to_s
249
346
  "(GMT#{formatted_offset}) #{name}"
@@ -265,29 +362,51 @@ module ActiveSupport
265
362
  # Time.zone = 'Hawaii' # => "Hawaii"
266
363
  # Time.utc(2000).to_f # => 946684800.0
267
364
  # Time.zone.at(946684800.0) # => Fri, 31 Dec 1999 14:00:00 HST -10:00
268
- def at(secs)
269
- Time.at(secs).utc.in_time_zone(self)
365
+ #
366
+ # A second argument can be supplied to specify sub-second precision.
367
+ #
368
+ # Time.zone = 'Hawaii' # => "Hawaii"
369
+ # Time.at(946684800, 123456.789).nsec # => 123456789
370
+ def at(*args)
371
+ Time.at(*args).utc.in_time_zone(self)
270
372
  end
271
373
 
272
374
  # Method for creating new ActiveSupport::TimeWithZone instance in time zone
273
- # of +self+ from parsed string.
375
+ # of +self+ from an ISO 8601 string.
274
376
  #
275
- # Time.zone = 'Hawaii' # => "Hawaii"
276
- # Time.zone.parse('1999-12-31 14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
377
+ # Time.zone = 'Hawaii' # => "Hawaii"
378
+ # Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
277
379
  #
278
- # If upper components are missing from the string, they are supplied from
279
- # TimeZone#now:
380
+ # If the time components are missing then they will be set to zero.
280
381
  #
281
- # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
282
- # Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
283
- def parse(str, now=now())
284
- parts = Date._parse(str, false)
285
- return if parts.empty?
382
+ # Time.zone = 'Hawaii' # => "Hawaii"
383
+ # Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
384
+ #
385
+ # If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
386
+ # which usually returns +nil+ when given an invalid date string.
387
+ def iso8601(str)
388
+ # Historically `Date._iso8601(nil)` returns `{}`, but in the `date` gem versions `3.2.1`, `3.1.2`, `3.0.2`,
389
+ # and `2.0.1`, `Date._iso8601(nil)` raises `TypeError` https://github.com/ruby/date/issues/39
390
+ # Future `date` releases are expected to revert back to the original behavior.
391
+ raise ArgumentError, "invalid date" if str.nil?
392
+
393
+ parts = Date._iso8601(str)
394
+
395
+ year = parts.fetch(:year)
396
+
397
+ if parts.key?(:yday)
398
+ ordinal_date = Date.ordinal(year, parts.fetch(:yday))
399
+ month = ordinal_date.month
400
+ day = ordinal_date.day
401
+ else
402
+ month = parts.fetch(:mon)
403
+ day = parts.fetch(:mday)
404
+ end
286
405
 
287
406
  time = Time.new(
288
- parts.fetch(:year, now.year),
289
- parts.fetch(:mon, now.month),
290
- parts.fetch(:mday, now.day),
407
+ year,
408
+ month,
409
+ day,
291
410
  parts.fetch(:hour, 0),
292
411
  parts.fetch(:min, 0),
293
412
  parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
@@ -299,6 +418,85 @@ module ActiveSupport
299
418
  else
300
419
  TimeWithZone.new(nil, self, time)
301
420
  end
421
+
422
+ rescue Date::Error, KeyError
423
+ raise ArgumentError, "invalid date"
424
+ end
425
+
426
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
427
+ # of +self+ from parsed string.
428
+ #
429
+ # Time.zone = 'Hawaii' # => "Hawaii"
430
+ # Time.zone.parse('1999-12-31 14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
431
+ #
432
+ # If upper components are missing from the string, they are supplied from
433
+ # TimeZone#now:
434
+ #
435
+ # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
436
+ # Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
437
+ #
438
+ # However, if the date component is not provided, but any other upper
439
+ # components are supplied, then the day of the month defaults to 1:
440
+ #
441
+ # Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
442
+ #
443
+ # If the string is invalid then an +ArgumentError+ could be raised.
444
+ def parse(str, now = now())
445
+ parts_to_time(Date._parse(str, false), now)
446
+ end
447
+
448
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
449
+ # of +self+ from an RFC 3339 string.
450
+ #
451
+ # Time.zone = 'Hawaii' # => "Hawaii"
452
+ # Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
453
+ #
454
+ # If the time or zone components are missing then an +ArgumentError+ will
455
+ # be raised. This is much stricter than either +parse+ or +iso8601+ which
456
+ # allow for missing components.
457
+ #
458
+ # Time.zone = 'Hawaii' # => "Hawaii"
459
+ # Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
460
+ def rfc3339(str)
461
+ parts = Date._rfc3339(str)
462
+
463
+ raise ArgumentError, "invalid date" if parts.empty?
464
+
465
+ time = Time.new(
466
+ parts.fetch(:year),
467
+ parts.fetch(:mon),
468
+ parts.fetch(:mday),
469
+ parts.fetch(:hour),
470
+ parts.fetch(:min),
471
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
472
+ parts.fetch(:offset)
473
+ )
474
+
475
+ TimeWithZone.new(time.utc, self)
476
+ end
477
+
478
+ # Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
479
+ #
480
+ # Assumes that +str+ is a time in the time zone +self+,
481
+ # unless +format+ includes an explicit time zone.
482
+ # (This is the same behavior as +parse+.)
483
+ # In either case, the returned TimeWithZone has the timezone of +self+.
484
+ #
485
+ # Time.zone = 'Hawaii' # => "Hawaii"
486
+ # 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
487
+ #
488
+ # If upper components are missing from the string, they are supplied from
489
+ # TimeZone#now:
490
+ #
491
+ # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
492
+ # Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
493
+ #
494
+ # However, if the date component is not provided, but any other upper
495
+ # components are supplied, then the day of the month defaults to 1:
496
+ #
497
+ # Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
498
+ def strptime(str, format, now = now())
499
+ parts_to_time(DateTime._strptime(str, format), now)
302
500
  end
303
501
 
304
502
  # Returns an ActiveSupport::TimeWithZone instance representing the current
@@ -310,21 +508,38 @@ module ActiveSupport
310
508
  time_now.utc.in_time_zone(self)
311
509
  end
312
510
 
313
- # Return the current date in this time zone.
511
+ # Returns the current date in this time zone.
314
512
  def today
315
513
  tzinfo.now.to_date
316
514
  end
317
515
 
516
+ # Returns the next date in this time zone.
517
+ def tomorrow
518
+ today + 1
519
+ end
520
+
521
+ # Returns the previous date in this time zone.
522
+ def yesterday
523
+ today - 1
524
+ end
525
+
318
526
  # Adjust the given time to the simultaneous time in the time zone
319
- # represented by +self+. Returns a Time.utc() instance -- if you want an
320
- # ActiveSupport::TimeWithZone instance, use Time#in_time_zone() instead.
527
+ # represented by +self+. Returns a local time with the appropriate offset
528
+ # -- if you want an ActiveSupport::TimeWithZone instance, use
529
+ # Time#in_time_zone() instead.
530
+ #
531
+ # As of tzinfo 2, utc_to_local returns a Time with a non-zero utc_offset.
532
+ # See the +utc_to_local_returns_utc_offset_times+ config for more info.
321
533
  def utc_to_local(time)
322
- tzinfo.utc_to_local(time)
534
+ tzinfo.utc_to_local(time).yield_self do |t|
535
+ ActiveSupport.utc_to_local_returns_utc_offset_times ?
536
+ t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction * 1_000_000)
537
+ end
323
538
  end
324
539
 
325
540
  # Adjust the given time to the simultaneous time in UTC. Returns a
326
541
  # Time.utc() instance.
327
- def local_to_utc(time, dst=true)
542
+ def local_to_utc(time, dst = true)
328
543
  tzinfo.local_to_utc(time, dst)
329
544
  end
330
545
 
@@ -336,95 +551,51 @@ module ActiveSupport
336
551
 
337
552
  # Available so that TimeZone instances respond like TZInfo::Timezone
338
553
  # instances.
339
- def period_for_local(time, dst=true)
340
- tzinfo.period_for_local(time, dst)
554
+ def period_for_local(time, dst = true)
555
+ tzinfo.period_for_local(time, dst) { |periods| periods.last }
341
556
  end
342
557
 
343
- def self.find_tzinfo(name)
344
- TZInfo::TimezoneProxy.new(MAPPING[name] || name)
558
+ def periods_for_local(time) # :nodoc:
559
+ tzinfo.periods_for_local(time)
345
560
  end
346
561
 
347
- class << self
348
- alias_method :create, :new
349
-
350
- # Return a TimeZone instance with the given name, or +nil+ if no
351
- # such TimeZone instance exists. (This exists to support the use of
352
- # this class with the +composed_of+ macro.)
353
- def new(name)
354
- self[name]
355
- end
356
-
357
- # Return an array of all TimeZone objects. There are multiple
358
- # TimeZone objects per time zone, in many cases, to make it easier
359
- # for users to find their own time zone.
360
- def all
361
- @zones ||= zones_map.values.sort
362
- end
562
+ def init_with(coder) # :nodoc:
563
+ initialize(coder["name"])
564
+ end
363
565
 
364
- def zones_map
365
- @zones_map ||= begin
366
- new_zones_names = MAPPING.keys - lazy_zones_map.keys
367
- new_zones = Hash[new_zones_names.map { |place| [place, create(place)] }]
566
+ def encode_with(coder) # :nodoc:
567
+ coder.tag = "!ruby/object:#{self.class}"
568
+ coder.map = { "name" => tzinfo.name }
569
+ end
368
570
 
369
- lazy_zones_map.merge(new_zones)
571
+ private
572
+ def parts_to_time(parts, now)
573
+ raise ArgumentError, "invalid date" if parts.nil?
574
+ return if parts.empty?
575
+
576
+ if parts[:seconds]
577
+ time = Time.at(parts[:seconds])
578
+ else
579
+ time = Time.new(
580
+ parts.fetch(:year, now.year),
581
+ parts.fetch(:mon, now.month),
582
+ parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
583
+ parts.fetch(:hour, 0),
584
+ parts.fetch(:min, 0),
585
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
586
+ parts.fetch(:offset, 0)
587
+ )
370
588
  end
371
- end
372
589
 
373
- # Locate a specific time zone object. If the argument is a string, it
374
- # is interpreted to mean the name of the timezone to locate. If it is a
375
- # numeric value it is either the hour offset, or the second offset, of the
376
- # timezone to find. (The first one with that offset will be returned.)
377
- # Returns +nil+ if no such time zone is known to the system.
378
- def [](arg)
379
- case arg
380
- when String
381
- begin
382
- lazy_zones_map[arg] ||= lookup(arg).tap { |tz| tz.utc_offset }
383
- rescue TZInfo::InvalidTimezoneIdentifier
384
- nil
385
- end
386
- when Numeric, ActiveSupport::Duration
387
- arg *= 3600 if arg.abs <= 13
388
- all.find { |z| z.utc_offset == arg.to_i }
389
- else
390
- raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
590
+ if parts[:offset] || parts[:seconds]
591
+ TimeWithZone.new(time.utc, self)
592
+ else
593
+ TimeWithZone.new(nil, self, time)
391
594
  end
392
595
  end
393
596
 
394
- # A convenience method for returning a collection of TimeZone objects
395
- # for time zones in the USA.
396
- def us_zones
397
- @us_zones ||= all.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ }
597
+ def time_now
598
+ Time.now
398
599
  end
399
-
400
- protected
401
-
402
- def require_tzinfo
403
- require 'tzinfo' unless defined?(::TZInfo)
404
- rescue LoadError
405
- $stderr.puts "You don't have tzinfo installed in your application. Please add it to your Gemfile and run bundle install"
406
- raise
407
- end
408
-
409
- private
410
-
411
- def lookup(name)
412
- (tzinfo = find_tzinfo(name)) && create(tzinfo.name.freeze)
413
- end
414
-
415
- def lazy_zones_map
416
- require_tzinfo
417
-
418
- @lazy_zones_map ||= Hash.new do |hash, place|
419
- hash[place] = create(place) if MAPPING.has_key?(place)
420
- end
421
- end
422
- end
423
-
424
- private
425
-
426
- def time_now
427
- Time.now
428
- end
429
600
  end
430
601
  end
@@ -1,11 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "gem_version"
4
+
1
5
  module ActiveSupport
2
- # Returns the version of the currently loaded ActiveSupport as a Gem::Version
6
+ # Returns the version of the currently loaded ActiveSupport as a <tt>Gem::Version</tt>
3
7
  def self.version
4
- Gem::Version.new "4.0.12"
5
- end
6
-
7
- module VERSION #:nodoc:
8
- MAJOR, MINOR, TINY, PRE = ActiveSupport.version.segments
9
- STRING = ActiveSupport.version.to_s
8
+ gem_version
10
9
  end
11
10
  end