activesupport 3.1.0 → 5.0.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 (276) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +798 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +13 -7
  5. data/lib/active_support/array_inquirer.rb +44 -0
  6. data/lib/active_support/backtrace_cleaner.rb +38 -34
  7. data/lib/active_support/benchmarkable.rb +17 -28
  8. data/lib/active_support/cache/file_store.rb +85 -70
  9. data/lib/active_support/cache/mem_cache_store.rb +75 -66
  10. data/lib/active_support/cache/memory_store.rb +31 -23
  11. data/lib/active_support/cache/null_store.rb +41 -0
  12. data/lib/active_support/cache/strategy/local_cache.rb +73 -70
  13. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  14. data/lib/active_support/cache.rb +360 -294
  15. data/lib/active_support/callbacks.rb +563 -393
  16. data/lib/active_support/concern.rb +42 -34
  17. data/lib/active_support/concurrency/latch.rb +19 -0
  18. data/lib/active_support/concurrency/share_lock.rb +186 -0
  19. data/lib/active_support/configurable.rb +70 -12
  20. data/lib/active_support/core_ext/array/access.rb +53 -9
  21. data/lib/active_support/core_ext/array/conversions.rb +109 -62
  22. data/lib/active_support/core_ext/array/extract_options.rb +2 -2
  23. data/lib/active_support/core_ext/array/grouping.rb +39 -32
  24. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  25. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  26. data/lib/active_support/core_ext/array/wrap.rb +16 -18
  27. data/lib/active_support/core_ext/array.rb +2 -2
  28. data/lib/active_support/core_ext/benchmark.rb +7 -0
  29. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -36
  30. data/lib/active_support/core_ext/class/attribute.rb +47 -34
  31. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -79
  32. data/lib/active_support/core_ext/class/subclasses.rb +12 -7
  33. data/lib/active_support/core_ext/class.rb +0 -3
  34. data/lib/active_support/core_ext/date/blank.rb +12 -0
  35. data/lib/active_support/core_ext/date/calculations.rb +57 -167
  36. data/lib/active_support/core_ext/date/conversions.rb +31 -42
  37. data/lib/active_support/core_ext/date/zones.rb +2 -10
  38. data/lib/active_support/core_ext/date.rb +5 -0
  39. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  40. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
  41. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  42. data/lib/active_support/core_ext/date_time/acts_like.rb +1 -0
  43. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  44. data/lib/active_support/core_ext/date_time/calculations.rb +132 -65
  45. data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
  46. data/lib/active_support/core_ext/date_time/conversions.rb +36 -34
  47. data/lib/active_support/core_ext/date_time.rb +5 -0
  48. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  49. data/lib/active_support/core_ext/enumerable.rb +81 -74
  50. data/lib/active_support/core_ext/file/atomic.rb +53 -26
  51. data/lib/active_support/core_ext/file.rb +0 -1
  52. data/lib/active_support/core_ext/hash/compact.rb +20 -0
  53. data/lib/active_support/core_ext/hash/conversions.rb +175 -70
  54. data/lib/active_support/core_ext/hash/deep_merge.rb +30 -8
  55. data/lib/active_support/core_ext/hash/except.rb +11 -12
  56. data/lib/active_support/core_ext/hash/indifferent_access.rb +7 -8
  57. data/lib/active_support/core_ext/hash/keys.rb +147 -24
  58. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
  59. data/lib/active_support/core_ext/hash/slice.rb +22 -14
  60. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  61. data/lib/active_support/core_ext/hash.rb +2 -2
  62. data/lib/active_support/core_ext/integer/inflections.rb +13 -1
  63. data/lib/active_support/core_ext/integer/multiple.rb +4 -0
  64. data/lib/active_support/core_ext/integer/time.rb +12 -22
  65. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
  66. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  67. data/lib/active_support/core_ext/kernel/debugger.rb +2 -15
  68. data/lib/active_support/core_ext/kernel/reporting.rb +12 -62
  69. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
  70. data/lib/active_support/core_ext/kernel.rb +2 -3
  71. data/lib/active_support/core_ext/load_error.rb +14 -7
  72. data/lib/active_support/core_ext/marshal.rb +22 -0
  73. data/lib/active_support/core_ext/module/aliasing.rb +16 -12
  74. data/lib/active_support/core_ext/module/anonymous.rb +12 -8
  75. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  76. data/lib/active_support/core_ext/module/attribute_accessors.rb +165 -13
  77. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  78. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  79. data/lib/active_support/core_ext/module/delegation.rb +141 -68
  80. data/lib/active_support/core_ext/module/deprecation.rb +17 -3
  81. data/lib/active_support/core_ext/module/introspection.rb +9 -31
  82. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  83. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  84. data/lib/active_support/core_ext/module/reachable.rb +1 -3
  85. data/lib/active_support/core_ext/module/remove_method.rb +24 -5
  86. data/lib/active_support/core_ext/module.rb +3 -3
  87. data/lib/active_support/core_ext/name_error.rb +15 -2
  88. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  89. data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
  90. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  91. data/lib/active_support/core_ext/numeric/time.rb +31 -36
  92. data/lib/active_support/core_ext/numeric.rb +2 -0
  93. data/lib/active_support/core_ext/object/acts_like.rb +4 -4
  94. data/lib/active_support/core_ext/object/blank.rb +52 -18
  95. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  96. data/lib/active_support/core_ext/object/duplicable.rb +12 -20
  97. data/lib/active_support/core_ext/object/inclusion.rb +13 -1
  98. data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
  99. data/lib/active_support/core_ext/object/json.rb +205 -0
  100. data/lib/active_support/core_ext/object/to_param.rb +1 -55
  101. data/lib/active_support/core_ext/object/to_query.rb +66 -9
  102. data/lib/active_support/core_ext/object/try.rb +124 -33
  103. data/lib/active_support/core_ext/object/with_options.rb +37 -11
  104. data/lib/active_support/core_ext/object.rb +2 -1
  105. data/lib/active_support/core_ext/range/conversions.rb +17 -7
  106. data/lib/active_support/core_ext/range/each.rb +21 -0
  107. data/lib/active_support/core_ext/range/include_range.rb +20 -18
  108. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  109. data/lib/active_support/core_ext/range.rb +1 -2
  110. data/lib/active_support/core_ext/securerandom.rb +23 -0
  111. data/lib/active_support/core_ext/string/access.rb +95 -90
  112. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  113. data/lib/active_support/core_ext/string/conversions.rb +41 -38
  114. data/lib/active_support/core_ext/string/exclude.rb +6 -1
  115. data/lib/active_support/core_ext/string/filters.rb +70 -17
  116. data/lib/active_support/core_ext/string/indent.rb +43 -0
  117. data/lib/active_support/core_ext/string/inflections.rb +139 -59
  118. data/lib/active_support/core_ext/string/inquiry.rb +2 -2
  119. data/lib/active_support/core_ext/string/multibyte.rb +46 -65
  120. data/lib/active_support/core_ext/string/output_safety.rb +153 -56
  121. data/lib/active_support/core_ext/string/strip.rb +3 -6
  122. data/lib/active_support/core_ext/string/zones.rb +14 -0
  123. data/lib/active_support/core_ext/string.rb +2 -3
  124. data/lib/active_support/core_ext/struct.rb +3 -0
  125. data/lib/active_support/core_ext/time/calculations.rb +173 -173
  126. data/lib/active_support/core_ext/time/compatibility.rb +5 -0
  127. data/lib/active_support/core_ext/time/conversions.rb +33 -29
  128. data/lib/active_support/core_ext/time/marshal.rb +2 -56
  129. data/lib/active_support/core_ext/time/zones.rb +57 -32
  130. data/lib/active_support/core_ext/time.rb +5 -0
  131. data/lib/active_support/core_ext/uri.rb +13 -19
  132. data/lib/active_support/core_ext.rb +3 -2
  133. data/lib/active_support/dependencies/autoload.rb +47 -20
  134. data/lib/active_support/dependencies/interlock.rb +51 -0
  135. data/lib/active_support/dependencies.rb +315 -265
  136. data/lib/active_support/deprecation/behaviors.rb +71 -30
  137. data/lib/active_support/deprecation/instance_delegator.rb +24 -0
  138. data/lib/active_support/deprecation/method_wrappers.rb +59 -18
  139. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -14
  140. data/lib/active_support/deprecation/reporting.rb +61 -14
  141. data/lib/active_support/deprecation.rb +38 -13
  142. data/lib/active_support/descendants_tracker.rb +34 -19
  143. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  144. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  145. data/lib/active_support/duration.rb +85 -14
  146. data/lib/active_support/evented_file_update_checker.rb +194 -0
  147. data/lib/active_support/execution_wrapper.rb +117 -0
  148. data/lib/active_support/executor.rb +6 -0
  149. data/lib/active_support/file_update_checker.rb +138 -17
  150. data/lib/active_support/gem_version.rb +15 -0
  151. data/lib/active_support/gzip.rb +11 -5
  152. data/lib/active_support/hash_with_indifferent_access.rb +199 -49
  153. data/lib/active_support/i18n.rb +6 -2
  154. data/lib/active_support/i18n_railtie.rb +40 -21
  155. data/lib/active_support/inflections.rb +22 -13
  156. data/lib/active_support/inflector/inflections.rb +175 -144
  157. data/lib/active_support/inflector/methods.rb +328 -91
  158. data/lib/active_support/inflector/transliterate.rb +51 -37
  159. data/lib/active_support/json/decoding.rb +31 -22
  160. data/lib/active_support/json/encoding.rb +88 -248
  161. data/lib/active_support/key_generator.rb +71 -0
  162. data/lib/active_support/lazy_load_hooks.rb +27 -25
  163. data/lib/active_support/locale/en.yml +102 -3
  164. data/lib/active_support/log_subscriber/test_helper.rb +24 -21
  165. data/lib/active_support/log_subscriber.rb +36 -49
  166. data/lib/active_support/logger.rb +106 -0
  167. data/lib/active_support/logger_silence.rb +28 -0
  168. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  169. data/lib/active_support/message_encryptor.rb +72 -36
  170. data/lib/active_support/message_verifier.rb +96 -24
  171. data/lib/active_support/multibyte/chars.rb +88 -333
  172. data/lib/active_support/multibyte/unicode.rb +156 -136
  173. data/lib/active_support/multibyte.rb +5 -28
  174. data/lib/active_support/notifications/fanout.rb +115 -19
  175. data/lib/active_support/notifications/instrumenter.rb +52 -15
  176. data/lib/active_support/notifications.rb +168 -33
  177. data/lib/active_support/number_helper/number_converter.rb +182 -0
  178. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  179. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  180. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  181. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  182. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  183. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  184. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  185. data/lib/active_support/number_helper.rb +368 -0
  186. data/lib/active_support/option_merger.rb +1 -1
  187. data/lib/active_support/ordered_hash.rb +18 -183
  188. data/lib/active_support/ordered_options.rb +44 -24
  189. data/lib/active_support/per_thread_registry.rb +58 -0
  190. data/lib/active_support/proxy_object.rb +13 -0
  191. data/lib/active_support/rails.rb +27 -0
  192. data/lib/active_support/railtie.rb +25 -34
  193. data/lib/active_support/reloader.rb +129 -0
  194. data/lib/active_support/rescuable.rb +98 -48
  195. data/lib/active_support/security_utils.rb +27 -0
  196. data/lib/active_support/string_inquirer.rb +14 -9
  197. data/lib/active_support/subscriber.rb +120 -0
  198. data/lib/active_support/tagged_logging.rb +78 -0
  199. data/lib/active_support/test_case.rb +69 -17
  200. data/lib/active_support/testing/assertions.rb +43 -41
  201. data/lib/active_support/testing/autorun.rb +12 -0
  202. data/lib/active_support/testing/constant_lookup.rb +50 -0
  203. data/lib/active_support/testing/declarative.rb +7 -21
  204. data/lib/active_support/testing/deprecation.rb +14 -33
  205. data/lib/active_support/testing/file_fixtures.rb +34 -0
  206. data/lib/active_support/testing/isolation.rb +53 -95
  207. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  208. data/lib/active_support/testing/setup_and_teardown.rb +21 -82
  209. data/lib/active_support/testing/stream.rb +42 -0
  210. data/lib/active_support/testing/tagged_logging.rb +25 -0
  211. data/lib/active_support/testing/time_helpers.rb +134 -0
  212. data/lib/active_support/time.rb +6 -23
  213. data/lib/active_support/time_with_zone.rb +239 -92
  214. data/lib/active_support/values/time_zone.rb +236 -160
  215. data/lib/active_support/values/unicode_tables.dat +0 -0
  216. data/lib/active_support/version.rb +5 -7
  217. data/lib/active_support/xml_mini/jdom.rb +19 -13
  218. data/lib/active_support/xml_mini/libxml.rb +3 -4
  219. data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
  220. data/lib/active_support/xml_mini/nokogiri.rb +3 -4
  221. data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
  222. data/lib/active_support/xml_mini/rexml.rb +8 -10
  223. data/lib/active_support/xml_mini.rb +66 -34
  224. data/lib/active_support.rb +40 -23
  225. metadata +185 -134
  226. data/CHANGELOG +0 -1534
  227. data/lib/active_support/base64.rb +0 -42
  228. data/lib/active_support/basic_object.rb +0 -21
  229. data/lib/active_support/buffered_logger.rb +0 -137
  230. data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
  231. data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
  232. data/lib/active_support/core_ext/array/random_access.rb +0 -30
  233. data/lib/active_support/core_ext/array/uniq_by.rb +0 -16
  234. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -44
  235. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
  236. data/lib/active_support/core_ext/date/freeze.rb +0 -31
  237. data/lib/active_support/core_ext/date_time/zones.rb +0 -21
  238. data/lib/active_support/core_ext/exception.rb +0 -3
  239. data/lib/active_support/core_ext/file/path.rb +0 -5
  240. data/lib/active_support/core_ext/float/rounding.rb +0 -19
  241. data/lib/active_support/core_ext/float.rb +0 -1
  242. data/lib/active_support/core_ext/hash/deep_dup.rb +0 -11
  243. data/lib/active_support/core_ext/hash/diff.rb +0 -13
  244. data/lib/active_support/core_ext/kernel/requires.rb +0 -28
  245. data/lib/active_support/core_ext/logger.rb +0 -81
  246. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
  247. data/lib/active_support/core_ext/module/method_names.rb +0 -14
  248. data/lib/active_support/core_ext/module/synchronization.rb +0 -43
  249. data/lib/active_support/core_ext/object/to_json.rb +0 -19
  250. data/lib/active_support/core_ext/proc.rb +0 -14
  251. data/lib/active_support/core_ext/process/daemon.rb +0 -23
  252. data/lib/active_support/core_ext/process.rb +0 -1
  253. data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
  254. data/lib/active_support/core_ext/range/cover.rb +0 -3
  255. data/lib/active_support/core_ext/rexml.rb +0 -46
  256. data/lib/active_support/core_ext/string/encoding.rb +0 -11
  257. data/lib/active_support/core_ext/string/interpolation.rb +0 -2
  258. data/lib/active_support/core_ext/string/xchar.rb +0 -18
  259. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
  260. data/lib/active_support/file_watcher.rb +0 -36
  261. data/lib/active_support/json/variable.rb +0 -9
  262. data/lib/active_support/memoizable.rb +0 -105
  263. data/lib/active_support/multibyte/exceptions.rb +0 -8
  264. data/lib/active_support/multibyte/utils.rb +0 -60
  265. data/lib/active_support/ruby/shim.rb +0 -22
  266. data/lib/active_support/secure_random.rb +0 -6
  267. data/lib/active_support/testing/mochaing.rb +0 -7
  268. data/lib/active_support/testing/pending.rb +0 -52
  269. data/lib/active_support/testing/performance/jruby.rb +0 -115
  270. data/lib/active_support/testing/performance/rubinius.rb +0 -113
  271. data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
  272. data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
  273. data/lib/active_support/testing/performance/ruby.rb +0 -152
  274. data/lib/active_support/testing/performance.rb +0 -317
  275. data/lib/active_support/time/autoload.rb +0 -5
  276. data/lib/active_support/whiny_nil.rb +0 -60
@@ -1,26 +1,28 @@
1
- require "active_support/values/time_zone"
1
+ require 'active_support/duration'
2
+ require 'active_support/values/time_zone'
2
3
  require 'active_support/core_ext/object/acts_like'
3
- require 'active_support/core_ext/object/inclusion'
4
+ require 'active_support/core_ext/date_and_time/compatibility'
4
5
 
5
6
  module ActiveSupport
6
- # A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are
7
- # limited to UTC and the system's <tt>ENV['TZ']</tt> zone.
7
+ # A Time-like class that can represent a time in any time zone. Necessary
8
+ # because standard Ruby Time instances are limited to UTC and the
9
+ # system's <tt>ENV['TZ']</tt> zone.
8
10
  #
9
- # You shouldn't ever need to create a TimeWithZone instance directly via <tt>new</tt> . Instead use methods
10
- # +local+, +parse+, +at+ and +now+ on TimeZone instances, and +in_time_zone+ on Time and DateTime instances.
11
- # Examples:
11
+ # You shouldn't ever need to create a TimeWithZone instance directly via +new+.
12
+ # Instead use methods +local+, +parse+, +at+ and +now+ on TimeZone instances,
13
+ # and +in_time_zone+ on Time and DateTime instances.
12
14
  #
13
15
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
14
16
  # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
15
- # Time.zone.parse('2007-02-01 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
17
+ # Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
18
+ # Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
17
19
  # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
18
20
  # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
19
21
  #
20
22
  # See Time and TimeZone for further documentation of these methods.
21
23
  #
22
- # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangeable.
23
- # Examples:
24
+ # TimeWithZone instances implement the same API as Ruby Time instances, so
25
+ # that Time and TimeWithZone instances are interchangeable.
24
26
  #
25
27
  # t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00
26
28
  # t.hour # => 13
@@ -33,26 +35,31 @@ module ActiveSupport
33
35
  # t > Time.utc(1999) # => true
34
36
  # t.is_a?(Time) # => true
35
37
  # t.is_a?(ActiveSupport::TimeWithZone) # => true
36
- #
37
38
  class TimeWithZone
39
+
40
+ # Report class name as 'Time' to thwart type checking.
38
41
  def self.name
39
- 'Time' # Report class name as 'Time' to thwart type checking
42
+ 'Time'
40
43
  end
41
44
 
42
- include Comparable
45
+ PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N".freeze }
46
+ PRECISIONS[0] = '%FT%T'.freeze
47
+
48
+ include Comparable, DateAndTime::Compatibility
43
49
  attr_reader :time_zone
44
50
 
45
51
  def initialize(utc_time, time_zone, local_time = nil, period = nil)
46
- @utc, @time_zone, @time = utc_time, time_zone, local_time
47
- @period = @utc ? period : get_period_and_ensure_valid_local_time
52
+ @utc = utc_time ? transfer_time_values_to_utc_constructor(utc_time) : nil
53
+ @time_zone, @time = time_zone, local_time
54
+ @period = @utc ? period : get_period_and_ensure_valid_local_time(period)
48
55
  end
49
56
 
50
- # Returns a Time or DateTime instance that represents the time in +time_zone+.
57
+ # Returns a <tt>Time</tt> instance that represents the time in +time_zone+.
51
58
  def time
52
59
  @time ||= period.to_local(@utc)
53
60
  end
54
61
 
55
- # Returns a Time or DateTime instance that represents the time in UTC.
62
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
56
63
  def utc
57
64
  @utc ||= period.to_utc(@time)
58
65
  end
@@ -72,113 +79,144 @@ module ActiveSupport
72
79
  utc.in_time_zone(new_zone)
73
80
  end
74
81
 
75
- # Returns a <tt>Time.local()</tt> instance of the simultaneous time in your system's <tt>ENV['TZ']</tt> zone
76
- def localtime
77
- utc.respond_to?(:getlocal) ? utc.getlocal : utc.to_time.getlocal
82
+ # Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
83
+ def localtime(utc_offset = nil)
84
+ utc.getlocal(utc_offset)
78
85
  end
79
86
  alias_method :getlocal, :localtime
80
87
 
88
+ # Returns true if the current time is within Daylight Savings Time for the
89
+ # specified time zone.
90
+ #
91
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
92
+ # Time.zone.parse("2012-5-30").dst? # => true
93
+ # Time.zone.parse("2012-11-30").dst? # => false
81
94
  def dst?
82
95
  period.dst?
83
96
  end
84
97
  alias_method :isdst, :dst?
85
98
 
99
+ # Returns true if the current time zone is set to UTC.
100
+ #
101
+ # Time.zone = 'UTC' # => 'UTC'
102
+ # Time.zone.now.utc? # => true
103
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
104
+ # Time.zone.now.utc? # => false
86
105
  def utc?
87
- time_zone.name == 'UTC'
106
+ period.offset.abbreviation == :UTC || period.offset.abbreviation == :UCT
88
107
  end
89
108
  alias_method :gmt?, :utc?
90
109
 
110
+ # Returns the offset from current time to UTC time in seconds.
91
111
  def utc_offset
92
112
  period.utc_total_offset
93
113
  end
94
114
  alias_method :gmt_offset, :utc_offset
95
115
  alias_method :gmtoff, :utc_offset
96
116
 
117
+ # Returns a formatted string of the offset from UTC, or an alternative
118
+ # string if the time zone is already UTC.
119
+ #
120
+ # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
121
+ # Time.zone.now.formatted_offset(true) # => "-05:00"
122
+ # Time.zone.now.formatted_offset(false) # => "-0500"
123
+ # Time.zone = 'UTC' # => "UTC"
124
+ # Time.zone.now.formatted_offset(true, "0") # => "0"
97
125
  def formatted_offset(colon = true, alternate_utc_string = nil)
98
126
  utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
99
127
  end
100
128
 
101
- # Time uses +zone+ to display the time zone abbreviation, so we're duck-typing it.
129
+ # Returns the time zone abbreviation.
130
+ #
131
+ # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
132
+ # Time.zone.now.zone # => "EST"
102
133
  def zone
103
134
  period.zone_identifier.to_s
104
135
  end
105
136
 
137
+ # Returns a string of the object's date, time, zone and offset from UTC.
138
+ #
139
+ # Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
106
140
  def inspect
107
141
  "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
108
142
  end
109
143
 
144
+ # Returns a string of the object's date and time in the ISO 8601 standard
145
+ # format.
146
+ #
147
+ # Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00"
110
148
  def xmlschema(fraction_digits = 0)
111
- fraction = if fraction_digits > 0
112
- ".%i" % time.usec.to_s[0, fraction_digits]
113
- end
114
-
115
- "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}#{formatted_offset(true, 'Z')}"
149
+ "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'.freeze)}"
116
150
  end
117
151
  alias_method :iso8601, :xmlschema
118
152
 
119
- # Coerces time to a string for JSON encoding. The default format is ISO 8601. You can get
120
- # %Y/%m/%d %H:%M:%S +offset style by setting <tt>ActiveSupport::JSON::Encoding.use_standard_json_time_format</tt>
121
- # to false.
122
- #
123
- # ==== Examples
153
+ # Coerces time to a string for JSON encoding. The default format is ISO 8601.
154
+ # You can get %Y/%m/%d %H:%M:%S +offset style by setting
155
+ # <tt>ActiveSupport::JSON::Encoding.use_standard_json_time_format</tt>
156
+ # to +false+.
124
157
  #
125
158
  # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
126
- # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
127
- # # => "2005-02-01T15:15:10Z"
159
+ # Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
160
+ # # => "2005-02-01T05:15:10.000-10:00"
128
161
  #
129
162
  # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
130
- # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
131
- # # => "2005/02/01 15:15:10 +0000"
132
- #
163
+ # Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
164
+ # # => "2005/02/01 05:15:10 -1000"
133
165
  def as_json(options = nil)
134
166
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
135
- xmlschema
167
+ xmlschema(ActiveSupport::JSON::Encoding.time_precision)
136
168
  else
137
169
  %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
138
170
  end
139
171
  end
140
172
 
141
- def encode_with(coder)
142
- if coder.respond_to?(:represent_object)
143
- coder.represent_object(nil, utc)
144
- else
145
- coder.represent_scalar(nil, utc.strftime("%Y-%m-%d %H:%M:%S.%9NZ"))
146
- end
173
+ def init_with(coder) #:nodoc:
174
+ initialize(coder['utc'], coder['zone'], coder['time'])
147
175
  end
148
176
 
149
- def to_yaml(options = {})
150
- return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
151
-
152
- utc.to_yaml(options)
177
+ def encode_with(coder) #:nodoc:
178
+ coder.tag = '!ruby/object:ActiveSupport::TimeWithZone'
179
+ coder.map = { 'utc' => utc, 'zone' => time_zone, 'time' => time }
153
180
  end
154
181
 
182
+ # Returns a string of the object's date and time in the format used by
183
+ # HTTP requests.
184
+ #
185
+ # Time.zone.now.httpdate # => "Tue, 01 Jan 2013 04:39:43 GMT"
155
186
  def httpdate
156
187
  utc.httpdate
157
188
  end
158
189
 
190
+ # Returns a string of the object's date and time in the RFC 2822 standard
191
+ # format.
192
+ #
193
+ # Time.zone.now.rfc2822 # => "Tue, 01 Jan 2013 04:51:39 +0000"
159
194
  def rfc2822
160
195
  to_s(:rfc822)
161
196
  end
162
197
  alias_method :rfc822, :rfc2822
163
198
 
164
- # <tt>:db</tt> format outputs time in UTC; all others output time in local.
165
- # Uses TimeWithZone's +strftime+, so <tt>%Z</tt> and <tt>%z</tt> work correctly.
199
+ # Returns a string of the object's date and time.
200
+ # Accepts an optional <tt>format</tt>:
201
+ # * <tt>:default</tt> - default value, mimics Ruby Time#to_s format.
202
+ # * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_formatted_s(:db).
203
+ # * Any key in <tt>Time::DATE_FORMATS</tt> can be used. See active_support/core_ext/time/conversions.rb.
166
204
  def to_s(format = :default)
167
205
  if format == :db
168
206
  utc.to_s(format)
169
207
  elsif formatter = ::Time::DATE_FORMATS[format]
170
208
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
171
209
  else
172
- "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby 1.9 Time#to_s format
210
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
173
211
  end
174
212
  end
175
213
  alias_method :to_formatted_s, :to_s
176
214
 
177
- # Replaces <tt>%Z</tt> and <tt>%z</tt> directives with +zone+ and +formatted_offset+, respectively, before passing to
178
- # Time#strftime, so that zone information is correct
215
+ # Replaces <tt>%Z</tt> directive with +zone before passing to Time#strftime,
216
+ # so that zone information is correct.
179
217
  def strftime(format)
180
- format = format.gsub('%Z', zone).gsub('%z', formatted_offset(false))
181
- time.strftime(format)
218
+ format = format.gsub(/((?:\A|[^%])(?:%%)*)%Z/, "\\1#{zone}")
219
+ getlocal(utc_offset).strftime(format)
182
220
  end
183
221
 
184
222
  # Use the time in UTC for comparisons.
@@ -186,29 +224,54 @@ module ActiveSupport
186
224
  utc <=> other
187
225
  end
188
226
 
227
+ # Returns true if the current object's time is within the specified
228
+ # +min+ and +max+ time.
189
229
  def between?(min, max)
190
230
  utc.between?(min, max)
191
231
  end
192
232
 
233
+ # Returns true if the current object's time is in the past.
193
234
  def past?
194
235
  utc.past?
195
236
  end
196
237
 
238
+ # Returns true if the current object's time falls within
239
+ # the current day.
197
240
  def today?
198
241
  time.today?
199
242
  end
200
243
 
244
+ # Returns true if the current object's time is in the future.
201
245
  def future?
202
246
  utc.future?
203
247
  end
204
248
 
249
+ # Returns +true+ if +other+ is equal to current object.
205
250
  def eql?(other)
206
- utc == other
251
+ other.eql?(utc)
207
252
  end
208
253
 
254
+ def hash
255
+ utc.hash
256
+ end
257
+
258
+ # Adds an interval of time to the current object's time and returns that
259
+ # value as a new TimeWithZone object.
260
+ #
261
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
262
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
263
+ # now + 1000 # => Sun, 02 Nov 2014 01:43:08 EDT -04:00
264
+ #
265
+ # If we're adding a Duration of variable length (i.e., years, months, days),
266
+ # move forward from #time, otherwise move forward from #utc, for accuracy
267
+ # when moving across DST boundaries.
268
+ #
269
+ # For instance, a time + 24.hours will advance exactly 24 hours, while a
270
+ # time + 1.day will advance 23-25 hours, depending on the day.
271
+ #
272
+ # now + 24.hours # => Mon, 03 Nov 2014 00:26:28 EST -05:00
273
+ # now + 1.day # => Mon, 03 Nov 2014 01:26:28 EST -05:00
209
274
  def +(other)
210
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
211
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
212
275
  if duration_of_variable_length?(other)
213
276
  method_missing(:+, other)
214
277
  else
@@ -216,12 +279,27 @@ module ActiveSupport
216
279
  result.in_time_zone(time_zone)
217
280
  end
218
281
  end
282
+ alias_method :since, :+
219
283
 
284
+ # Returns a new TimeWithZone object that represents the difference between
285
+ # the current object's time and the +other+ time.
286
+ #
287
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
288
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
289
+ # now - 1000 # => Mon, 03 Nov 2014 00:09:48 EST -05:00
290
+ #
291
+ # If subtracting a Duration of variable length (i.e., years, months, days),
292
+ # move backward from #time, otherwise move backward from #utc, for accuracy
293
+ # when moving across DST boundaries.
294
+ #
295
+ # For instance, a time - 24.hours will go subtract exactly 24 hours, while a
296
+ # time - 1.day will subtract 23-25 hours, depending on the day.
297
+ #
298
+ # now - 24.hours # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
299
+ # now - 1.day # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
220
300
  def -(other)
221
- # If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time,
222
- # otherwise move backwards #utc, for accuracy when moving across DST boundaries
223
301
  if other.acts_like?(:time)
224
- utc.to_f - other.to_f
302
+ to_time - other.to_time
225
303
  elsif duration_of_variable_length?(other)
226
304
  method_missing(:-, other)
227
305
  else
@@ -230,20 +308,48 @@ module ActiveSupport
230
308
  end
231
309
  end
232
310
 
233
- def since(other)
234
- # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
235
- # otherwise move forward from #utc, for accuracy when moving across DST boundaries
236
- if duration_of_variable_length?(other)
237
- method_missing(:since, other)
238
- else
239
- utc.since(other).in_time_zone(time_zone)
240
- end
241
- end
242
-
311
+ # Subtracts an interval of time from the current object's time and returns
312
+ # the result as a new TimeWithZone object.
313
+ #
314
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
315
+ # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
316
+ # now.ago(1000) # => Mon, 03 Nov 2014 00:09:48 EST -05:00
317
+ #
318
+ # If we're subtracting a Duration of variable length (i.e., years, months,
319
+ # days), move backward from #time, otherwise move backward from #utc, for
320
+ # accuracy when moving across DST boundaries.
321
+ #
322
+ # For instance, <tt>time.ago(24.hours)</tt> will move back exactly 24 hours,
323
+ # while <tt>time.ago(1.day)</tt> will move back 23-25 hours, depending on
324
+ # the day.
325
+ #
326
+ # now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
327
+ # now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
243
328
  def ago(other)
244
329
  since(-other)
245
330
  end
246
331
 
332
+ # Uses Date to provide precise Time calculations for years, months, and days
333
+ # according to the proleptic Gregorian calendar. The result is returned as a
334
+ # new TimeWithZone object.
335
+ #
336
+ # The +options+ parameter takes a hash with any of these keys:
337
+ # <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>,
338
+ # <tt>:hours</tt>, <tt>:minutes</tt>, <tt>:seconds</tt>.
339
+ #
340
+ # If advancing by a value of variable length (i.e., years, weeks, months,
341
+ # days), move forward from #time, otherwise move forward from #utc, for
342
+ # accuracy when moving across DST boundaries.
343
+ #
344
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
345
+ # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
346
+ # now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29 EDT -04:00
347
+ # now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28 EDT -04:00
348
+ # now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28 EST -05:00
349
+ # now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28 EST -05:00
350
+ # now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28 EST -05:00
351
+ # now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28 EST -05:00
352
+ # now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28 EST -05:00
247
353
  def advance(options)
248
354
  # If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
249
355
  # otherwise advance from #utc, for accuracy when moving across DST boundaries
@@ -254,7 +360,7 @@ module ActiveSupport
254
360
  end
255
361
  end
256
362
 
257
- %w(year mon month day mday wday yday hour min sec to_date).each do |method_name|
363
+ %w(year mon month day mday wday yday hour min sec usec nsec to_date).each do |method_name|
258
364
  class_eval <<-EOV, __FILE__, __LINE__ + 1
259
365
  def #{method_name} # def month
260
366
  time.#{method_name} # time.month
@@ -262,29 +368,44 @@ module ActiveSupport
262
368
  EOV
263
369
  end
264
370
 
265
- def usec
266
- time.respond_to?(:usec) ? time.usec : 0
267
- end
268
-
371
+ # Returns Array of parts of Time in sequence of
372
+ # [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].
373
+ #
374
+ # now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00
375
+ # now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
269
376
  def to_a
270
377
  [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
271
378
  end
272
379
 
380
+ # Returns the object's date and time as a floating point number of seconds
381
+ # since the Epoch (January 1, 1970 00:00 UTC).
382
+ #
383
+ # Time.zone.now.to_f # => 1417709320.285418
273
384
  def to_f
274
385
  utc.to_f
275
386
  end
276
387
 
388
+ # Returns the object's date and time as an integer number of seconds
389
+ # since the Epoch (January 1, 1970 00:00 UTC).
390
+ #
391
+ # Time.zone.now.to_i # => 1417709320
277
392
  def to_i
278
393
  utc.to_i
279
394
  end
280
- alias_method :hash, :to_i
281
395
  alias_method :tv_sec, :to_i
282
396
 
283
- # A TimeWithZone acts like a Time, so just return +self+.
284
- def to_time
285
- utc
397
+ # Returns the object's date and time as a rational number of seconds
398
+ # since the Epoch (January 1, 1970 00:00 UTC).
399
+ #
400
+ # Time.zone.now.to_r # => (708854548642709/500000)
401
+ def to_r
402
+ utc.to_r
286
403
  end
287
404
 
405
+ # Returns an instance of DateTime with the timezone's UTC offset
406
+ #
407
+ # Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
408
+ # Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
288
409
  def to_datetime
289
410
  utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
290
411
  end
@@ -300,6 +421,11 @@ module ActiveSupport
300
421
  end
301
422
  alias_method :kind_of?, :is_a?
302
423
 
424
+ # An instance of ActiveSupport::TimeWithZone is never blank
425
+ def blank?
426
+ false
427
+ end
428
+
303
429
  def freeze
304
430
  period; utc; time # preload instance variables before freezing
305
431
  super
@@ -313,26 +439,36 @@ module ActiveSupport
313
439
  initialize(variables[0].utc, ::Time.find_zone(variables[1]), variables[2].utc)
314
440
  end
315
441
 
316
- # Ensure proxy class responds to all methods that underlying time instance responds to.
442
+ # respond_to_missing? is not called in some cases, such as when type conversion is
443
+ # performed with Kernel#String
317
444
  def respond_to?(sym, include_priv = false)
318
- # consistently respond false to acts_like?(:date), regardless of whether #time is a Time or DateTime
319
- return false if sym.to_s == 'acts_like_date?'
320
- super || time.respond_to?(sym, include_priv)
445
+ # ensure that we're not going to throw and rescue from NoMethodError in method_missing which is slow
446
+ return false if sym.to_sym == :to_str
447
+ super
448
+ end
449
+
450
+ # Ensure proxy class responds to all methods that underlying time instance
451
+ # responds to.
452
+ def respond_to_missing?(sym, include_priv)
453
+ return false if sym.to_sym == :acts_like_date?
454
+ time.respond_to?(sym, include_priv)
321
455
  end
322
456
 
323
- # Send the missing method to +time+ instance, and wrap result in a new TimeWithZone with the existing +time_zone+.
457
+ # Send the missing method to +time+ instance, and wrap result in a new
458
+ # TimeWithZone with the existing +time_zone+.
324
459
  def method_missing(sym, *args, &block)
325
- result = time.__send__(sym, *args, &block)
326
- result.acts_like?(:time) ? self.class.new(nil, time_zone, result) : result
460
+ wrap_with_time_zone time.__send__(sym, *args, &block)
461
+ rescue NoMethodError => e
462
+ raise e, e.message.sub(time.inspect, self.inspect), e.backtrace
327
463
  end
328
464
 
329
465
  private
330
- def get_period_and_ensure_valid_local_time
466
+ def get_period_and_ensure_valid_local_time(period)
331
467
  # we don't want a Time.local instance enforcing its own DST rules as well,
332
468
  # so transfer time values to a utc constructor if necessary
333
469
  @time = transfer_time_values_to_utc_constructor(@time) unless @time.utc?
334
470
  begin
335
- @time_zone.period_for_local(@time)
471
+ period || @time_zone.period_for_local(@time)
336
472
  rescue ::TZInfo::PeriodNotFound
337
473
  # time is in the "spring forward" hour gap, so we're moving the time forward one hour and trying again
338
474
  @time += 1.hour
@@ -341,11 +477,22 @@ module ActiveSupport
341
477
  end
342
478
 
343
479
  def transfer_time_values_to_utc_constructor(time)
344
- ::Time.utc_time(time.year, time.month, time.day, time.hour, time.min, time.sec, time.respond_to?(:usec) ? time.usec : 0)
480
+ ::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + time.subsec)
345
481
  end
346
482
 
347
483
  def duration_of_variable_length?(obj)
348
- ActiveSupport::Duration === obj && obj.parts.any? {|p| p[0].in?([:years, :months, :days]) }
484
+ ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include?(p[0]) }
485
+ end
486
+
487
+ def wrap_with_time_zone(time)
488
+ if time.acts_like?(:time)
489
+ periods = time_zone.periods_for_local(time)
490
+ self.class.new(nil, time_zone, time, periods.include?(period) ? period : nil)
491
+ elsif time.is_a?(Range)
492
+ wrap_with_time_zone(time.begin)..wrap_with_time_zone(time.end)
493
+ else
494
+ time
495
+ end
349
496
  end
350
497
  end
351
498
  end