activesupport 5.0.0 → 6.1.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 (268) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +343 -590
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -4
  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 +11 -5
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +45 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +81 -79
  13. data/lib/active_support/cache/memory_store.rb +69 -41
  14. data/lib/active_support/cache/null_store.rb +11 -4
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +74 -37
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +332 -161
  19. data/lib/active_support/callbacks.rb +657 -586
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +59 -19
  23. data/lib/active_support/configurable.rb +15 -17
  24. data/lib/active_support/configuration_file.rb +46 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +20 -18
  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 +3 -1
  30. data/lib/active_support/core_ext/array/inquiry.rb +3 -1
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +9 -7
  33. data/lib/active_support/core_ext/benchmark.rb +5 -3
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -26
  39. data/lib/active_support/core_ext/class.rb +4 -2
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +3 -1
  42. data/lib/active_support/core_ext/date/calculations.rb +16 -13
  43. data/lib/active_support/core_ext/date/conversions.rb +23 -21
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +7 -5
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
  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 +3 -1
  51. data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
  53. data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +165 -29
  58. data/lib/active_support/core_ext/file/atomic.rb +7 -5
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/conversions.rb +40 -39
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
  65. data/lib/active_support/core_ext/hash/keys.rb +9 -36
  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 +3 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +5 -4
  77. data/lib/active_support/core_ext/load_error.rb +2 -23
  78. data/lib/active_support/core_ext/marshal.rb +6 -2
  79. data/lib/active_support/core_ext/module/aliasing.rb +5 -48
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
  84. data/lib/active_support/core_ext/module/concerning.rb +16 -11
  85. data/lib/active_support/core_ext/module/delegation.rb +159 -44
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +23 -26
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +13 -12
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
  94. data/lib/active_support/core_ext/numeric/time.rb +18 -26
  95. data/lib/active_support/core_ext/numeric.rb +5 -4
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +14 -2
  98. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  99. data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
  100. data/lib/active_support/core_ext/object/duplicable.rb +13 -62
  101. data/lib/active_support/core_ext/object/inclusion.rb +3 -1
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +42 -15
  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 +20 -8
  107. data/lib/active_support/core_ext/object/with_options.rb +15 -2
  108. data/lib/active_support/core_ext/object.rb +14 -12
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  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 +28 -6
  117. data/lib/active_support/core_ext/string/access.rb +9 -18
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +47 -4
  122. data/lib/active_support/core_ext/string/indent.rb +6 -4
  123. data/lib/active_support/core_ext/string/inflections.rb +78 -29
  124. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  125. data/lib/active_support/core_ext/string/multibyte.rb +10 -5
  126. data/lib/active_support/core_ext/string/output_safety.rb +86 -31
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  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 +117 -45
  135. data/lib/active_support/core_ext/time/compatibility.rb +13 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +18 -12
  137. data/lib/active_support/core_ext/time/zones.rb +9 -7
  138. data/lib/active_support/core_ext/time.rb +7 -5
  139. data/lib/active_support/core_ext/uri.rb +12 -7
  140. data/lib/active_support/core_ext.rb +3 -2
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +208 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +7 -1
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  146. data/lib/active_support/dependencies.rb +172 -98
  147. data/lib/active_support/deprecation/behaviors.rb +45 -13
  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 +32 -17
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
  153. data/lib/active_support/deprecation/reporting.rb +61 -16
  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 +20 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +67 -66
  158. data/lib/active_support/duration/iso8601_serializer.rb +25 -17
  159. data/lib/active_support/duration.rb +349 -46
  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 +88 -112
  164. data/lib/active_support/execution_wrapper.rb +25 -13
  165. data/lib/active_support/executor.rb +3 -1
  166. data/lib/active_support/file_update_checker.rb +56 -51
  167. data/lib/active_support/fork_tracker.rb +62 -0
  168. data/lib/active_support/gem_version.rb +4 -2
  169. data/lib/active_support/gzip.rb +7 -5
  170. data/lib/active_support/hash_with_indifferent_access.rb +153 -49
  171. data/lib/active_support/i18n.rb +9 -6
  172. data/lib/active_support/i18n_railtie.rb +30 -20
  173. data/lib/active_support/inflections.rb +13 -11
  174. data/lib/active_support/inflector/inflections.rb +28 -15
  175. data/lib/active_support/inflector/methods.rb +120 -109
  176. data/lib/active_support/inflector/transliterate.rb +60 -25
  177. data/lib/active_support/inflector.rb +7 -5
  178. data/lib/active_support/json/decoding.rb +30 -29
  179. data/lib/active_support/json/encoding.rb +22 -11
  180. data/lib/active_support/json.rb +4 -2
  181. data/lib/active_support/key_generator.rb +6 -36
  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 +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +11 -9
  186. data/lib/active_support/log_subscriber.rb +51 -18
  187. data/lib/active_support/logger.rb +9 -22
  188. data/lib/active_support/logger_silence.rb +14 -21
  189. data/lib/active_support/logger_thread_safe_level.rb +55 -8
  190. data/lib/active_support/message_encryptor.rb +170 -53
  191. data/lib/active_support/message_verifier.rb +91 -20
  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 +24 -78
  196. data/lib/active_support/multibyte/unicode.rb +21 -352
  197. data/lib/active_support/multibyte.rb +4 -2
  198. data/lib/active_support/notifications/fanout.rb +121 -19
  199. data/lib/active_support/notifications/instrumenter.rb +78 -14
  200. data/lib/active_support/notifications.rb +80 -12
  201. data/lib/active_support/number_helper/number_converter.rb +17 -16
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
  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 +5 -4
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
  209. data/lib/active_support/number_helper/rounding_helper.rb +50 -0
  210. data/lib/active_support/number_helper.rb +45 -16
  211. data/lib/active_support/option_merger.rb +25 -4
  212. data/lib/active_support/ordered_hash.rb +6 -4
  213. data/lib/active_support/ordered_options.rb +23 -9
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +7 -5
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +8 -9
  218. data/lib/active_support/railtie.rb +62 -11
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +20 -11
  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 +12 -3
  224. data/lib/active_support/subscriber.rb +77 -23
  225. data/lib/active_support/tagged_logging.rb +52 -17
  226. data/lib/active_support/test_case.rb +106 -29
  227. data/lib/active_support/testing/assertions.rb +144 -8
  228. data/lib/active_support/testing/autorun.rb +5 -10
  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 +4 -2
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +19 -24
  234. data/lib/active_support/testing/method_call_assertions.rb +31 -2
  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 +30 -29
  240. data/lib/active_support/testing/tagged_logging.rb +3 -1
  241. data/lib/active_support/testing/time_helpers.rb +125 -24
  242. data/lib/active_support/time.rb +14 -12
  243. data/lib/active_support/time_with_zone.rb +142 -55
  244. data/lib/active_support/values/time_zone.rb +160 -53
  245. data/lib/active_support/version.rb +3 -1
  246. data/lib/active_support/xml_mini/jdom.rb +115 -114
  247. data/lib/active_support/xml_mini/libxml.rb +15 -14
  248. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  249. data/lib/active_support/xml_mini/nokogiri.rb +13 -13
  250. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  251. data/lib/active_support/xml_mini/rexml.rb +18 -9
  252. data/lib/active_support/xml_mini.rb +44 -42
  253. data/lib/active_support.rb +19 -10
  254. metadata +79 -37
  255. data/lib/active_support/concurrency/latch.rb +0 -19
  256. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  257. data/lib/active_support/core_ext/hash/compact.rb +0 -20
  258. data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
  259. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  260. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  261. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  262. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  263. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  264. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  265. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  266. data/lib/active_support/core_ext/struct.rb +0 -3
  267. data/lib/active_support/core_ext/time/marshal.rb +0 -3
  268. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,15 +1,18 @@
1
- require 'active_support/core_ext/object/try'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/try"
4
+ require "active_support/core_ext/date_time/conversions"
2
5
 
3
6
  module DateAndTime
4
7
  module Calculations
5
8
  DAYS_INTO_WEEK = {
6
- :monday => 0,
7
- :tuesday => 1,
8
- :wednesday => 2,
9
- :thursday => 3,
10
- :friday => 4,
11
- :saturday => 5,
12
- :sunday => 6
9
+ sunday: 0,
10
+ monday: 1,
11
+ tuesday: 2,
12
+ wednesday: 3,
13
+ thursday: 4,
14
+ friday: 5,
15
+ saturday: 6
13
16
  }
14
17
  WEEKEND_DAYS = [ 6, 0 ]
15
18
 
@@ -18,26 +21,28 @@ module DateAndTime
18
21
  advance(days: -1)
19
22
  end
20
23
 
21
- # Returns a new date/time representing the previous day.
22
- def prev_day
23
- advance(days: -1)
24
- end
25
-
26
24
  # Returns a new date/time representing tomorrow.
27
25
  def tomorrow
28
26
  advance(days: 1)
29
27
  end
30
28
 
31
- # Returns a new date/time representing the next day.
32
- def next_day
33
- advance(days: 1)
34
- end
35
-
36
29
  # Returns true if the date/time is today.
37
30
  def today?
38
31
  to_date == ::Date.current
39
32
  end
40
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
+
41
46
  # Returns true if the date/time is in the past.
42
47
  def past?
43
48
  self < self.class.current
@@ -58,44 +63,54 @@ module DateAndTime
58
63
  !WEEKEND_DAYS.include?(wday)
59
64
  end
60
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
+
61
76
  # Returns a new date/time the specified number of days ago.
62
77
  def days_ago(days)
63
- advance(:days => -days)
78
+ advance(days: -days)
64
79
  end
65
80
 
66
81
  # Returns a new date/time the specified number of days in the future.
67
82
  def days_since(days)
68
- advance(:days => days)
83
+ advance(days: days)
69
84
  end
70
85
 
71
86
  # Returns a new date/time the specified number of weeks ago.
72
87
  def weeks_ago(weeks)
73
- advance(:weeks => -weeks)
88
+ advance(weeks: -weeks)
74
89
  end
75
90
 
76
91
  # Returns a new date/time the specified number of weeks in the future.
77
92
  def weeks_since(weeks)
78
- advance(:weeks => weeks)
93
+ advance(weeks: weeks)
79
94
  end
80
95
 
81
96
  # Returns a new date/time the specified number of months ago.
82
97
  def months_ago(months)
83
- advance(:months => -months)
98
+ advance(months: -months)
84
99
  end
85
100
 
86
101
  # Returns a new date/time the specified number of months in the future.
87
102
  def months_since(months)
88
- advance(:months => months)
103
+ advance(months: months)
89
104
  end
90
105
 
91
106
  # Returns a new date/time the specified number of years ago.
92
107
  def years_ago(years)
93
- advance(:years => -years)
108
+ advance(years: -years)
94
109
  end
95
110
 
96
111
  # Returns a new date/time the specified number of years in the future.
97
112
  def years_since(years)
98
- advance(:years => years)
113
+ advance(years: years)
99
114
  end
100
115
 
101
116
  # Returns a new date/time at the start of the month.
@@ -108,7 +123,7 @@ module DateAndTime
108
123
  # now = DateTime.current # => Thu, 18 Jun 2015 15:23:13 +0000
109
124
  # now.beginning_of_month # => Mon, 01 Jun 2015 00:00:00 +0000
110
125
  def beginning_of_month
111
- first_hour(change(:day => 1))
126
+ first_hour(change(day: 1))
112
127
  end
113
128
  alias :at_beginning_of_month :beginning_of_month
114
129
 
@@ -122,8 +137,8 @@ module DateAndTime
122
137
  # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
123
138
  # now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
124
139
  def beginning_of_quarter
125
- first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
126
- 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)
127
142
  end
128
143
  alias :at_beginning_of_quarter :beginning_of_quarter
129
144
 
@@ -137,8 +152,8 @@ module DateAndTime
137
152
  # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
138
153
  # now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
139
154
  def end_of_quarter
140
- last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
141
- 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
142
157
  end
143
158
  alias :at_end_of_quarter :end_of_quarter
144
159
 
@@ -152,7 +167,7 @@ module DateAndTime
152
167
  # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
153
168
  # now.beginning_of_year # => Thu, 01 Jan 2015 00:00:00 +0000
154
169
  def beginning_of_year
155
- change(:month => 1).beginning_of_month
170
+ change(month: 1).beginning_of_month
156
171
  end
157
172
  alias :at_beginning_of_year :beginning_of_year
158
173
 
@@ -186,21 +201,11 @@ module DateAndTime
186
201
  end
187
202
  end
188
203
 
189
- # Short-hand for months_since(1).
190
- def next_month
191
- months_since(1)
192
- end
193
-
194
204
  # Short-hand for months_since(3)
195
205
  def next_quarter
196
206
  months_since(3)
197
207
  end
198
208
 
199
- # Short-hand for years_since(1).
200
- def next_year
201
- years_since(1)
202
- end
203
-
204
209
  # Returns a new date/time representing the given day in the previous week.
205
210
  # Week is assumed to start on +start_day+, default is
206
211
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
@@ -222,10 +227,9 @@ module DateAndTime
222
227
  alias_method :last_weekday, :prev_weekday
223
228
 
224
229
  # Short-hand for months_ago(1).
225
- def prev_month
230
+ def last_month
226
231
  months_ago(1)
227
232
  end
228
- alias_method :last_month, :prev_month
229
233
 
230
234
  # Short-hand for months_ago(3).
231
235
  def prev_quarter
@@ -234,18 +238,16 @@ module DateAndTime
234
238
  alias_method :last_quarter, :prev_quarter
235
239
 
236
240
  # Short-hand for years_ago(1).
237
- def prev_year
241
+ def last_year
238
242
  years_ago(1)
239
243
  end
240
- alias_method :last_year, :prev_year
241
244
 
242
245
  # Returns the number of days to the start of the week on the given day.
243
246
  # Week is assumed to start on +start_day+, default is
244
247
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
245
248
  def days_to_week_start(start_day = Date.beginning_of_week)
246
- start_day_number = DAYS_INTO_WEEK[start_day]
247
- current_day_number = wday != 0 ? wday - 1 : 6
248
- (current_day_number - start_day_number) % 7
249
+ start_day_number = DAYS_INTO_WEEK.fetch(start_day)
250
+ (wday - start_day_number) % 7
249
251
  end
250
252
 
251
253
  # Returns a new date/time representing the start of this week on the given day.
@@ -290,12 +292,17 @@ module DateAndTime
290
292
  # Returns a new date/time representing the end of the year.
291
293
  # DateTime objects will have a time set to 23:59:59.
292
294
  def end_of_year
293
- change(:month => 12).end_of_month
295
+ change(month: 12).end_of_month
294
296
  end
295
297
  alias :at_end_of_year :end_of_year
296
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
+
297
304
  # Returns a Range representing the whole week of the current date/time.
298
- # 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.
299
306
  def all_week(start_day = Date.beginning_of_week)
300
307
  beginning_of_week(start_day)..end_of_week(start_day)
301
308
  end
@@ -315,6 +322,28 @@ module DateAndTime
315
322
  beginning_of_year..end_of_year
316
323
  end
317
324
 
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)
334
+ end
335
+
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)
345
+ end
346
+
318
347
  private
319
348
  def first_hour(date_or_time)
320
349
  date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
@@ -325,11 +354,11 @@ module DateAndTime
325
354
  end
326
355
 
327
356
  def days_span(day)
328
- (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
357
+ (DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
329
358
  end
330
359
 
331
360
  def copy_time_to(other)
332
- other.change(hour: hour, min: min, sec: sec, usec: try(:usec))
361
+ other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
333
362
  end
334
363
  end
335
364
  end
@@ -1,4 +1,6 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/attribute_accessors"
2
4
 
3
5
  module DateAndTime
4
6
  module Compatibility
@@ -9,10 +11,21 @@ module DateAndTime
9
11
  # of the receiver. For backwards compatibility we're overriding
10
12
  # this behavior, but new apps will have an initializer that sets
11
13
  # this to true, because the new behavior is preferred.
12
- mattr_accessor(:preserve_timezone, instance_writer: false) { false }
14
+ mattr_accessor :preserve_timezone, instance_writer: false, default: false
13
15
 
14
- def to_time
15
- preserve_timezone ? getlocal(utc_offset) : getlocal
16
- end
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
17
30
  end
18
31
  end
@@ -1,3 +1,5 @@
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
@@ -22,19 +24,17 @@ module DateAndTime
22
24
  if time_zone
23
25
  time_with_zone(time, time_zone)
24
26
  else
25
- time || self.to_time
27
+ time || to_time
26
28
  end
27
29
  end
28
30
 
29
31
  private
30
-
31
- def time_with_zone(time, zone)
32
- if time
33
- ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
34
- else
35
- 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
36
38
  end
37
- end
38
39
  end
39
40
  end
40
-
@@ -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?.
@@ -1,4 +1,6 @@
1
- require 'date'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
2
4
 
3
5
  class DateTime #:nodoc:
4
6
  # No DateTime is ever blank:
@@ -1,4 +1,6 @@
1
- require 'date'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
2
4
 
3
5
  class DateTime
4
6
  class << self
@@ -47,13 +49,23 @@ class DateTime
47
49
  # DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => DateTime.new(1981, 8, 1, 22, 35, 0)
48
50
  # DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
49
51
  def change(options)
52
+ if new_nsec = options[:nsec]
53
+ raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
54
+ new_fraction = Rational(new_nsec, 1000000000)
55
+ else
56
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
57
+ new_fraction = Rational(new_usec, 1000000)
58
+ end
59
+
60
+ raise ArgumentError, "argument out of range" if new_fraction >= 1
61
+
50
62
  ::DateTime.civil(
51
63
  options.fetch(:year, year),
52
64
  options.fetch(:month, month),
53
65
  options.fetch(:day, day),
54
66
  options.fetch(:hour, hour),
55
67
  options.fetch(:min, options[:hour] ? 0 : min),
56
- options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec + sec_fraction),
68
+ options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
57
69
  options.fetch(:offset, offset),
58
70
  options.fetch(:start, start)
59
71
  )
@@ -75,7 +87,7 @@ class DateTime
75
87
  end
76
88
 
77
89
  d = to_date.advance(options)
78
- datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
90
+ datetime_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
79
91
  seconds_to_advance = \
80
92
  options.fetch(:seconds, 0) +
81
93
  options.fetch(:minutes, 0) * 60 +
@@ -98,13 +110,13 @@ class DateTime
98
110
  # instance time. Do not use this method in combination with x.months, use
99
111
  # months_since instead!
100
112
  def since(seconds)
101
- self + Rational(seconds.round, 86400)
113
+ self + Rational(seconds, 86400)
102
114
  end
103
115
  alias :in :since
104
116
 
105
117
  # Returns a new DateTime representing the start of the day (0:00).
106
118
  def beginning_of_day
107
- change(:hour => 0)
119
+ change(hour: 0)
108
120
  end
109
121
  alias :midnight :beginning_of_day
110
122
  alias :at_midnight :beginning_of_day
@@ -112,7 +124,7 @@ class DateTime
112
124
 
113
125
  # Returns a new DateTime representing the middle of the day (12:00)
114
126
  def middle_of_day
115
- change(:hour => 12)
127
+ change(hour: 12)
116
128
  end
117
129
  alias :midday :middle_of_day
118
130
  alias :noon :middle_of_day
@@ -122,31 +134,31 @@ class DateTime
122
134
 
123
135
  # Returns a new DateTime representing the end of the day (23:59:59).
124
136
  def end_of_day
125
- change(:hour => 23, :min => 59, :sec => 59)
137
+ change(hour: 23, min: 59, sec: 59, usec: Rational(999999999, 1000))
126
138
  end
127
139
  alias :at_end_of_day :end_of_day
128
140
 
129
141
  # Returns a new DateTime representing the start of the hour (hh:00:00).
130
142
  def beginning_of_hour
131
- change(:min => 0)
143
+ change(min: 0)
132
144
  end
133
145
  alias :at_beginning_of_hour :beginning_of_hour
134
146
 
135
147
  # Returns a new DateTime representing the end of the hour (hh:59:59).
136
148
  def end_of_hour
137
- change(:min => 59, :sec => 59)
149
+ change(min: 59, sec: 59, usec: Rational(999999999, 1000))
138
150
  end
139
151
  alias :at_end_of_hour :end_of_hour
140
152
 
141
153
  # Returns a new DateTime representing the start of the minute (hh:mm:00).
142
154
  def beginning_of_minute
143
- change(:sec => 0)
155
+ change(sec: 0)
144
156
  end
145
157
  alias :at_beginning_of_minute :beginning_of_minute
146
158
 
147
159
  # Returns a new DateTime representing the end of the minute (hh:mm:59).
148
160
  def end_of_minute
149
- change(:sec => 59)
161
+ change(sec: 59, usec: Rational(999999999, 1000))
150
162
  end
151
163
  alias :at_end_of_minute :end_of_minute
152
164
 
@@ -1,5 +1,18 @@
1
- require 'active_support/core_ext/date_and_time/compatibility'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/date_and_time/compatibility"
4
+ require "active_support/core_ext/module/redefine_method"
2
5
 
3
6
  class DateTime
4
- prepend DateAndTime::Compatibility
7
+ include DateAndTime::Compatibility
8
+
9
+ silence_redefinition_of_method :to_time
10
+
11
+ # Either return an instance of +Time+ with the same UTC offset
12
+ # as +self+ or an instance of +Time+ representing the same time
13
+ # in the local system timezone depending on the setting of
14
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
15
+ def to_time
16
+ preserve_timezone ? getlocal(utc_offset) : getlocal
17
+ end
5
18
  end
@@ -1,8 +1,10 @@
1
- require 'date'
2
- require 'active_support/inflector/methods'
3
- require 'active_support/core_ext/time/conversions'
4
- require 'active_support/core_ext/date_time/calculations'
5
- require 'active_support/values/time_zone'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/inflector/methods"
5
+ require "active_support/core_ext/time/conversions"
6
+ require "active_support/core_ext/date_time/calculations"
7
+ require "active_support/values/time_zone"
6
8
 
7
9
  class DateTime
8
10
  # Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
@@ -64,7 +66,7 @@ class DateTime
64
66
  # # => Sun, 01 Jan 2012 00:00:00 +0300
65
67
  # DateTime.civil_from_format :local, 2012, 12, 17
66
68
  # # => Mon, 17 Dec 2012 00:00:00 +0000
67
- def self.civil_from_format(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0)
69
+ def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)
68
70
  if utc_or_local.to_sym == :local
69
71
  offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
70
72
  else
@@ -94,12 +96,11 @@ class DateTime
94
96
  end
95
97
 
96
98
  private
99
+ def offset_in_seconds
100
+ (offset * 86400).to_i
101
+ end
97
102
 
98
- def offset_in_seconds
99
- (offset * 86400).to_i
100
- end
101
-
102
- def seconds_since_unix_epoch
103
- (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
104
- end
103
+ def seconds_since_unix_epoch
104
+ (jd - 2440588) * 86400 - offset_in_seconds + seconds_since_midnight
105
+ end
105
106
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/date_time/acts_like'
2
- require 'active_support/core_ext/date_time/blank'
3
- require 'active_support/core_ext/date_time/calculations'
4
- require 'active_support/core_ext/date_time/compatibility'
5
- require 'active_support/core_ext/date_time/conversions'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/date_time/acts_like"
4
+ require "active_support/core_ext/date_time/blank"
5
+ require "active_support/core_ext/date_time/calculations"
6
+ require "active_support/core_ext/date_time/compatibility"
7
+ require "active_support/core_ext/date_time/conversions"
@@ -1,4 +1,6 @@
1
- require 'securerandom'
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
2
4
 
3
5
  module Digest
4
6
  module UUID
@@ -12,7 +14,7 @@ module Digest
12
14
  # Using Digest::MD5 generates version 3 UUIDs; Digest::SHA1 generates version 5 UUIDs.
13
15
  # uuid_from_hash always generates the same UUID for a given name and namespace combination.
14
16
  #
15
- # See RFC 4122 for details of UUID at: http://www.ietf.org/rfc/rfc4122.txt
17
+ # See RFC 4122 for details of UUID at: https://www.ietf.org/rfc/rfc4122.txt
16
18
  def self.uuid_from_hash(hash_class, uuid_namespace, name)
17
19
  if hash_class == Digest::MD5
18
20
  version = 3
@@ -26,7 +28,7 @@ module Digest
26
28
  hash.update(uuid_namespace)
27
29
  hash.update(name)
28
30
 
29
- ary = hash.digest.unpack('NnnnnN')
31
+ ary = hash.digest.unpack("NnnnnN")
30
32
  ary[2] = (ary[2] & 0x0FFF) | (version << 12)
31
33
  ary[3] = (ary[3] & 0x3FFF) | 0x8000
32
34
 
@@ -35,12 +37,12 @@ module Digest
35
37
 
36
38
  # Convenience method for uuid_from_hash using Digest::MD5.
37
39
  def self.uuid_v3(uuid_namespace, name)
38
- self.uuid_from_hash(Digest::MD5, uuid_namespace, name)
40
+ uuid_from_hash(Digest::MD5, uuid_namespace, name)
39
41
  end
40
42
 
41
43
  # Convenience method for uuid_from_hash using Digest::SHA1.
42
44
  def self.uuid_v5(uuid_namespace, name)
43
- self.uuid_from_hash(Digest::SHA1, uuid_namespace, name)
45
+ uuid_from_hash(Digest::SHA1, uuid_namespace, name)
44
46
  end
45
47
 
46
48
  # Convenience method for SecureRandom.uuid.
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/digest/uuid"