activesupport 4.2.11.1 → 6.1.7.3

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 (272) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +464 -391
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +50 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +61 -55
  12. data/lib/active_support/cache/mem_cache_store.rb +115 -100
  13. data/lib/active_support/cache/memory_store.rb +81 -58
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +90 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +386 -225
  19. data/lib/active_support/callbacks.rb +661 -594
  20. data/lib/active_support/concern.rb +80 -7
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +16 -17
  24. data/lib/active_support/configuration_file.rb +51 -0
  25. data/lib/active_support/core_ext/array/access.rb +41 -1
  26. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  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/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +5 -3
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +52 -48
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -25
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +27 -24
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +167 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +19 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +8 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +186 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +13 -10
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +20 -43
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +10 -9
  69. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +11 -18
  72. data/lib/active_support/core_ext/integer.rb +5 -3
  73. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +5 -5
  77. data/lib/active_support/core_ext/load_error.rb +3 -22
  78. data/lib/active_support/core_ext/marshal.rb +10 -8
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +63 -69
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +148 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +19 -14
  85. data/lib/active_support/core_ext/module/delegation.rb +164 -51
  86. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  87. data/lib/active_support/core_ext/module/introspection.rb +23 -22
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  90. data/lib/active_support/core_ext/module.rb +13 -11
  91. data/lib/active_support/core_ext/name_error.rb +51 -4
  92. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +133 -136
  94. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  95. data/lib/active_support/core_ext/numeric.rb +5 -3
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +27 -3
  98. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  99. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  100. data/lib/active_support/core_ext/object/duplicable.rb +13 -93
  101. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  102. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  103. data/lib/active_support/core_ext/object/json.rb +63 -21
  104. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  105. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  106. data/lib/active_support/core_ext/object/try.rb +81 -23
  107. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  108. data/lib/active_support/core_ext/object.rb +14 -13
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  111. data/lib/active_support/core_ext/range/each.rb +18 -17
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +7 -4
  115. data/lib/active_support/core_ext/regexp.rb +10 -1
  116. data/lib/active_support/core_ext/securerandom.rb +45 -0
  117. data/lib/active_support/core_ext/string/access.rb +9 -18
  118. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  119. data/lib/active_support/core_ext/string/conversions.rb +8 -4
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +48 -6
  122. data/lib/active_support/core_ext/string/indent.rb +6 -4
  123. data/lib/active_support/core_ext/string/inflections.rb +102 -26
  124. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  125. data/lib/active_support/core_ext/string/multibyte.rb +18 -9
  126. data/lib/active_support/core_ext/string/output_safety.rb +125 -40
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +6 -5
  129. data/lib/active_support/core_ext/string/zones.rb +4 -2
  130. data/lib/active_support/core_ext/string.rb +15 -13
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  134. data/lib/active_support/core_ext/time/calculations.rb +137 -53
  135. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +22 -13
  137. data/lib/active_support/core_ext/time/zones.rb +41 -7
  138. data/lib/active_support/core_ext/time.rb +7 -6
  139. data/lib/active_support/core_ext/uri.rb +11 -8
  140. data/lib/active_support/core_ext.rb +3 -1
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +210 -0
  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/dependencies/zeitwerk_integration.rb +120 -0
  146. data/lib/active_support/dependencies.rb +241 -175
  147. data/lib/active_support/deprecation/behaviors.rb +58 -12
  148. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  151. data/lib/active_support/deprecation/method_wrappers.rb +62 -21
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  153. data/lib/active_support/deprecation/reporting.rb +81 -18
  154. data/lib/active_support/deprecation.rb +17 -9
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +22 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  158. data/lib/active_support/duration/iso8601_serializer.rb +59 -0
  159. data/lib/active_support/duration.rb +364 -39
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +170 -0
  164. data/lib/active_support/execution_wrapper.rb +132 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/fork_tracker.rb +64 -0
  168. data/lib/active_support/gem_version.rb +7 -5
  169. data/lib/active_support/gzip.rb +7 -5
  170. data/lib/active_support/hash_with_indifferent_access.rb +171 -48
  171. data/lib/active_support/i18n.rb +9 -6
  172. data/lib/active_support/i18n_railtie.rb +47 -16
  173. data/lib/active_support/inflections.rb +13 -11
  174. data/lib/active_support/inflector/inflections.rb +58 -14
  175. data/lib/active_support/inflector/methods.rb +186 -169
  176. data/lib/active_support/inflector/transliterate.rb +83 -33
  177. data/lib/active_support/inflector.rb +7 -5
  178. data/lib/active_support/json/decoding.rb +32 -30
  179. data/lib/active_support/json/encoding.rb +22 -61
  180. data/lib/active_support/json.rb +4 -2
  181. data/lib/active_support/key_generator.rb +11 -43
  182. data/lib/active_support/lazy_load_hooks.rb +53 -20
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +9 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  186. data/lib/active_support/log_subscriber.rb +52 -19
  187. data/lib/active_support/logger.rb +10 -24
  188. data/lib/active_support/logger_silence.rb +14 -20
  189. data/lib/active_support/logger_thread_safe_level.rb +56 -10
  190. data/lib/active_support/message_encryptor.rb +167 -57
  191. data/lib/active_support/message_verifier.rb +151 -18
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +35 -80
  196. data/lib/active_support/multibyte/unicode.rb +22 -330
  197. data/lib/active_support/multibyte.rb +4 -2
  198. data/lib/active_support/notifications/fanout.rb +125 -23
  199. data/lib/active_support/notifications/instrumenter.rb +98 -16
  200. data/lib/active_support/notifications.rb +82 -14
  201. data/lib/active_support/number_helper/number_converter.rb +17 -16
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -14
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +14 -11
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +12 -10
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +29 -57
  209. data/lib/active_support/number_helper/rounding_helper.rb +50 -0
  210. data/lib/active_support/number_helper.rb +123 -71
  211. data/lib/active_support/option_merger.rb +25 -4
  212. data/lib/active_support/ordered_hash.rb +7 -5
  213. data/lib/active_support/ordered_options.rb +35 -7
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +10 -4
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +10 -11
  218. data/lib/active_support/railtie.rb +66 -10
  219. data/lib/active_support/reloader.rb +130 -0
  220. data/lib/active_support/rescuable.rb +112 -57
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +13 -4
  224. data/lib/active_support/subscriber.rb +80 -31
  225. data/lib/active_support/tagged_logging.rb +54 -17
  226. data/lib/active_support/test_case.rb +107 -44
  227. data/lib/active_support/testing/assertions.rb +158 -20
  228. data/lib/active_support/testing/autorun.rb +4 -2
  229. data/lib/active_support/testing/constant_lookup.rb +2 -1
  230. data/lib/active_support/testing/declarative.rb +3 -1
  231. data/lib/active_support/testing/deprecation.rb +13 -10
  232. data/lib/active_support/testing/file_fixtures.rb +38 -0
  233. data/lib/active_support/testing/isolation.rb +35 -26
  234. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  239. data/lib/active_support/testing/stream.rb +43 -0
  240. data/lib/active_support/testing/tagged_logging.rb +3 -1
  241. data/lib/active_support/testing/time_helpers.rb +121 -20
  242. data/lib/active_support/time.rb +14 -12
  243. data/lib/active_support/time_with_zone.rb +215 -51
  244. data/lib/active_support/values/time_zone.rb +223 -71
  245. data/lib/active_support/version.rb +3 -1
  246. data/lib/active_support/xml_mini/jdom.rb +116 -115
  247. data/lib/active_support/xml_mini/libxml.rb +16 -13
  248. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  249. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  250. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  251. data/lib/active_support/xml_mini/rexml.rb +18 -9
  252. data/lib/active_support/xml_mini.rb +38 -46
  253. data/lib/active_support.rb +25 -11
  254. metadata +100 -43
  255. data/lib/active_support/concurrency/latch.rb +0 -27
  256. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  257. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  258. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  259. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  260. data/lib/active_support/core_ext/hash/compact.rb +0 -24
  261. data/lib/active_support/core_ext/hash/transform_values.rb +0 -23
  262. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  263. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  264. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  265. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  266. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  267. data/lib/active_support/core_ext/object/itself.rb +0 -15
  268. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  269. data/lib/active_support/core_ext/struct.rb +0 -6
  270. data/lib/active_support/core_ext/thread.rb +0 -86
  271. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  272. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,30 +1,25 @@
1
- require 'date'
2
- require 'active_support/inflector/methods'
3
- require 'active_support/core_ext/date/zones'
4
- require 'active_support/core_ext/module/remove_method'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/inflector/methods"
5
+ require "active_support/core_ext/date/zones"
6
+ require "active_support/core_ext/module/redefine_method"
5
7
 
6
8
  class Date
7
9
  DATE_FORMATS = {
8
- :short => '%e %b',
9
- :long => '%B %e, %Y',
10
- :db => '%Y-%m-%d',
11
- :number => '%Y%m%d',
12
- :long_ordinal => lambda { |date|
10
+ short: "%d %b",
11
+ long: "%B %d, %Y",
12
+ db: "%Y-%m-%d",
13
+ inspect: "%Y-%m-%d",
14
+ number: "%Y%m%d",
15
+ long_ordinal: lambda { |date|
13
16
  day_format = ActiveSupport::Inflector.ordinalize(date.day)
14
17
  date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
15
18
  },
16
- :rfc822 => '%e %b %Y',
17
- :iso8601 => lambda { |date| date.iso8601 }
19
+ rfc822: "%d %b %Y",
20
+ iso8601: lambda { |date| date.iso8601 }
18
21
  }
19
22
 
20
- # Ruby 1.9 has Date#to_time which converts to localtime only.
21
- remove_method :to_time
22
-
23
- # Ruby 1.9 has Date#xmlschema which converts to a string without the time
24
- # component. This removal may generate an issue on FreeBSD, that's why we
25
- # need to use remove_possible_method here
26
- remove_possible_method :xmlschema
27
-
28
23
  # Convert to a formatted string. See DATE_FORMATS for predefined formats.
29
24
  #
30
25
  # This method is aliased to <tt>to_s</tt>.
@@ -65,24 +60,32 @@ class Date
65
60
 
66
61
  # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
67
62
  def readable_inspect
68
- strftime('%a, %d %b %Y')
63
+ strftime("%a, %d %b %Y")
69
64
  end
70
65
  alias_method :default_inspect, :inspect
71
66
  alias_method :inspect, :readable_inspect
72
67
 
68
+ silence_redefinition_of_method :to_time
69
+
73
70
  # Converts a Date instance to a Time, where the time is set to the beginning of the day.
74
71
  # The timezone can be either :local or :utc (default :local).
75
72
  #
76
73
  # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
77
74
  #
78
- # date.to_time # => Sat Nov 10 00:00:00 0800 2007
79
- # date.to_time(:local) # => Sat Nov 10 00:00:00 0800 2007
75
+ # date.to_time # => 2007-11-10 00:00:00 0800
76
+ # date.to_time(:local) # => 2007-11-10 00:00:00 0800
77
+ #
78
+ # date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
80
79
  #
81
- # date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007
80
+ # NOTE: The :local timezone is Ruby's *process* timezone, i.e. ENV['TZ'].
81
+ # If the *application's* timezone is needed, then use +in_time_zone+ instead.
82
82
  def to_time(form = :local)
83
- ::Time.send(form, year, month, day)
83
+ raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
84
+ ::Time.public_send(form, year, month, day)
84
85
  end
85
86
 
87
+ silence_redefinition_of_method :xmlschema
88
+
86
89
  # Returns a string which represents the time in used time zone as DateTime
87
90
  # defined by XML Schema:
88
91
  #
@@ -1,5 +1,7 @@
1
- require 'date'
2
- require 'active_support/core_ext/date_and_time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/core_ext/date_and_time/zones"
3
5
 
4
6
  class Date
5
7
  include DateAndTime::Zones
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/date/acts_like'
2
- require 'active_support/core_ext/date/calculations'
3
- require 'active_support/core_ext/date/conversions'
4
- require 'active_support/core_ext/date/zones'
1
+ # frozen_string_literal: true
5
2
 
3
+ require "active_support/core_ext/date/acts_like"
4
+ require "active_support/core_ext/date/blank"
5
+ require "active_support/core_ext/date/calculations"
6
+ require "active_support/core_ext/date/conversions"
7
+ require "active_support/core_ext/date/zones"
@@ -1,23 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/try"
4
+ require "active_support/core_ext/date_time/conversions"
5
+
1
6
  module DateAndTime
2
7
  module Calculations
3
8
  DAYS_INTO_WEEK = {
4
- :monday => 0,
5
- :tuesday => 1,
6
- :wednesday => 2,
7
- :thursday => 3,
8
- :friday => 4,
9
- :saturday => 5,
10
- :sunday => 6
9
+ sunday: 0,
10
+ monday: 1,
11
+ tuesday: 2,
12
+ wednesday: 3,
13
+ thursday: 4,
14
+ friday: 5,
15
+ saturday: 6
11
16
  }
17
+ WEEKEND_DAYS = [ 6, 0 ]
12
18
 
13
19
  # Returns a new date/time representing yesterday.
14
20
  def yesterday
15
- advance(:days => -1)
21
+ advance(days: -1)
16
22
  end
17
23
 
18
24
  # Returns a new date/time representing tomorrow.
19
25
  def tomorrow
20
- advance(:days => 1)
26
+ advance(days: 1)
21
27
  end
22
28
 
23
29
  # Returns true if the date/time is today.
@@ -25,6 +31,18 @@ module DateAndTime
25
31
  to_date == ::Date.current
26
32
  end
27
33
 
34
+ # Returns true if the date/time is tomorrow.
35
+ def tomorrow?
36
+ to_date == ::Date.current.tomorrow
37
+ end
38
+ alias :next_day? :tomorrow?
39
+
40
+ # Returns true if the date/time is yesterday.
41
+ def yesterday?
42
+ to_date == ::Date.current.yesterday
43
+ end
44
+ alias :prev_day? :yesterday?
45
+
28
46
  # Returns true if the date/time is in the past.
29
47
  def past?
30
48
  self < self.class.current
@@ -35,76 +53,121 @@ module DateAndTime
35
53
  self > self.class.current
36
54
  end
37
55
 
56
+ # Returns true if the date/time falls on a Saturday or Sunday.
57
+ def on_weekend?
58
+ WEEKEND_DAYS.include?(wday)
59
+ end
60
+
61
+ # Returns true if the date/time does not fall on a Saturday or Sunday.
62
+ def on_weekday?
63
+ !WEEKEND_DAYS.include?(wday)
64
+ end
65
+
66
+ # Returns true if the date/time falls before <tt>date_or_time</tt>.
67
+ def before?(date_or_time)
68
+ self < date_or_time
69
+ end
70
+
71
+ # Returns true if the date/time falls after <tt>date_or_time</tt>.
72
+ def after?(date_or_time)
73
+ self > date_or_time
74
+ end
75
+
38
76
  # Returns a new date/time the specified number of days ago.
39
77
  def days_ago(days)
40
- advance(:days => -days)
78
+ advance(days: -days)
41
79
  end
42
80
 
43
81
  # Returns a new date/time the specified number of days in the future.
44
82
  def days_since(days)
45
- advance(:days => days)
83
+ advance(days: days)
46
84
  end
47
85
 
48
86
  # Returns a new date/time the specified number of weeks ago.
49
87
  def weeks_ago(weeks)
50
- advance(:weeks => -weeks)
88
+ advance(weeks: -weeks)
51
89
  end
52
90
 
53
91
  # Returns a new date/time the specified number of weeks in the future.
54
92
  def weeks_since(weeks)
55
- advance(:weeks => weeks)
93
+ advance(weeks: weeks)
56
94
  end
57
95
 
58
96
  # Returns a new date/time the specified number of months ago.
59
97
  def months_ago(months)
60
- advance(:months => -months)
98
+ advance(months: -months)
61
99
  end
62
100
 
63
101
  # Returns a new date/time the specified number of months in the future.
64
102
  def months_since(months)
65
- advance(:months => months)
103
+ advance(months: months)
66
104
  end
67
105
 
68
106
  # Returns a new date/time the specified number of years ago.
69
107
  def years_ago(years)
70
- advance(:years => -years)
108
+ advance(years: -years)
71
109
  end
72
110
 
73
111
  # Returns a new date/time the specified number of years in the future.
74
112
  def years_since(years)
75
- advance(:years => years)
113
+ advance(years: years)
76
114
  end
77
115
 
78
116
  # Returns a new date/time at the start of the month.
79
- # DateTime objects will have a time set to 0:00.
117
+ #
118
+ # today = Date.today # => Thu, 18 Jun 2015
119
+ # today.beginning_of_month # => Mon, 01 Jun 2015
120
+ #
121
+ # +DateTime+ objects will have a time set to 0:00.
122
+ #
123
+ # now = DateTime.current # => Thu, 18 Jun 2015 15:23:13 +0000
124
+ # now.beginning_of_month # => Mon, 01 Jun 2015 00:00:00 +0000
80
125
  def beginning_of_month
81
- first_hour(change(:day => 1))
126
+ first_hour(change(day: 1))
82
127
  end
83
128
  alias :at_beginning_of_month :beginning_of_month
84
129
 
85
130
  # Returns a new date/time at the start of the quarter.
86
- # Example: 1st January, 1st July, 1st October.
87
- # DateTime objects will have a time set to 0:00.
131
+ #
132
+ # today = Date.today # => Fri, 10 Jul 2015
133
+ # today.beginning_of_quarter # => Wed, 01 Jul 2015
134
+ #
135
+ # +DateTime+ objects will have a time set to 0:00.
136
+ #
137
+ # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
138
+ # now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
88
139
  def beginning_of_quarter
89
- first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
90
- beginning_of_month.change(:month => first_quarter_month)
140
+ first_quarter_month = month - (2 + month) % 3
141
+ beginning_of_month.change(month: first_quarter_month)
91
142
  end
92
143
  alias :at_beginning_of_quarter :beginning_of_quarter
93
144
 
94
145
  # Returns a new date/time at the end of the quarter.
95
- # Example: 31st March, 30th June, 30th September.
96
- # DateTime objects will have a time set to 23:59:59.
146
+ #
147
+ # today = Date.today # => Fri, 10 Jul 2015
148
+ # today.end_of_quarter # => Wed, 30 Sep 2015
149
+ #
150
+ # +DateTime+ objects will have a time set to 23:59:59.
151
+ #
152
+ # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
153
+ # now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
97
154
  def end_of_quarter
98
- last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
99
- beginning_of_month.change(:month => last_quarter_month).end_of_month
155
+ last_quarter_month = month + (12 - month) % 3
156
+ beginning_of_month.change(month: last_quarter_month).end_of_month
100
157
  end
101
158
  alias :at_end_of_quarter :end_of_quarter
102
159
 
103
- # Return a new date/time at the beginning of the year.
104
- # Example: 1st January.
105
- # DateTime objects will have a time set to 0:00.
160
+ # Returns a new date/time at the beginning of the year.
161
+ #
162
+ # today = Date.today # => Fri, 10 Jul 2015
163
+ # today.beginning_of_year # => Thu, 01 Jan 2015
164
+ #
165
+ # +DateTime+ objects will have a time set to 0:00.
166
+ #
167
+ # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
168
+ # now.beginning_of_year # => Thu, 01 Jan 2015 00:00:00 +0000
106
169
  def beginning_of_year
107
- change(:month => 1).beginning_of_month
170
+ change(month: 1).beginning_of_month
108
171
  end
109
172
  alias :at_beginning_of_year :beginning_of_year
110
173
 
@@ -115,21 +178,27 @@ module DateAndTime
115
178
  #
116
179
  # The +given_day_in_next_week+ defaults to the beginning of the week
117
180
  # which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
181
+ # when set.
118
182
  #
119
183
  # today = Date.today # => Thu, 07 May 2015
120
184
  # today.next_week(:friday) # => Fri, 15 May 2015
121
185
  #
122
- # when set. +DateTime+ objects have their time set to 0:00.
186
+ # +DateTime+ objects have their time set to 0:00 unless +same_time+ is true.
123
187
  #
124
- # now = Time.current # => Thu, 07 May 2015 13:31:16 UTC +00:00
125
- # now.next_week # => Mon, 11 May 2015 00:00:00 UTC +00:00
126
- def next_week(given_day_in_next_week = Date.beginning_of_week)
127
- first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
188
+ # now = DateTime.current # => Thu, 07 May 2015 13:31:16 +0000
189
+ # now.next_week # => Mon, 11 May 2015 00:00:00 +0000
190
+ def next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false)
191
+ result = first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
192
+ same_time ? copy_time_to(result) : result
128
193
  end
129
194
 
130
- # Short-hand for months_since(1).
131
- def next_month
132
- months_since(1)
195
+ # Returns a new date/time representing the next weekday.
196
+ def next_weekday
197
+ if next_day.on_weekend?
198
+ next_week(:monday, same_time: true)
199
+ else
200
+ next_day
201
+ end
133
202
  end
134
203
 
135
204
  # Short-hand for months_since(3)
@@ -137,25 +206,30 @@ module DateAndTime
137
206
  months_since(3)
138
207
  end
139
208
 
140
- # Short-hand for years_since(1).
141
- def next_year
142
- years_since(1)
143
- end
144
-
145
209
  # Returns a new date/time representing the given day in the previous week.
146
210
  # Week is assumed to start on +start_day+, default is
147
211
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
148
- # DateTime objects have their time set to 0:00.
149
- def prev_week(start_day = Date.beginning_of_week)
150
- first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
212
+ # DateTime objects have their time set to 0:00 unless +same_time+ is true.
213
+ def prev_week(start_day = Date.beginning_of_week, same_time: false)
214
+ result = first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
215
+ same_time ? copy_time_to(result) : result
151
216
  end
152
217
  alias_method :last_week, :prev_week
153
218
 
219
+ # Returns a new date/time representing the previous weekday.
220
+ def prev_weekday
221
+ if prev_day.on_weekend?
222
+ copy_time_to(beginning_of_week(:friday))
223
+ else
224
+ prev_day
225
+ end
226
+ end
227
+ alias_method :last_weekday, :prev_weekday
228
+
154
229
  # Short-hand for months_ago(1).
155
- def prev_month
230
+ def last_month
156
231
  months_ago(1)
157
232
  end
158
- alias_method :last_month, :prev_month
159
233
 
160
234
  # Short-hand for months_ago(3).
161
235
  def prev_quarter
@@ -164,18 +238,16 @@ module DateAndTime
164
238
  alias_method :last_quarter, :prev_quarter
165
239
 
166
240
  # Short-hand for years_ago(1).
167
- def prev_year
241
+ def last_year
168
242
  years_ago(1)
169
243
  end
170
- alias_method :last_year, :prev_year
171
244
 
172
245
  # Returns the number of days to the start of the week on the given day.
173
246
  # Week is assumed to start on +start_day+, default is
174
247
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
175
248
  def days_to_week_start(start_day = Date.beginning_of_week)
176
- start_day_number = DAYS_INTO_WEEK[start_day]
177
- current_day_number = wday != 0 ? wday - 1 : 6
178
- (current_day_number - start_day_number) % 7
249
+ start_day_number = DAYS_INTO_WEEK.fetch(start_day)
250
+ (wday - start_day_number) % 7
179
251
  end
180
252
 
181
253
  # Returns a new date/time representing the start of this week on the given day.
@@ -220,12 +292,17 @@ module DateAndTime
220
292
  # Returns a new date/time representing the end of the year.
221
293
  # DateTime objects will have a time set to 23:59:59.
222
294
  def end_of_year
223
- change(:month => 12).end_of_month
295
+ change(month: 12).end_of_month
224
296
  end
225
297
  alias :at_end_of_year :end_of_year
226
298
 
299
+ # Returns a Range representing the whole day of the current date/time.
300
+ def all_day
301
+ beginning_of_day..end_of_day
302
+ end
303
+
227
304
  # Returns a Range representing the whole week of the current date/time.
228
- # Week starts on start_day, default is <tt>Date.week_start</tt> or <tt>config.week_start</tt> when set.
305
+ # Week starts on start_day, default is <tt>Date.beginning_of_week</tt> or <tt>config.beginning_of_week</tt> when set.
229
306
  def all_week(start_day = Date.beginning_of_week)
230
307
  beginning_of_week(start_day)..end_of_week(start_day)
231
308
  end
@@ -245,18 +322,43 @@ module DateAndTime
245
322
  beginning_of_year..end_of_year
246
323
  end
247
324
 
248
- private
249
-
250
- def first_hour(date_or_time)
251
- date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
325
+ # Returns a new date/time representing the next occurrence of the specified day of week.
326
+ #
327
+ # today = Date.today # => Thu, 14 Dec 2017
328
+ # today.next_occurring(:monday) # => Mon, 18 Dec 2017
329
+ # today.next_occurring(:thursday) # => Thu, 21 Dec 2017
330
+ def next_occurring(day_of_week)
331
+ from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
332
+ from_now += 7 unless from_now > 0
333
+ advance(days: from_now)
252
334
  end
253
335
 
254
- def last_hour(date_or_time)
255
- date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
336
+ # Returns a new date/time representing the previous occurrence of the specified day of week.
337
+ #
338
+ # today = Date.today # => Thu, 14 Dec 2017
339
+ # today.prev_occurring(:monday) # => Mon, 11 Dec 2017
340
+ # today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
341
+ def prev_occurring(day_of_week)
342
+ ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
343
+ ago += 7 unless ago > 0
344
+ advance(days: -ago)
256
345
  end
257
346
 
258
- def days_span(day)
259
- (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
260
- end
347
+ private
348
+ def first_hour(date_or_time)
349
+ date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
350
+ end
351
+
352
+ def last_hour(date_or_time)
353
+ date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
354
+ end
355
+
356
+ def days_span(day)
357
+ (DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
358
+ end
359
+
360
+ def copy_time_to(other)
361
+ other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
362
+ end
261
363
  end
262
364
  end
@@ -1,5 +1,6 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
2
- require 'active_support/core_ext/module/remove_method'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/attribute_accessors"
3
4
 
4
5
  module DateAndTime
5
6
  module Compatibility
@@ -10,6 +11,21 @@ module DateAndTime
10
11
  # of the receiver. For backwards compatibility we're overriding
11
12
  # this behavior, but new apps will have an initializer that sets
12
13
  # this to true, because the new behavior is preferred.
13
- mattr_accessor(:preserve_timezone, instance_writer: false) { false }
14
+ mattr_accessor :preserve_timezone, instance_writer: false, default: false
15
+
16
+ # Change the output of <tt>ActiveSupport::TimeZone.utc_to_local</tt>.
17
+ #
18
+ # When `true`, it returns local times with an UTC offset, with `false` local
19
+ # times are returned as UTC.
20
+ #
21
+ # # Given this zone:
22
+ # zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
23
+ #
24
+ # # With `utc_to_local_returns_utc_offset_times = false`, local time is converted to UTC:
25
+ # zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 UTC
26
+ #
27
+ # # With `utc_to_local_returns_utc_offset_times = true`, local time is returned with UTC offset:
28
+ # zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 -0500
29
+ mattr_accessor :utc_to_local_returns_utc_offset_times, instance_writer: false, default: false
14
30
  end
15
31
  end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DateAndTime
2
4
  module Zones
3
5
  # Returns the simultaneous time in <tt>Time.zone</tt> if a zone is given or
4
6
  # if Time.zone_default is set. Otherwise, it returns the current time.
5
7
  #
6
8
  # Time.zone = 'Hawaii' # => 'Hawaii'
7
- # DateTime.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
8
- # Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00
9
+ # Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
10
+ # Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00
9
11
  #
10
12
  # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
11
13
  # instead of the operating system's time zone.
@@ -14,8 +16,7 @@ module DateAndTime
14
16
  # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
15
17
  #
16
18
  # Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
17
- # DateTime.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
18
- # Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
19
+ # Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
19
20
  def in_time_zone(zone = ::Time.zone)
20
21
  time_zone = ::Time.find_zone! zone
21
22
  time = acts_like?(:time) ? self : nil
@@ -23,19 +24,17 @@ module DateAndTime
23
24
  if time_zone
24
25
  time_with_zone(time, time_zone)
25
26
  else
26
- time || self.to_time
27
+ time || to_time
27
28
  end
28
29
  end
29
30
 
30
31
  private
31
-
32
- def time_with_zone(time, zone)
33
- if time
34
- ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
35
- else
36
- ActiveSupport::TimeWithZone.new(nil, zone, to_time(:utc))
32
+ def time_with_zone(time, zone)
33
+ if time
34
+ ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
35
+ else
36
+ ActiveSupport::TimeWithZone.new(nil, zone, to_time(:utc))
37
+ end
37
38
  end
38
- end
39
39
  end
40
40
  end
41
-
@@ -1,5 +1,7 @@
1
- require 'date'
2
- require 'active_support/core_ext/object/acts_like'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/core_ext/object/acts_like"
3
5
 
4
6
  class DateTime
5
7
  # Duck-types as a Date-like class. See Object#acts_like?.
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ class DateTime #:nodoc:
6
+ # No DateTime is ever blank:
7
+ #
8
+ # DateTime.now.blank? # => false
9
+ #
10
+ # @return [false]
11
+ def blank?
12
+ false
13
+ end
14
+ end