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,18 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
- autoload :Duration, 'active_support/duration'
3
- autoload :TimeWithZone, 'active_support/time_with_zone'
4
- autoload :TimeZone, 'active_support/values/time_zone'
4
+ autoload :Duration, "active_support/duration"
5
+ autoload :TimeWithZone, "active_support/time_with_zone"
6
+ autoload :TimeZone, "active_support/values/time_zone"
5
7
  end
6
8
 
7
- require 'date'
8
- require 'time'
9
+ require "date"
10
+ require "time"
9
11
 
10
- require 'active_support/core_ext/time'
11
- require 'active_support/core_ext/date'
12
- require 'active_support/core_ext/date_time'
12
+ require "active_support/core_ext/time"
13
+ require "active_support/core_ext/date"
14
+ require "active_support/core_ext/date_time"
13
15
 
14
- require 'active_support/core_ext/integer/time'
15
- require 'active_support/core_ext/numeric/time'
16
+ require "active_support/core_ext/integer/time"
17
+ require "active_support/core_ext/numeric/time"
16
18
 
17
- require 'active_support/core_ext/string/conversions'
18
- require 'active_support/core_ext/string/zones'
19
+ require "active_support/core_ext/string/conversions"
20
+ require "active_support/core_ext/string/zones"
@@ -1,5 +1,9 @@
1
- require 'active_support/values/time_zone'
2
- require 'active_support/core_ext/object/acts_like'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/duration"
4
+ require "active_support/values/time_zone"
5
+ require "active_support/core_ext/object/acts_like"
6
+ require "active_support/core_ext/date_and_time/compatibility"
3
7
 
4
8
  module ActiveSupport
5
9
  # A Time-like class that can represent a time in any time zone. Necessary
@@ -13,7 +17,7 @@ module ActiveSupport
13
17
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
14
18
  # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
15
19
  # Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
16
- # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
20
+ # Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
17
21
  # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
18
22
  # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
19
23
  #
@@ -34,26 +38,29 @@ module ActiveSupport
34
38
  # t.is_a?(Time) # => true
35
39
  # t.is_a?(ActiveSupport::TimeWithZone) # => true
36
40
  class TimeWithZone
37
-
38
41
  # Report class name as 'Time' to thwart type checking.
39
42
  def self.name
40
- 'Time'
43
+ "Time"
41
44
  end
42
45
 
43
- include Comparable
46
+ PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N".freeze }
47
+ PRECISIONS[0] = "%FT%T".freeze
48
+
49
+ include Comparable, DateAndTime::Compatibility
44
50
  attr_reader :time_zone
45
51
 
46
52
  def initialize(utc_time, time_zone, local_time = nil, period = nil)
47
- @utc, @time_zone, @time = utc_time, time_zone, local_time
53
+ @utc = utc_time ? transfer_time_values_to_utc_constructor(utc_time) : nil
54
+ @time_zone, @time = time_zone, local_time
48
55
  @period = @utc ? period : get_period_and_ensure_valid_local_time(period)
49
56
  end
50
57
 
51
- # Returns a Time or DateTime instance that represents the time in +time_zone+.
58
+ # Returns a <tt>Time</tt> instance that represents the time in +time_zone+.
52
59
  def time
53
60
  @time ||= period.to_local(@utc)
54
61
  end
55
62
 
56
- # Returns a Time or DateTime instance that represents the time in UTC.
63
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
57
64
  def utc
58
65
  @utc ||= period.to_utc(@time)
59
66
  end
@@ -73,10 +80,9 @@ module ActiveSupport
73
80
  utc.in_time_zone(new_zone)
74
81
  end
75
82
 
76
- # Returns a <tt>Time.local()</tt> instance of the simultaneous time in your
77
- # system's <tt>ENV['TZ']</tt> zone.
83
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
78
84
  def localtime(utc_offset = nil)
79
- utc.respond_to?(:getlocal) ? utc.getlocal(utc_offset) : utc.to_time.getlocal(utc_offset)
85
+ utc.getlocal(utc_offset)
80
86
  end
81
87
  alias_method :getlocal, :localtime
82
88
 
@@ -98,7 +104,7 @@ module ActiveSupport
98
104
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
99
105
  # Time.zone.now.utc? # => false
100
106
  def utc?
101
- time_zone.name == 'UTC'
107
+ period.offset.abbreviation == :UTC || period.offset.abbreviation == :UCT
102
108
  end
103
109
  alias_method :gmt?, :utc?
104
110
 
@@ -121,24 +127,30 @@ module ActiveSupport
121
127
  utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
122
128
  end
123
129
 
124
- # Time uses +zone+ to display the time zone abbreviation, so we're
125
- # duck-typing it.
130
+ # Returns the time zone abbreviation.
131
+ #
132
+ # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
133
+ # Time.zone.now.zone # => "EST"
126
134
  def zone
127
135
  period.zone_identifier.to_s
128
136
  end
129
137
 
138
+ # Returns a string of the object's date, time, zone, and offset from UTC.
139
+ #
140
+ # Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
130
141
  def inspect
131
142
  "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
132
143
  end
133
144
 
145
+ # Returns a string of the object's date and time in the ISO 8601 standard
146
+ # format.
147
+ #
148
+ # Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00"
134
149
  def xmlschema(fraction_digits = 0)
135
- fraction = if fraction_digits.to_i > 0
136
- (".%06i" % time.usec)[0, fraction_digits.to_i + 1]
137
- end
138
-
139
- "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}#{formatted_offset(true, 'Z')}"
150
+ "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'.freeze)}"
140
151
  end
141
152
  alias_method :iso8601, :xmlschema
153
+ alias_method :rfc3339, :xmlschema
142
154
 
143
155
  # Coerces time to a string for JSON encoding. The default format is ISO 8601.
144
156
  # You can get %Y/%m/%d %H:%M:%S +offset style by setting
@@ -160,12 +172,13 @@ module ActiveSupport
160
172
  end
161
173
  end
162
174
 
163
- def encode_with(coder)
164
- if coder.respond_to?(:represent_object)
165
- coder.represent_object(nil, utc)
166
- else
167
- coder.represent_scalar(nil, utc.strftime("%Y-%m-%d %H:%M:%S.%9NZ"))
168
- end
175
+ def init_with(coder) #:nodoc:
176
+ initialize(coder["utc"], coder["zone"], coder["time"])
177
+ end
178
+
179
+ def encode_with(coder) #:nodoc:
180
+ coder.tag = "!ruby/object:ActiveSupport::TimeWithZone"
181
+ coder.map = { "utc" => utc, "zone" => time_zone, "time" => time }
169
182
  end
170
183
 
171
184
  # Returns a string of the object's date and time in the format used by
@@ -187,7 +200,7 @@ module ActiveSupport
187
200
 
188
201
  # Returns a string of the object's date and time.
189
202
  # Accepts an optional <tt>format</tt>:
190
- # * <tt>:default</tt> - default value, mimics Ruby 1.9 Time#to_s format.
203
+ # * <tt>:default</tt> - default value, mimics Ruby Time#to_s format.
191
204
  # * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_formatted_s(:db).
192
205
  # * Any key in <tt>Time::DATE_FORMATS</tt> can be used. See active_support/core_ext/time/conversions.rb.
193
206
  def to_s(format = :default)
@@ -196,7 +209,7 @@ module ActiveSupport
196
209
  elsif formatter = ::Time::DATE_FORMATS[format]
197
210
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
198
211
  else
199
- "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby 1.9 Time#to_s format
212
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
200
213
  end
201
214
  end
202
215
  alias_method :to_formatted_s, :to_s
@@ -235,17 +248,32 @@ module ActiveSupport
235
248
  utc.future?
236
249
  end
237
250
 
251
+ # Returns +true+ if +other+ is equal to current object.
238
252
  def eql?(other)
239
- utc.eql?(other)
253
+ other.eql?(utc)
240
254
  end
241
255
 
242
256
  def hash
243
257
  utc.hash
244
258
  end
245
259
 
260
+ # Adds an interval of time to the current object's time and returns that
261
+ # value as a new TimeWithZone object.
262
+ #
263
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
264
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
265
+ # now + 1000 # => Sun, 02 Nov 2014 01:43:08 EDT -04:00
266
+ #
267
+ # If we're adding a Duration of variable length (i.e., years, months, days),
268
+ # move forward from #time, otherwise move forward from #utc, for accuracy
269
+ # when moving across DST boundaries.
270
+ #
271
+ # For instance, a time + 24.hours will advance exactly 24 hours, while a
272
+ # time + 1.day will advance 23-25 hours, depending on the day.
273
+ #
274
+ # now + 24.hours # => Mon, 03 Nov 2014 00:26:28 EST -05:00
275
+ # now + 1.day # => Mon, 03 Nov 2014 01:26:28 EST -05:00
246
276
  def +(other)
247
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
248
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
249
277
  if duration_of_variable_length?(other)
250
278
  method_missing(:+, other)
251
279
  else
@@ -253,10 +281,26 @@ module ActiveSupport
253
281
  result.in_time_zone(time_zone)
254
282
  end
255
283
  end
284
+ alias_method :since, :+
285
+ alias_method :in, :+
256
286
 
287
+ # Returns a new TimeWithZone object that represents the difference between
288
+ # the current object's time and the +other+ time.
289
+ #
290
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
291
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
292
+ # now - 1000 # => Mon, 03 Nov 2014 00:09:48 EST -05:00
293
+ #
294
+ # If subtracting a Duration of variable length (i.e., years, months, days),
295
+ # move backward from #time, otherwise move backward from #utc, for accuracy
296
+ # when moving across DST boundaries.
297
+ #
298
+ # For instance, a time - 24.hours will go subtract exactly 24 hours, while a
299
+ # time - 1.day will subtract 23-25 hours, depending on the day.
300
+ #
301
+ # now - 24.hours # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
302
+ # now - 1.day # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
257
303
  def -(other)
258
- # If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time,
259
- # otherwise move backwards #utc, for accuracy when moving across DST boundaries
260
304
  if other.acts_like?(:time)
261
305
  to_time - other.to_time
262
306
  elsif duration_of_variable_length?(other)
@@ -267,20 +311,84 @@ module ActiveSupport
267
311
  end
268
312
  end
269
313
 
270
- def since(other)
271
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
272
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
273
- if duration_of_variable_length?(other)
274
- method_missing(:since, other)
275
- else
276
- utc.since(other).in_time_zone(time_zone)
277
- end
278
- end
279
-
314
+ # Subtracts an interval of time from the current object's time and returns
315
+ # the result as a new TimeWithZone object.
316
+ #
317
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
318
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
319
+ # now.ago(1000) # => Mon, 03 Nov 2014 00:09:48 EST -05:00
320
+ #
321
+ # If we're subtracting a Duration of variable length (i.e., years, months,
322
+ # days), move backward from #time, otherwise move backward from #utc, for
323
+ # accuracy when moving across DST boundaries.
324
+ #
325
+ # For instance, <tt>time.ago(24.hours)</tt> will move back exactly 24 hours,
326
+ # while <tt>time.ago(1.day)</tt> will move back 23-25 hours, depending on
327
+ # the day.
328
+ #
329
+ # now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
330
+ # now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
280
331
  def ago(other)
281
332
  since(-other)
282
333
  end
283
334
 
335
+ # Returns a new +ActiveSupport::TimeWithZone+ where one or more of the elements have
336
+ # been changed according to the +options+ parameter. The time options (<tt>:hour</tt>,
337
+ # <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly,
338
+ # so if only the hour is passed, then minute, sec, usec and nsec is set to 0. If the
339
+ # hour and minute is passed, then sec, usec and nsec is set to 0. The +options+
340
+ # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
341
+ # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>,
342
+ # <tt>:nsec</tt>, <tt>:offset</tt>, <tt>:zone</tt>. Pass either <tt>:usec</tt>
343
+ # or <tt>:nsec</tt>, not both. Similarly, pass either <tt>:zone</tt> or
344
+ # <tt>:offset</tt>, not both.
345
+ #
346
+ # t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15 EST -05:00
347
+ # t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15 EST -05:00
348
+ # t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00 EST -05:00
349
+ # t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00 EST -05:00
350
+ # t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
351
+ # t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
352
+ def change(options)
353
+ if options[:zone] && options[:offset]
354
+ raise ArgumentError, "Can't change both :offset and :zone at the same time: #{options.inspect}"
355
+ end
356
+
357
+ new_time = time.change(options)
358
+
359
+ if options[:zone]
360
+ new_zone = ::Time.find_zone(options[:zone])
361
+ elsif options[:offset]
362
+ new_zone = ::Time.find_zone(new_time.utc_offset)
363
+ end
364
+
365
+ new_zone ||= time_zone
366
+ periods = new_zone.periods_for_local(new_time)
367
+
368
+ self.class.new(nil, new_zone, new_time, periods.include?(period) ? period : nil)
369
+ end
370
+
371
+ # Uses Date to provide precise Time calculations for years, months, and days
372
+ # according to the proleptic Gregorian calendar. The result is returned as a
373
+ # new TimeWithZone object.
374
+ #
375
+ # The +options+ parameter takes a hash with any of these keys:
376
+ # <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>,
377
+ # <tt>:hours</tt>, <tt>:minutes</tt>, <tt>:seconds</tt>.
378
+ #
379
+ # If advancing by a value of variable length (i.e., years, weeks, months,
380
+ # days), move forward from #time, otherwise move forward from #utc, for
381
+ # accuracy when moving across DST boundaries.
382
+ #
383
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
384
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
385
+ # now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29 EDT -04:00
386
+ # now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28 EDT -04:00
387
+ # now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28 EST -05:00
388
+ # now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28 EST -05:00
389
+ # now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28 EST -05:00
390
+ # now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28 EST -05:00
391
+ # now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28 EST -05:00
284
392
  def advance(options)
285
393
  # If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
286
394
  # otherwise advance from #utc, for accuracy when moving across DST boundaries
@@ -299,30 +407,57 @@ module ActiveSupport
299
407
  EOV
300
408
  end
301
409
 
410
+ # Returns Array of parts of Time in sequence of
411
+ # [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].
412
+ #
413
+ # now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00
414
+ # now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
302
415
  def to_a
303
416
  [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
304
417
  end
305
418
 
419
+ # Returns the object's date and time as a floating point number of seconds
420
+ # since the Epoch (January 1, 1970 00:00 UTC).
421
+ #
422
+ # Time.zone.now.to_f # => 1417709320.285418
306
423
  def to_f
307
424
  utc.to_f
308
425
  end
309
426
 
427
+ # Returns the object's date and time as an integer number of seconds
428
+ # since the Epoch (January 1, 1970 00:00 UTC).
429
+ #
430
+ # Time.zone.now.to_i # => 1417709320
310
431
  def to_i
311
432
  utc.to_i
312
433
  end
313
434
  alias_method :tv_sec, :to_i
314
435
 
436
+ # Returns the object's date and time as a rational number of seconds
437
+ # since the Epoch (January 1, 1970 00:00 UTC).
438
+ #
439
+ # Time.zone.now.to_r # => (708854548642709/500000)
315
440
  def to_r
316
441
  utc.to_r
317
442
  end
318
443
 
319
- # Return an instance of Time in the system timezone.
320
- def to_time
321
- utc.to_time
444
+ # Returns an instance of DateTime with the timezone's UTC offset
445
+ #
446
+ # Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
447
+ # Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
448
+ def to_datetime
449
+ @to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
322
450
  end
323
451
 
324
- def to_datetime
325
- utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
452
+ # Returns an instance of +Time+, either with the same UTC offset
453
+ # as +self+ or in the local system timezone depending on the setting
454
+ # of +ActiveSupport.to_time_preserves_timezone+.
455
+ def to_time
456
+ if preserve_timezone
457
+ @to_time_with_instance_offset ||= getlocal(utc_offset)
458
+ else
459
+ @to_time_with_system_offset ||= getlocal
460
+ end
326
461
  end
327
462
 
328
463
  # So that +self+ <tt>acts_like?(:time)</tt>.
@@ -336,8 +471,14 @@ module ActiveSupport
336
471
  end
337
472
  alias_method :kind_of?, :is_a?
338
473
 
474
+ # An instance of ActiveSupport::TimeWithZone is never blank
475
+ def blank?
476
+ false
477
+ end
478
+
339
479
  def freeze
340
- period; utc; time # preload instance variables before freezing
480
+ # preload instance variables before freezing
481
+ period; utc; time; to_datetime; to_time
341
482
  super
342
483
  end
343
484
 
@@ -360,7 +501,6 @@ module ActiveSupport
360
501
  # Ensure proxy class responds to all methods that underlying time instance
361
502
  # responds to.
362
503
  def respond_to_missing?(sym, include_priv)
363
- # consistently respond false to acts_like?(:date), regardless of whether #time is a Time or DateTime
364
504
  return false if sym.to_sym == :acts_like_date?
365
505
  time.respond_to?(sym, include_priv)
366
506
  end
@@ -370,7 +510,7 @@ module ActiveSupport
370
510
  def method_missing(sym, *args, &block)
371
511
  wrap_with_time_zone time.__send__(sym, *args, &block)
372
512
  rescue NoMethodError => e
373
- raise e, e.message.sub(time.inspect, self.inspect), e.backtrace
513
+ raise e, e.message.sub(time.inspect, inspect), e.backtrace
374
514
  end
375
515
 
376
516
  private
@@ -388,11 +528,13 @@ module ActiveSupport
388
528
  end
389
529
 
390
530
  def transfer_time_values_to_utc_constructor(time)
391
- ::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec, Rational(time.nsec, 1000))
531
+ # avoid creating another Time object if possible
532
+ return time if time.instance_of?(::Time) && time.utc?
533
+ ::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + time.subsec)
392
534
  end
393
535
 
394
536
  def duration_of_variable_length?(obj)
395
- ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include?(p[0]) }
537
+ ActiveSupport::Duration === obj && obj.parts.any? { |p| [:years, :months, :weeks, :days].include?(p[0]) }
396
538
  end
397
539
 
398
540
  def wrap_with_time_zone(time)