activesupport 4.0.12 → 7.0.2.4

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 (295) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +249 -501
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -5
  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 +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +41 -13
  9. data/lib/active_support/benchmarkable.rb +7 -15
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +96 -74
  12. data/lib/active_support/cache/mem_cache_store.rb +211 -103
  13. data/lib/active_support/cache/memory_store.rb +90 -58
  14. data/lib/active_support/cache/null_store.rb +19 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +468 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +86 -83
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  18. data/lib/active_support/cache.rb +580 -241
  19. data/lib/active_support/callbacks.rb +812 -425
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +103 -14
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
  23. data/lib/active_support/concurrency/share_lock.rb +226 -0
  24. data/lib/active_support/configurable.rb +21 -19
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +47 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +35 -44
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +26 -16
  32. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  34. data/lib/active_support/core_ext/array.rb +10 -7
  35. data/lib/active_support/core_ext/benchmark.rb +5 -3
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  37. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  38. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  40. data/lib/active_support/core_ext/class/subclasses.rb +25 -26
  41. data/lib/active_support/core_ext/class.rb +4 -4
  42. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  43. data/lib/active_support/core_ext/date/blank.rb +14 -0
  44. data/lib/active_support/core_ext/date/calculations.rb +31 -18
  45. data/lib/active_support/core_ext/date/conversions.rb +43 -32
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +5 -34
  48. data/lib/active_support/core_ext/date.rb +7 -4
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  53. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  54. data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  56. data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +8 -4
  59. data/lib/active_support/core_ext/digest/uuid.rb +79 -0
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +249 -17
  62. data/lib/active_support/core_ext/file/atomic.rb +41 -32
  63. data/lib/active_support/core_ext/file.rb +3 -1
  64. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +14 -5
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +39 -56
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -23
  72. data/lib/active_support/core_ext/hash.rb +10 -8
  73. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +11 -33
  76. data/lib/active_support/core_ext/integer.rb +5 -3
  77. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  80. data/lib/active_support/core_ext/kernel.rb +5 -4
  81. data/lib/active_support/core_ext/load_error.rb +5 -21
  82. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  83. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  84. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
  87. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  88. data/lib/active_support/core_ext/module/delegation.rb +172 -45
  89. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  90. data/lib/active_support/core_ext/module/introspection.rb +23 -38
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -10
  94. data/lib/active_support/core_ext/name_error.rb +45 -4
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  99. data/lib/active_support/core_ext/numeric.rb +6 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +70 -20
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  104. data/lib/active_support/core_ext/object/duplicable.rb +17 -47
  105. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +244 -0
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  110. data/lib/active_support/core_ext/object/try.rb +106 -26
  111. data/lib/active_support/core_ext/object/with_options.rb +64 -5
  112. data/lib/active_support/core_ext/object.rb +14 -12
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +18 -17
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  121. data/lib/active_support/core_ext/range.rb +7 -4
  122. data/lib/active_support/core_ext/regexp.rb +10 -1
  123. data/lib/active_support/core_ext/securerandom.rb +45 -0
  124. data/lib/active_support/core_ext/string/access.rb +42 -51
  125. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  126. data/lib/active_support/core_ext/string/conversions.rb +18 -13
  127. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  128. data/lib/active_support/core_ext/string/filters.rb +97 -7
  129. data/lib/active_support/core_ext/string/indent.rb +6 -4
  130. data/lib/active_support/core_ext/string/inflections.rb +106 -25
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +18 -9
  133. data/lib/active_support/core_ext/string/output_safety.rb +227 -54
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +6 -5
  136. data/lib/active_support/core_ext/string/zones.rb +4 -1
  137. data/lib/active_support/core_ext/string.rb +15 -13
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  141. data/lib/active_support/core_ext/time/calculations.rb +178 -116
  142. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  143. data/lib/active_support/core_ext/time/conversions.rb +37 -25
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +44 -42
  146. data/lib/active_support/core_ext/time.rb +8 -5
  147. data/lib/active_support/core_ext/uri.rb +4 -25
  148. data/lib/active_support/core_ext.rb +4 -2
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +3 -1
  152. data/lib/active_support/dependencies/interlock.rb +49 -0
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +71 -696
  155. data/lib/active_support/deprecation/behaviors.rb +65 -16
  156. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  159. data/lib/active_support/deprecation/method_wrappers.rb +62 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
  161. data/lib/active_support/deprecation/reporting.rb +81 -18
  162. data/lib/active_support/deprecation.rb +19 -11
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  166. data/lib/active_support/duration/iso8601_serializer.rb +67 -0
  167. data/lib/active_support/duration.rb +437 -39
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +117 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +170 -0
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +151 -0
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +8 -0
  178. data/lib/active_support/file_update_checker.rb +62 -37
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +17 -0
  181. data/lib/active_support/gzip.rb +7 -5
  182. data/lib/active_support/hash_with_indifferent_access.rb +207 -54
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +10 -6
  185. data/lib/active_support/i18n_railtie.rb +48 -19
  186. data/lib/active_support/inflections.rb +19 -12
  187. data/lib/active_support/inflector/inflections.rb +97 -37
  188. data/lib/active_support/inflector/methods.rb +192 -157
  189. data/lib/active_support/inflector/transliterate.rb +83 -33
  190. data/lib/active_support/inflector.rb +7 -5
  191. data/lib/active_support/isolated_execution_state.rb +64 -0
  192. data/lib/active_support/json/decoding.rb +37 -42
  193. data/lib/active_support/json/encoding.rb +93 -293
  194. data/lib/active_support/json.rb +4 -2
  195. data/lib/active_support/key_generator.rb +30 -47
  196. data/lib/active_support/lazy_load_hooks.rb +54 -21
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +10 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  200. data/lib/active_support/log_subscriber.rb +61 -18
  201. data/lib/active_support/logger.rb +40 -4
  202. data/lib/active_support/logger_silence.rb +17 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +69 -0
  204. data/lib/active_support/message_encryptor.rb +178 -55
  205. data/lib/active_support/message_verifier.rb +195 -26
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +45 -92
  210. data/lib/active_support/multibyte/unicode.rb +44 -377
  211. data/lib/active_support/multibyte.rb +5 -3
  212. data/lib/active_support/notifications/fanout.rb +177 -44
  213. data/lib/active_support/notifications/instrumenter.rb +117 -17
  214. data/lib/active_support/notifications.rb +106 -39
  215. data/lib/active_support/number_helper/number_converter.rb +181 -0
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  223. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  224. data/lib/active_support/number_helper.rb +152 -394
  225. data/lib/active_support/option_merger.rb +18 -5
  226. data/lib/active_support/ordered_hash.rb +8 -6
  227. data/lib/active_support/ordered_options.rb +43 -7
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +24 -11
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +10 -11
  232. data/lib/active_support/railtie.rb +118 -12
  233. data/lib/active_support/reloader.rb +130 -0
  234. data/lib/active_support/rescuable.rb +112 -57
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +38 -0
  238. data/lib/active_support/string_inquirer.rb +11 -4
  239. data/lib/active_support/subscriber.rb +109 -39
  240. data/lib/active_support/tagged_logging.rb +54 -17
  241. data/lib/active_support/test_case.rb +121 -37
  242. data/lib/active_support/testing/assertions.rb +177 -39
  243. data/lib/active_support/testing/autorun.rb +5 -3
  244. data/lib/active_support/testing/constant_lookup.rb +3 -6
  245. data/lib/active_support/testing/declarative.rb +10 -22
  246. data/lib/active_support/testing/deprecation.rb +65 -11
  247. data/lib/active_support/testing/file_fixtures.rb +38 -0
  248. data/lib/active_support/testing/isolation.rb +56 -87
  249. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  255. data/lib/active_support/testing/stream.rb +41 -0
  256. data/lib/active_support/testing/tagged_logging.rb +6 -4
  257. data/lib/active_support/testing/time_helpers.rb +246 -0
  258. data/lib/active_support/time.rb +13 -13
  259. data/lib/active_support/time_with_zone.rb +315 -90
  260. data/lib/active_support/values/time_zone.rb +306 -135
  261. data/lib/active_support/version.rb +6 -7
  262. data/lib/active_support/xml_mini/jdom.rb +117 -115
  263. data/lib/active_support/xml_mini/libxml.rb +22 -21
  264. data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
  265. data/lib/active_support/xml_mini/nokogiri.rb +19 -19
  266. data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
  267. data/lib/active_support/xml_mini/rexml.rb +25 -17
  268. data/lib/active_support/xml_mini.rb +67 -56
  269. data/lib/active_support.rb +58 -3
  270. metadata +125 -66
  271. data/lib/active_support/basic_object.rb +0 -11
  272. data/lib/active_support/buffered_logger.rb +0 -21
  273. data/lib/active_support/concurrency/latch.rb +0 -27
  274. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  275. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  276. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  277. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  278. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  279. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  280. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  281. data/lib/active_support/core_ext/logger.rb +0 -67
  282. data/lib/active_support/core_ext/marshal.rb +0 -21
  283. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  284. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  285. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  286. data/lib/active_support/core_ext/proc.rb +0 -17
  287. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  288. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  289. data/lib/active_support/core_ext/struct.rb +0 -6
  290. data/lib/active_support/core_ext/thread.rb +0 -79
  291. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  292. data/lib/active_support/file_watcher.rb +0 -36
  293. data/lib/active_support/json/variable.rb +0 -18
  294. data/lib/active_support/testing/pending.rb +0 -14
  295. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -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,90 +53,152 @@ 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
 
111
174
  # Returns a new date/time representing the given day in the next week.
175
+ #
176
+ # today = Date.today # => Thu, 07 May 2015
177
+ # today.next_week # => Mon, 11 May 2015
178
+ #
112
179
  # The +given_day_in_next_week+ defaults to the beginning of the week
113
180
  # which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
114
- # when set. +DateTime+ objects have their time set to 0:00.
115
- def next_week(given_day_in_next_week = Date.beginning_of_week)
116
- first_hour{ weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)) }
117
- end
118
-
119
- # Short-hand for months_since(1).
120
- def next_month
121
- months_since(1)
181
+ # when set.
182
+ #
183
+ # today = Date.today # => Thu, 07 May 2015
184
+ # today.next_week(:friday) # => Fri, 15 May 2015
185
+ #
186
+ # +DateTime+ objects have their time set to 0:00 unless +same_time+ is true.
187
+ #
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
193
+ end
194
+
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
122
202
  end
123
203
 
124
204
  # Short-hand for months_since(3)
@@ -126,25 +206,30 @@ module DateAndTime
126
206
  months_since(3)
127
207
  end
128
208
 
129
- # Short-hand for years_since(1).
130
- def next_year
131
- years_since(1)
132
- end
133
-
134
209
  # Returns a new date/time representing the given day in the previous week.
135
210
  # Week is assumed to start on +start_day+, default is
136
211
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
137
- # DateTime objects have their time set to 0:00.
138
- def prev_week(start_day = Date.beginning_of_week)
139
- 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
140
216
  end
141
217
  alias_method :last_week, :prev_week
142
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
+
143
229
  # Short-hand for months_ago(1).
144
- def prev_month
230
+ def last_month
145
231
  months_ago(1)
146
232
  end
147
- alias_method :last_month, :prev_month
148
233
 
149
234
  # Short-hand for months_ago(3).
150
235
  def prev_quarter
@@ -153,18 +238,16 @@ module DateAndTime
153
238
  alias_method :last_quarter, :prev_quarter
154
239
 
155
240
  # Short-hand for years_ago(1).
156
- def prev_year
241
+ def last_year
157
242
  years_ago(1)
158
243
  end
159
- alias_method :last_year, :prev_year
160
244
 
161
245
  # Returns the number of days to the start of the week on the given day.
162
246
  # Week is assumed to start on +start_day+, default is
163
247
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
164
248
  def days_to_week_start(start_day = Date.beginning_of_week)
165
- start_day_number = DAYS_INTO_WEEK[start_day]
166
- current_day_number = wday != 0 ? wday - 1 : 6
167
- (current_day_number - start_day_number) % 7
249
+ start_day_number = DAYS_INTO_WEEK.fetch(start_day)
250
+ (wday - start_day_number) % 7
168
251
  end
169
252
 
170
253
  # Returns a new date/time representing the start of this week on the given day.
@@ -188,7 +271,7 @@ module DateAndTime
188
271
  # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
189
272
  # DateTime objects have their time set to 23:59:59.
190
273
  def end_of_week(start_day = Date.beginning_of_week)
191
- last_hour{ days_since(6 - days_to_week_start(start_day)) }
274
+ last_hour(days_since(6 - days_to_week_start(start_day)))
192
275
  end
193
276
  alias :at_end_of_week :end_of_week
194
277
 
@@ -202,31 +285,80 @@ module DateAndTime
202
285
  # DateTime objects will have a time set to 23:59:59.
203
286
  def end_of_month
204
287
  last_day = ::Time.days_in_month(month, year)
205
- last_hour{ days_since(last_day - day) }
288
+ last_hour(days_since(last_day - day))
206
289
  end
207
290
  alias :at_end_of_month :end_of_month
208
291
 
209
292
  # Returns a new date/time representing the end of the year.
210
293
  # DateTime objects will have a time set to 23:59:59.
211
294
  def end_of_year
212
- change(:month => 12).end_of_month
295
+ change(month: 12).end_of_month
213
296
  end
214
297
  alias :at_end_of_year :end_of_year
215
298
 
216
- private
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
+
304
+ # Returns a Range representing the whole week of the current date/time.
305
+ # Week starts on start_day, default is <tt>Date.beginning_of_week</tt> or <tt>config.beginning_of_week</tt> when set.
306
+ def all_week(start_day = Date.beginning_of_week)
307
+ beginning_of_week(start_day)..end_of_week(start_day)
308
+ end
217
309
 
218
- def first_hour
219
- result = yield
220
- acts_like?(:time) ? result.change(:hour => 0) : result
310
+ # Returns a Range representing the whole month of the current date/time.
311
+ def all_month
312
+ beginning_of_month..end_of_month
221
313
  end
222
314
 
223
- def last_hour
224
- result = yield
225
- acts_like?(:time) ? result.end_of_day : result
315
+ # Returns a Range representing the whole quarter of the current date/time.
316
+ def all_quarter
317
+ beginning_of_quarter..end_of_quarter
226
318
  end
227
319
 
228
- def days_span(day)
229
- (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
320
+ # Returns a Range representing the whole year of the current date/time.
321
+ def all_year
322
+ beginning_of_year..end_of_year
230
323
  end
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
+
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
231
363
  end
232
364
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/attribute_accessors"
4
+
5
+ module DateAndTime
6
+ module Compatibility
7
+ # If true, +to_time+ preserves the timezone offset of receiver.
8
+ #
9
+ # NOTE: With Ruby 2.4+ the default for +to_time+ changed from
10
+ # converting to the local system time, to preserving the offset
11
+ # of the receiver. For backwards compatibility we're overriding
12
+ # this behavior, but new apps will have an initializer that sets
13
+ # this to true, because the new behavior is preferred.
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 a 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
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DateAndTime
4
+ module Zones
5
+ # Returns the simultaneous time in <tt>Time.zone</tt> if a zone is given or
6
+ # if Time.zone_default is set. Otherwise, it returns the current time.
7
+ #
8
+ # Time.zone = 'Hawaii' # => 'Hawaii'
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
11
+ #
12
+ # This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
13
+ # instead of the operating system's time zone.
14
+ #
15
+ # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
16
+ # and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
17
+ #
18
+ # Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
19
+ # Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
20
+ def in_time_zone(zone = ::Time.zone)
21
+ time_zone = ::Time.find_zone! zone
22
+ time = acts_like?(:time) ? self : nil
23
+
24
+ if time_zone
25
+ time_with_zone(time, time_zone)
26
+ else
27
+ time || to_time
28
+ end
29
+ end
30
+
31
+ private
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
38
+ end
39
+ end
40
+ end
@@ -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