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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  alias_method :starts_with?, :start_with?
3
5
  alias_method :ends_with?, :end_with?
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/object/try'
1
+ # frozen_string_literal: true
2
2
 
3
3
  class String
4
4
  # Strips indentation in heredocs.
@@ -17,10 +17,9 @@ class String
17
17
  #
18
18
  # the user would see the usage message aligned against the left margin.
19
19
  #
20
- # Technically, it looks for the least indented line in the whole string, and removes
21
- # that amount of leading whitespace.
20
+ # Technically, it looks for the least indented non-empty line
21
+ # in the whole string, and removes that amount of leading whitespace.
22
22
  def strip_heredoc
23
- indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
24
- gsub(/^[ \t]{#{indent}}/, '')
23
+ gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
25
24
  end
26
25
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/string/conversions'
2
- require 'active_support/core_ext/time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/conversions"
4
+ require "active_support/core_ext/time/zones"
3
5
 
4
6
  class String
5
7
  # Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/time/acts_like'
2
- require 'active_support/core_ext/time/calculations'
3
- require 'active_support/core_ext/time/conversions'
4
- require 'active_support/core_ext/time/marshal'
5
- require 'active_support/core_ext/time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/acts_like"
4
+ require "active_support/core_ext/time/calculations"
5
+ require "active_support/core_ext/time/compatibility"
6
+ require "active_support/core_ext/time/conversions"
7
+ require "active_support/core_ext/time/zones"
@@ -1,4 +1,6 @@
1
- require 'active_support/core_ext/object/acts_like'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/acts_like"
2
4
 
3
5
  class Time
4
6
  # Duck-types as a Time-like class. See Object#acts_like?.
@@ -1,8 +1,11 @@
1
- require 'active_support/duration'
2
- require 'active_support/core_ext/time/conversions'
3
- require 'active_support/time_with_zone'
4
- require 'active_support/core_ext/time/zones'
5
- require 'active_support/core_ext/date_and_time/calculations'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/duration"
4
+ require "active_support/core_ext/time/conversions"
5
+ require "active_support/time_with_zone"
6
+ require "active_support/core_ext/time/zones"
7
+ require "active_support/core_ext/date_and_time/calculations"
8
+ require "active_support/core_ext/date/calculations"
6
9
 
7
10
  class Time
8
11
  include DateAndTime::Calculations
@@ -15,9 +18,9 @@ class Time
15
18
  super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
16
19
  end
17
20
 
18
- # Return the number of days in the given month.
21
+ # Returns the number of days in the given month.
19
22
  # If no year is specified, it will use the current year.
20
- def days_in_month(month, year = now.year)
23
+ def days_in_month(month, year = current.year)
21
24
  if month == 2 && ::Date.gregorian_leap?(year)
22
25
  29
23
26
  else
@@ -25,6 +28,12 @@ class Time
25
28
  end
26
29
  end
27
30
 
31
+ # Returns the number of days in the given year.
32
+ # If no year is specified, it will use the current year.
33
+ def days_in_year(year = current.year)
34
+ days_in_month(2, year) + 337
35
+ end
36
+
28
37
  # Returns <tt>Time.zone.now</tt> when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns <tt>Time.now</tt>.
29
38
  def current
30
39
  ::Time.zone ? ::Time.zone.now : ::Time.now
@@ -46,11 +55,38 @@ class Time
46
55
  end
47
56
  alias_method :at_without_coercion, :at
48
57
  alias_method :at, :at_with_coercion
58
+
59
+ # Creates a +Time+ instance from an RFC 3339 string.
60
+ #
61
+ # Time.rfc3339('1999-12-31T14:00:00-10:00') # => 2000-01-01 00:00:00 -1000
62
+ #
63
+ # If the time or offset components are missing then an +ArgumentError+ will be raised.
64
+ #
65
+ # Time.rfc3339('1999-12-31') # => ArgumentError: invalid date
66
+ def rfc3339(str)
67
+ parts = Date._rfc3339(str)
68
+
69
+ raise ArgumentError, "invalid date" if parts.empty?
70
+
71
+ Time.new(
72
+ parts.fetch(:year),
73
+ parts.fetch(:mon),
74
+ parts.fetch(:mday),
75
+ parts.fetch(:hour),
76
+ parts.fetch(:min),
77
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
78
+ parts.fetch(:offset)
79
+ )
80
+ end
49
81
  end
50
82
 
51
- # Seconds since midnight: Time.now.seconds_since_midnight
83
+ # Returns the number of seconds since 00:00:00.
84
+ #
85
+ # Time.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0.0
86
+ # Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0
87
+ # Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0
52
88
  def seconds_since_midnight
53
- to_i - change(:hour => 0).to_i + (usec / 1.0e+6)
89
+ to_i - change(hour: 0).to_i + (usec / 1.0e+6)
54
90
  end
55
91
 
56
92
  # Returns the number of seconds until 23:59:59.
@@ -62,40 +98,53 @@ class Time
62
98
  end_of_day.to_i - to_i
63
99
  end
64
100
 
101
+ # Returns the fraction of a second as a +Rational+
102
+ #
103
+ # Time.new(2012, 8, 29, 0, 0, 0.5).sec_fraction # => (1/2)
104
+ def sec_fraction
105
+ subsec
106
+ end
107
+
65
108
  # Returns a new Time where one or more of the elements have been changed according
66
109
  # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
67
110
  # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
68
111
  # the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
69
- # and minute is passed, then sec, usec and nsec is set to 0. The +options+
70
- # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
71
- # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>
72
- # <tt>:nsec</tt>. Path either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
112
+ # and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
113
+ # takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
114
+ # <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
115
+ # <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
73
116
  #
74
117
  # Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
75
118
  # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
76
119
  # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
77
120
  def change(options)
78
- new_year = options.fetch(:year, year)
79
- new_month = options.fetch(:month, month)
80
- new_day = options.fetch(:day, day)
81
- new_hour = options.fetch(:hour, hour)
82
- new_min = options.fetch(:min, options[:hour] ? 0 : min)
83
- new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
121
+ new_year = options.fetch(:year, year)
122
+ new_month = options.fetch(:month, month)
123
+ new_day = options.fetch(:day, day)
124
+ new_hour = options.fetch(:hour, hour)
125
+ new_min = options.fetch(:min, options[:hour] ? 0 : min)
126
+ new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
127
+ new_offset = options.fetch(:offset, nil)
84
128
 
85
129
  if new_nsec = options[:nsec]
86
130
  raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
87
131
  new_usec = Rational(new_nsec, 1000)
88
132
  else
89
- new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
133
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
90
134
  end
91
135
 
92
- if utc?
93
- ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
136
+ raise ArgumentError, "argument out of range" if new_usec >= 1000000
137
+
138
+ new_sec += Rational(new_usec, 1000000)
139
+
140
+ if new_offset
141
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
142
+ elsif utc?
143
+ ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
94
144
  elsif zone
95
- ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
145
+ ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
96
146
  else
97
- raise ArgumentError, 'argument out of range' if new_usec > 999999
98
- ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
147
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
99
148
  end
100
149
  end
101
150
 
@@ -104,6 +153,12 @@ class Time
104
153
  # takes a hash with any of these keys: <tt>:years</tt>, <tt>:months</tt>,
105
154
  # <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>, <tt>:minutes</tt>,
106
155
  # <tt>:seconds</tt>.
156
+ #
157
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(seconds: 1) # => 2015-08-01 14:35:01 -0700
158
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(minutes: 1) # => 2015-08-01 14:36:00 -0700
159
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1) # => 2015-08-01 15:35:00 -0700
160
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1) # => 2015-08-02 14:35:00 -0700
161
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1) # => 2015-08-08 14:35:00 -0700
107
162
  def advance(options)
108
163
  unless options[:weeks].nil?
109
164
  options[:weeks], partial_weeks = options[:weeks].divmod(1)
@@ -117,7 +172,7 @@ class Time
117
172
 
118
173
  d = to_date.advance(options)
119
174
  d = d.gregorian if d.julian?
120
- time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
175
+ time_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
121
176
  seconds_to_advance = \
122
177
  options.fetch(:seconds, 0) +
123
178
  options.fetch(:minutes, 0) * 60 +
@@ -145,8 +200,7 @@ class Time
145
200
 
146
201
  # Returns a new Time representing the start of the day (0:00)
147
202
  def beginning_of_day
148
- #(self - seconds_since_midnight).change(usec: 0)
149
- change(:hour => 0)
203
+ change(hour: 0)
150
204
  end
151
205
  alias :midnight :beginning_of_day
152
206
  alias :at_midnight :beginning_of_day
@@ -154,7 +208,7 @@ class Time
154
208
 
155
209
  # Returns a new Time representing the middle of the day (12:00)
156
210
  def middle_of_day
157
- change(:hour => 12)
211
+ change(hour: 12)
158
212
  end
159
213
  alias :midday :middle_of_day
160
214
  alias :noon :middle_of_day
@@ -162,53 +216,48 @@ class Time
162
216
  alias :at_noon :middle_of_day
163
217
  alias :at_middle_of_day :middle_of_day
164
218
 
165
- # Returns a new Time representing the end of the day, 23:59:59.999999 (.999999999 in ruby1.9)
219
+ # Returns a new Time representing the end of the day, 23:59:59.999999
166
220
  def end_of_day
167
221
  change(
168
- :hour => 23,
169
- :min => 59,
170
- :sec => 59,
171
- :usec => Rational(999999999, 1000)
222
+ hour: 23,
223
+ min: 59,
224
+ sec: 59,
225
+ usec: Rational(999999999, 1000)
172
226
  )
173
227
  end
174
228
  alias :at_end_of_day :end_of_day
175
229
 
176
230
  # Returns a new Time representing the start of the hour (x:00)
177
231
  def beginning_of_hour
178
- change(:min => 0)
232
+ change(min: 0)
179
233
  end
180
234
  alias :at_beginning_of_hour :beginning_of_hour
181
235
 
182
- # Returns a new Time representing the end of the hour, x:59:59.999999 (.999999999 in ruby1.9)
236
+ # Returns a new Time representing the end of the hour, x:59:59.999999
183
237
  def end_of_hour
184
238
  change(
185
- :min => 59,
186
- :sec => 59,
187
- :usec => Rational(999999999, 1000)
239
+ min: 59,
240
+ sec: 59,
241
+ usec: Rational(999999999, 1000)
188
242
  )
189
243
  end
190
244
  alias :at_end_of_hour :end_of_hour
191
245
 
192
246
  # Returns a new Time representing the start of the minute (x:xx:00)
193
247
  def beginning_of_minute
194
- change(:sec => 0)
248
+ change(sec: 0)
195
249
  end
196
250
  alias :at_beginning_of_minute :beginning_of_minute
197
251
 
198
- # Returns a new Time representing the end of the minute, x:xx:59.999999 (.999999999 in ruby1.9)
252
+ # Returns a new Time representing the end of the minute, x:xx:59.999999
199
253
  def end_of_minute
200
254
  change(
201
- :sec => 59,
202
- :usec => Rational(999999999, 1000)
255
+ sec: 59,
256
+ usec: Rational(999999999, 1000)
203
257
  )
204
258
  end
205
259
  alias :at_end_of_minute :end_of_minute
206
260
 
207
- # Returns a Range representing the whole day of the current time.
208
- def all_day
209
- beginning_of_day..end_of_day
210
- end
211
-
212
261
  def plus_with_duration(other) #:nodoc:
213
262
  if ActiveSupport::Duration === other
214
263
  other.since(self)
@@ -242,8 +291,10 @@ class Time
242
291
  # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
243
292
  # can be chronologically compared with a Time
244
293
  def compare_with_coercion(other)
245
- # we're avoiding Time#to_datetime cause it's expensive
246
- if other.is_a?(Time)
294
+ # we're avoiding Time#to_datetime and Time#to_time because they're expensive
295
+ if other.class == Time
296
+ compare_without_coercion(other)
297
+ elsif other.is_a?(Time)
247
298
  compare_without_coercion(other.to_time)
248
299
  else
249
300
  to_datetime <=> other
@@ -261,5 +312,4 @@ class Time
261
312
  end
262
313
  alias_method :eql_without_coercion, :eql?
263
314
  alias_method :eql?, :eql_with_coercion
264
-
265
315
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/date_and_time/compatibility"
4
+ require "active_support/core_ext/module/redefine_method"
5
+
6
+ class Time
7
+ include DateAndTime::Compatibility
8
+
9
+ silence_redefinition_of_method :to_time
10
+
11
+ # Either return +self+ or the time in the local system timezone depending
12
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
13
+ def to_time
14
+ preserve_timezone ? self : getlocal
15
+ end
16
+ end
@@ -1,30 +1,33 @@
1
- require 'active_support/inflector/methods'
2
- require 'active_support/values/time_zone'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector/methods"
4
+ require "active_support/values/time_zone"
3
5
 
4
6
  class Time
5
7
  DATE_FORMATS = {
6
- :db => '%Y-%m-%d %H:%M:%S',
7
- :number => '%Y%m%d%H%M%S',
8
- :nsec => '%Y%m%d%H%M%S%9N',
9
- :time => '%H:%M',
10
- :short => '%d %b %H:%M',
11
- :long => '%B %d, %Y %H:%M',
12
- :long_ordinal => lambda { |time|
8
+ db: "%Y-%m-%d %H:%M:%S",
9
+ number: "%Y%m%d%H%M%S",
10
+ nsec: "%Y%m%d%H%M%S%9N",
11
+ usec: "%Y%m%d%H%M%S%6N",
12
+ time: "%H:%M",
13
+ short: "%d %b %H:%M",
14
+ long: "%B %d, %Y %H:%M",
15
+ long_ordinal: lambda { |time|
13
16
  day_format = ActiveSupport::Inflector.ordinalize(time.day)
14
17
  time.strftime("%B #{day_format}, %Y %H:%M")
15
18
  },
16
- :rfc822 => lambda { |time|
19
+ rfc822: lambda { |time|
17
20
  offset_format = time.formatted_offset(false)
18
21
  time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
19
22
  },
20
- :iso8601 => lambda { |time| time.iso8601 }
23
+ iso8601: lambda { |time| time.iso8601 }
21
24
  }
22
25
 
23
26
  # Converts to a formatted string. See DATE_FORMATS for built-in formats.
24
27
  #
25
28
  # This method is aliased to <tt>to_s</tt>.
26
29
  #
27
- # time = Time.now # => Thu Jan 18 06:10:17 CST 2007
30
+ # time = Time.now # => 2007-01-18 06:10:17 -06:00
28
31
  #
29
32
  # time.to_formatted_s(:time) # => "06:10"
30
33
  # time.to_s(:time) # => "06:10"
@@ -55,11 +58,15 @@ class Time
55
58
  alias_method :to_default_s, :to_s
56
59
  alias_method :to_s, :to_formatted_s
57
60
 
58
- # Returns the UTC offset as an +HH:MM formatted string.
61
+ # Returns a formatted string of the offset from UTC, or an alternative
62
+ # string if the time zone is already UTC.
59
63
  #
60
64
  # Time.local(2000).formatted_offset # => "-06:00"
61
65
  # Time.local(2000).formatted_offset(false) # => "-0600"
62
66
  def formatted_offset(colon = true, alternate_utc_string = nil)
63
67
  utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
64
68
  end
69
+
70
+ # Aliased to +xmlschema+ for compatibility with +DateTime+
71
+ alias_method :rfc3339, :xmlschema
65
72
  end
@@ -1,6 +1,8 @@
1
- require 'active_support/time_with_zone'
2
- require 'active_support/core_ext/time/acts_like'
3
- require 'active_support/core_ext/date_and_time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/time_with_zone"
4
+ require "active_support/core_ext/time/acts_like"
5
+ require "active_support/core_ext/date_and_time/zones"
4
6
 
5
7
  class Time
6
8
  include DateAndTime::Zones
@@ -26,7 +28,7 @@ class Time
26
28
  # <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
27
29
  #
28
30
  # class ApplicationController < ActionController::Base
29
- # around_filter :set_time_zone
31
+ # around_action :set_time_zone
30
32
  #
31
33
  # def set_time_zone
32
34
  # if logged_in?
@@ -40,7 +42,23 @@ class Time
40
42
  Thread.current[:time_zone] = find_zone!(time_zone)
41
43
  end
42
44
 
43
- # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
45
+ # Allows override of <tt>Time.zone</tt> locally inside supplied block;
46
+ # resets <tt>Time.zone</tt> to existing value when done.
47
+ #
48
+ # class ApplicationController < ActionController::Base
49
+ # around_action :set_time_zone
50
+ #
51
+ # private
52
+ #
53
+ # def set_time_zone
54
+ # Time.use_zone(current_user.timezone) { yield }
55
+ # end
56
+ # end
57
+ #
58
+ # NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
59
+ # objects that have already been created, e.g. any model timestamp
60
+ # attributes that have been read before the block will remain in
61
+ # the application's default timezone.
44
62
  def use_zone(time_zone)
45
63
  new_zone = find_zone!(time_zone)
46
64
  begin
@@ -51,12 +69,22 @@ class Time
51
69
  end
52
70
  end
53
71
 
54
- # Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones.
72
+ # Returns a TimeZone instance matching the time zone provided.
73
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
74
+ # Raises an +ArgumentError+ for invalid time zones.
75
+ #
76
+ # Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
77
+ # Time.find_zone! "EST" # => #<ActiveSupport::TimeZone @name="EST" ...>
78
+ # Time.find_zone! -5.hours # => #<ActiveSupport::TimeZone @name="Bogota" ...>
79
+ # Time.find_zone! nil # => nil
80
+ # Time.find_zone! false # => false
81
+ # Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
55
82
  def find_zone!(time_zone)
56
83
  if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
57
84
  time_zone
58
85
  else
59
- # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
86
+ # Look up the timezone based on the identifier (unless we've been
87
+ # passed a TZInfo::Timezone)
60
88
  unless time_zone.respond_to?(:period_for_local)
61
89
  time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
62
90
  end
@@ -72,6 +100,12 @@ class Time
72
100
  raise ArgumentError, "Invalid Timezone: #{time_zone}"
73
101
  end
74
102
 
103
+ # Returns a TimeZone instance matching the time zone provided.
104
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
105
+ # Returns +nil+ for invalid time zones.
106
+ #
107
+ # Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
108
+ # Time.find_zone "NOT-A-TIMEZONE" # => nil
75
109
  def find_zone(time_zone)
76
110
  find_zone!(time_zone) rescue nil
77
111
  end