activesupport 4.0.13 → 5.2.5

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 (264) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +412 -444
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +8 -4
  5. data/lib/active_support/all.rb +5 -3
  6. data/lib/active_support/array_inquirer.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +14 -12
  8. data/lib/active_support/benchmarkable.rb +6 -14
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +67 -51
  11. data/lib/active_support/cache/mem_cache_store.rb +95 -97
  12. data/lib/active_support/cache/memory_store.rb +28 -30
  13. data/lib/active_support/cache/null_store.rb +7 -8
  14. data/lib/active_support/cache/redis_cache_store.rb +466 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +70 -56
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  17. data/lib/active_support/cache.rb +331 -206
  18. data/lib/active_support/callbacks.rb +697 -426
  19. data/lib/active_support/concern.rb +32 -10
  20. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  21. data/lib/active_support/concurrency/share_lock.rb +227 -0
  22. data/lib/active_support/configurable.rb +8 -5
  23. data/lib/active_support/core_ext/array/access.rb +39 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +24 -35
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +23 -13
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -5
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -7
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -23
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  37. data/lib/active_support/core_ext/class.rb +4 -4
  38. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  39. data/lib/active_support/core_ext/date/blank.rb +14 -0
  40. data/lib/active_support/core_ext/date/calculations.rb +21 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +32 -22
  42. data/lib/active_support/core_ext/date/zones.rb +5 -34
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +199 -57
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  47. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  48. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  49. data/lib/active_support/core_ext/date_time/calculations.rb +78 -37
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  51. data/lib/active_support/core_ext/date_time/conversions.rb +19 -13
  52. data/lib/active_support/core_ext/date_time.rb +7 -4
  53. data/lib/active_support/core_ext/digest/uuid.rb +53 -0
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +113 -29
  56. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/hash/compact.rb +29 -0
  59. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +12 -3
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +50 -38
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +12 -6
  66. data/lib/active_support/core_ext/hash/transform_values.rb +32 -0
  67. data/lib/active_support/core_ext/hash.rb +11 -8
  68. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  69. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  70. data/lib/active_support/core_ext/integer/time.rb +11 -33
  71. data/lib/active_support/core_ext/integer.rb +5 -3
  72. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  74. data/lib/active_support/core_ext/kernel/reporting.rb +5 -74
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -4
  77. data/lib/active_support/core_ext/load_error.rb +5 -21
  78. data/lib/active_support/core_ext/marshal.rb +13 -10
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +170 -21
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +134 -0
  85. data/lib/active_support/core_ext/module/delegation.rb +135 -45
  86. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -25
  88. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  89. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  90. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  91. data/lib/active_support/core_ext/module.rb +14 -10
  92. data/lib/active_support/core_ext/name_error.rb +22 -2
  93. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  94. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  97. data/lib/active_support/core_ext/numeric.rb +6 -3
  98. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  99. data/lib/active_support/core_ext/object/blank.rb +70 -19
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  102. data/lib/active_support/core_ext/object/duplicable.rb +100 -34
  103. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +227 -0
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  108. data/lib/active_support/core_ext/object/try.rb +94 -24
  109. data/lib/active_support/core_ext/object/with_options.rb +45 -5
  110. data/lib/active_support/core_ext/object.rb +14 -12
  111. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  112. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  113. data/lib/active_support/core_ext/range/each.rb +19 -17
  114. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  115. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  116. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  117. data/lib/active_support/core_ext/range.rb +7 -4
  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/access.rb +41 -39
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +17 -13
  123. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  124. data/lib/active_support/core_ext/string/filters.rb +55 -6
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  127. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  128. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  129. data/lib/active_support/core_ext/string/output_safety.rb +114 -54
  130. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  131. data/lib/active_support/core_ext/string/strip.rb +4 -5
  132. data/lib/active_support/core_ext/string/zones.rb +4 -1
  133. data/lib/active_support/core_ext/string.rb +15 -13
  134. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  135. data/lib/active_support/core_ext/time/calculations.rb +123 -110
  136. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  137. data/lib/active_support/core_ext/time/conversions.rb +23 -14
  138. data/lib/active_support/core_ext/time/zones.rb +42 -26
  139. data/lib/active_support/core_ext/time.rb +7 -5
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -2
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies/autoload.rb +3 -1
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/dependencies.rb +196 -166
  146. data/lib/active_support/deprecation/behaviors.rb +48 -15
  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 +66 -20
  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/deprecation.rb +14 -11
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  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/duration.rb +354 -34
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +205 -0
  161. data/lib/active_support/execution_wrapper.rb +128 -0
  162. data/lib/active_support/executor.rb +8 -0
  163. data/lib/active_support/file_update_checker.rb +63 -37
  164. data/lib/active_support/gem_version.rb +17 -0
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +158 -35
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +38 -20
  169. data/lib/active_support/inflections.rb +19 -12
  170. data/lib/active_support/inflector/inflections.rb +79 -30
  171. data/lib/active_support/inflector/methods.rb +197 -129
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/inflector.rb +7 -5
  174. data/lib/active_support/json/decoding.rb +21 -25
  175. data/lib/active_support/json/encoding.rb +84 -292
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +26 -28
  178. data/lib/active_support/lazy_load_hooks.rb +51 -21
  179. data/lib/active_support/locale/en.yml +2 -0
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/log_subscriber.rb +13 -10
  182. data/lib/active_support/logger.rb +54 -3
  183. data/lib/active_support/logger_silence.rb +12 -7
  184. data/lib/active_support/logger_thread_safe_level.rb +34 -0
  185. data/lib/active_support/message_encryptor.rb +173 -50
  186. data/lib/active_support/message_verifier.rb +159 -22
  187. data/lib/active_support/messages/metadata.rb +71 -0
  188. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  189. data/lib/active_support/messages/rotator.rb +56 -0
  190. data/lib/active_support/multibyte/chars.rb +38 -26
  191. data/lib/active_support/multibyte/unicode.rb +138 -146
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +23 -16
  194. data/lib/active_support/notifications/instrumenter.rb +29 -8
  195. data/lib/active_support/notifications.rb +22 -13
  196. data/lib/active_support/number_helper/number_converter.rb +184 -0
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +29 -0
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +59 -0
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +14 -0
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +54 -0
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/number_helper.rb +125 -391
  206. data/lib/active_support/option_merger.rb +3 -1
  207. data/lib/active_support/ordered_hash.rb +6 -4
  208. data/lib/active_support/ordered_options.rb +31 -5
  209. data/lib/active_support/per_thread_registry.rb +19 -11
  210. data/lib/active_support/proxy_object.rb +2 -0
  211. data/lib/active_support/rails.rb +16 -8
  212. data/lib/active_support/railtie.rb +43 -9
  213. data/lib/active_support/reloader.rb +131 -0
  214. data/lib/active_support/rescuable.rb +108 -53
  215. data/lib/active_support/security_utils.rb +31 -0
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +54 -17
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +42 -37
  220. data/lib/active_support/testing/assertions.rb +126 -39
  221. data/lib/active_support/testing/autorun.rb +5 -3
  222. data/lib/active_support/testing/constant_lookup.rb +3 -6
  223. data/lib/active_support/testing/declarative.rb +10 -22
  224. data/lib/active_support/testing/deprecation.rb +14 -10
  225. data/lib/active_support/testing/file_fixtures.rb +36 -0
  226. data/lib/active_support/testing/isolation.rb +55 -86
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +5 -3
  231. data/lib/active_support/testing/time_helpers.rb +200 -0
  232. data/lib/active_support/time.rb +13 -13
  233. data/lib/active_support/time_with_zone.rb +223 -73
  234. data/lib/active_support/values/time_zone.rb +261 -126
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +6 -7
  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. data/lib/active_support/xml_mini.rb +69 -51
  244. data/lib/active_support.rb +29 -3
  245. metadata +84 -54
  246. data/lib/active_support/basic_object.rb +0 -11
  247. data/lib/active_support/buffered_logger.rb +0 -21
  248. data/lib/active_support/concurrency/latch.rb +0 -27
  249. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  250. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  251. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  252. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  253. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  254. data/lib/active_support/core_ext/logger.rb +0 -67
  255. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  256. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  257. data/lib/active_support/core_ext/proc.rb +0 -17
  258. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  259. data/lib/active_support/core_ext/struct.rb +0 -6
  260. data/lib/active_support/core_ext/thread.rb +0 -79
  261. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  262. data/lib/active_support/file_watcher.rb +0 -36
  263. data/lib/active_support/json/variable.rb +0 -18
  264. data/lib/active_support/testing/pending.rb +0 -14
@@ -1,11 +1,14 @@
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"
5
+ require "active_support/core_ext/object/blank"
3
6
 
4
7
  module ActiveSupport
5
8
  # The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
6
9
  # It allows us to do the following:
7
10
  #
8
- # * 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
9
12
  # zones.
10
13
  # * Retrieve and display zones with a friendlier name
11
14
  # (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
@@ -21,19 +24,13 @@ module ActiveSupport
21
24
  # config.time_zone = 'Eastern Time (US & Canada)'
22
25
  # end
23
26
  #
24
- # Time.zone # => #<TimeZone:0x514834...>
27
+ # Time.zone # => #<ActiveSupport::TimeZone:0x514834...>
25
28
  # Time.zone.name # => "Eastern Time (US & Canada)"
26
29
  # 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
30
  class TimeZone
34
31
  # Keys are Rails TimeZone names, values are TZInfo identifiers.
35
32
  MAPPING = {
36
- "International Date Line West" => "Pacific/Midway",
33
+ "International Date Line West" => "Etc/GMT+12",
37
34
  "Midway Island" => "Pacific/Midway",
38
35
  "American Samoa" => "Pacific/Pago_Pago",
39
36
  "Hawaii" => "Pacific/Honolulu",
@@ -64,6 +61,7 @@ module ActiveSupport
64
61
  "Buenos Aires" => "America/Argentina/Buenos_Aires",
65
62
  "Montevideo" => "America/Montevideo",
66
63
  "Georgetown" => "America/Guyana",
64
+ "Puerto Rico" => "America/Puerto_Rico",
67
65
  "Greenland" => "America/Godthab",
68
66
  "Mid-Atlantic" => "Atlantic/South_Georgia",
69
67
  "Azores" => "Atlantic/Azores",
@@ -90,7 +88,8 @@ module ActiveSupport
90
88
  "Paris" => "Europe/Paris",
91
89
  "Amsterdam" => "Europe/Amsterdam",
92
90
  "Berlin" => "Europe/Berlin",
93
- "Bern" => "Europe/Berlin",
91
+ "Bern" => "Europe/Zurich",
92
+ "Zurich" => "Europe/Zurich",
94
93
  "Rome" => "Europe/Rome",
95
94
  "Stockholm" => "Europe/Stockholm",
96
95
  "Vienna" => "Europe/Vienna",
@@ -109,9 +108,11 @@ module ActiveSupport
109
108
  "Jerusalem" => "Asia/Jerusalem",
110
109
  "Harare" => "Africa/Harare",
111
110
  "Pretoria" => "Africa/Johannesburg",
111
+ "Kaliningrad" => "Europe/Kaliningrad",
112
112
  "Moscow" => "Europe/Moscow",
113
113
  "St. Petersburg" => "Europe/Moscow",
114
- "Volgograd" => "Europe/Moscow",
114
+ "Volgograd" => "Europe/Volgograd",
115
+ "Samara" => "Europe/Samara",
115
116
  "Kuwait" => "Asia/Kuwait",
116
117
  "Riyadh" => "Asia/Riyadh",
117
118
  "Nairobi" => "Africa/Nairobi",
@@ -168,6 +169,7 @@ module ActiveSupport
168
169
  "Guam" => "Pacific/Guam",
169
170
  "Port Moresby" => "Pacific/Port_Moresby",
170
171
  "Magadan" => "Asia/Magadan",
172
+ "Srednekolymsk" => "Asia/Srednekolymsk",
171
173
  "Solomon Is." => "Pacific/Guadalcanal",
172
174
  "New Caledonia" => "Pacific/Noumea",
173
175
  "Fiji" => "Pacific/Fiji",
@@ -181,19 +183,107 @@ module ActiveSupport
181
183
  "Samoa" => "Pacific/Apia"
182
184
  }
183
185
 
184
- UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
185
- UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.sub(':', '')
186
+ UTC_OFFSET_WITH_COLON = "%s%02d:%02d"
187
+ UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(":", "")
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.new(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 String
233
+ begin
234
+ @lazy_zones_map[arg] ||= create(arg)
235
+ rescue TZInfo::InvalidTimezoneIdentifier
236
+ nil
237
+ end
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}"
243
+ end
244
+ end
245
+
246
+ # A convenience method for returning a collection of TimeZone objects
247
+ # for time zones in the USA.
248
+ def us_zones
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
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
+ timezone = self[name]
284
+ zones[name] = timezone if timezone
285
+ end
286
+ end
197
287
  end
198
288
 
199
289
  include Comparable
@@ -205,12 +295,9 @@ module ActiveSupport
205
295
  # (GMT). Seconds were chosen as the offset unit because that is the unit
206
296
  # that Ruby uses to represent time zone offsets (see Time#utc_offset).
207
297
  def initialize(name, utc_offset = nil, tzinfo = nil)
208
- self.class.send(:require_tzinfo)
209
-
210
298
  @name = name
211
299
  @utc_offset = utc_offset
212
300
  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
213
- @current_period = nil
214
301
  end
215
302
 
216
303
  # Returns the offset of this time zone from UTC in seconds.
@@ -218,14 +305,17 @@ module ActiveSupport
218
305
  if @utc_offset
219
306
  @utc_offset
220
307
  else
221
- @current_period ||= tzinfo.try(:current_period)
222
- @current_period.try(:utc_offset)
308
+ tzinfo.current_period.utc_offset if tzinfo && tzinfo.current_period
223
309
  end
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
 
@@ -270,24 +360,27 @@ module ActiveSupport
270
360
  end
271
361
 
272
362
  # Method for creating new ActiveSupport::TimeWithZone instance in time zone
273
- # of +self+ from parsed string.
363
+ # of +self+ from an ISO 8601 string.
274
364
  #
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
365
+ # Time.zone = 'Hawaii' # => "Hawaii"
366
+ # Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
277
367
  #
278
- # If upper components are missing from the string, they are supplied from
279
- # TimeZone#now:
368
+ # If the time components are missing then they will be set to zero.
280
369
  #
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?
370
+ # Time.zone = 'Hawaii' # => "Hawaii"
371
+ # Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
372
+ #
373
+ # If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
374
+ # which usually returns +nil+ when given an invalid date string.
375
+ def iso8601(str)
376
+ parts = Date._iso8601(str)
377
+
378
+ raise ArgumentError, "invalid date" if parts.empty?
286
379
 
287
380
  time = Time.new(
288
- parts.fetch(:year, now.year),
289
- parts.fetch(:mon, now.month),
290
- parts.fetch(:mday, now.day),
381
+ parts.fetch(:year),
382
+ parts.fetch(:mon),
383
+ parts.fetch(:mday),
291
384
  parts.fetch(:hour, 0),
292
385
  parts.fetch(:min, 0),
293
386
  parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
@@ -301,6 +394,82 @@ module ActiveSupport
301
394
  end
302
395
  end
303
396
 
397
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
398
+ # of +self+ from parsed string.
399
+ #
400
+ # Time.zone = 'Hawaii' # => "Hawaii"
401
+ # Time.zone.parse('1999-12-31 14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
402
+ #
403
+ # If upper components are missing from the string, they are supplied from
404
+ # TimeZone#now:
405
+ #
406
+ # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
407
+ # Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
408
+ #
409
+ # However, if the date component is not provided, but any other upper
410
+ # components are supplied, then the day of the month defaults to 1:
411
+ #
412
+ # Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
413
+ #
414
+ # If the string is invalid then an +ArgumentError+ could be raised.
415
+ def parse(str, now = now())
416
+ parts_to_time(Date._parse(str, false), now)
417
+ end
418
+
419
+ # Method for creating new ActiveSupport::TimeWithZone instance in time zone
420
+ # of +self+ from an RFC 3339 string.
421
+ #
422
+ # Time.zone = 'Hawaii' # => "Hawaii"
423
+ # Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
424
+ #
425
+ # If the time or zone components are missing then an +ArgumentError+ will
426
+ # be raised. This is much stricter than either +parse+ or +iso8601+ which
427
+ # allow for missing components.
428
+ #
429
+ # Time.zone = 'Hawaii' # => "Hawaii"
430
+ # Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
431
+ def rfc3339(str)
432
+ parts = Date._rfc3339(str)
433
+
434
+ raise ArgumentError, "invalid date" if parts.empty?
435
+
436
+ time = Time.new(
437
+ parts.fetch(:year),
438
+ parts.fetch(:mon),
439
+ parts.fetch(:mday),
440
+ parts.fetch(:hour),
441
+ parts.fetch(:min),
442
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
443
+ parts.fetch(:offset)
444
+ )
445
+
446
+ TimeWithZone.new(time.utc, self)
447
+ end
448
+
449
+ # Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
450
+ #
451
+ # Assumes that +str+ is a time in the time zone +self+,
452
+ # unless +format+ includes an explicit time zone.
453
+ # (This is the same behavior as +parse+.)
454
+ # In either case, the returned TimeWithZone has the timezone of +self+.
455
+ #
456
+ # Time.zone = 'Hawaii' # => "Hawaii"
457
+ # 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
458
+ #
459
+ # If upper components are missing from the string, they are supplied from
460
+ # TimeZone#now:
461
+ #
462
+ # Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
463
+ # Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
464
+ #
465
+ # However, if the date component is not provided, but any other upper
466
+ # components are supplied, then the day of the month defaults to 1:
467
+ #
468
+ # Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
469
+ def strptime(str, format, now = now())
470
+ parts_to_time(DateTime._strptime(str, format), now)
471
+ end
472
+
304
473
  # Returns an ActiveSupport::TimeWithZone instance representing the current
305
474
  # time in the time zone represented by +self+.
306
475
  #
@@ -310,11 +479,21 @@ module ActiveSupport
310
479
  time_now.utc.in_time_zone(self)
311
480
  end
312
481
 
313
- # Return the current date in this time zone.
482
+ # Returns the current date in this time zone.
314
483
  def today
315
484
  tzinfo.now.to_date
316
485
  end
317
486
 
487
+ # Returns the next date in this time zone.
488
+ def tomorrow
489
+ today + 1
490
+ end
491
+
492
+ # Returns the previous date in this time zone.
493
+ def yesterday
494
+ today - 1
495
+ end
496
+
318
497
  # Adjust the given time to the simultaneous time in the time zone
319
498
  # represented by +self+. Returns a Time.utc() instance -- if you want an
320
499
  # ActiveSupport::TimeWithZone instance, use Time#in_time_zone() instead.
@@ -324,7 +503,7 @@ module ActiveSupport
324
503
 
325
504
  # Adjust the given time to the simultaneous time in UTC. Returns a
326
505
  # Time.utc() instance.
327
- def local_to_utc(time, dst=true)
506
+ def local_to_utc(time, dst = true)
328
507
  tzinfo.local_to_utc(time, dst)
329
508
  end
330
509
 
@@ -336,95 +515,51 @@ module ActiveSupport
336
515
 
337
516
  # Available so that TimeZone instances respond like TZInfo::Timezone
338
517
  # instances.
339
- def period_for_local(time, dst=true)
340
- tzinfo.period_for_local(time, dst)
518
+ def period_for_local(time, dst = true)
519
+ tzinfo.period_for_local(time, dst) { |periods| periods.last }
341
520
  end
342
521
 
343
- def self.find_tzinfo(name)
344
- TZInfo::TimezoneProxy.new(MAPPING[name] || name)
522
+ def periods_for_local(time) #:nodoc:
523
+ tzinfo.periods_for_local(time)
345
524
  end
346
525
 
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
526
+ def init_with(coder) #:nodoc:
527
+ initialize(coder["name"])
528
+ end
363
529
 
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)] }]
530
+ def encode_with(coder) #:nodoc:
531
+ coder.tag = "!ruby/object:#{self.class}"
532
+ coder.map = { "name" => tzinfo.name }
533
+ end
368
534
 
369
- lazy_zones_map.merge(new_zones)
535
+ private
536
+ def parts_to_time(parts, now)
537
+ raise ArgumentError, "invalid date" if parts.nil?
538
+ return if parts.empty?
539
+
540
+ if parts[:seconds]
541
+ time = Time.at(parts[:seconds])
542
+ else
543
+ time = Time.new(
544
+ parts.fetch(:year, now.year),
545
+ parts.fetch(:mon, now.month),
546
+ parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
547
+ parts.fetch(:hour, 0),
548
+ parts.fetch(:min, 0),
549
+ parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
550
+ parts.fetch(:offset, 0)
551
+ )
370
552
  end
371
- end
372
553
 
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}"
554
+ if parts[:offset] || parts[:seconds]
555
+ TimeWithZone.new(time.utc, self)
556
+ else
557
+ TimeWithZone.new(nil, self, time)
391
558
  end
392
559
  end
393
560
 
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/ }
561
+ def time_now
562
+ Time.now
398
563
  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
564
  end
430
565
  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.13"
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