activesupport 5.0.7.2

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 (236) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1018 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/lib/active_support.rb +99 -0
  6. data/lib/active_support/all.rb +3 -0
  7. data/lib/active_support/array_inquirer.rb +44 -0
  8. data/lib/active_support/backtrace_cleaner.rb +103 -0
  9. data/lib/active_support/benchmarkable.rb +49 -0
  10. data/lib/active_support/builder.rb +6 -0
  11. data/lib/active_support/cache.rb +701 -0
  12. data/lib/active_support/cache/file_store.rb +204 -0
  13. data/lib/active_support/cache/mem_cache_store.rb +207 -0
  14. data/lib/active_support/cache/memory_store.rb +167 -0
  15. data/lib/active_support/cache/null_store.rb +41 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +172 -0
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  18. data/lib/active_support/callbacks.rb +791 -0
  19. data/lib/active_support/concern.rb +142 -0
  20. data/lib/active_support/concurrency/latch.rb +26 -0
  21. data/lib/active_support/concurrency/share_lock.rb +226 -0
  22. data/lib/active_support/configurable.rb +148 -0
  23. data/lib/active_support/core_ext.rb +4 -0
  24. data/lib/active_support/core_ext/array.rb +7 -0
  25. data/lib/active_support/core_ext/array/access.rb +90 -0
  26. data/lib/active_support/core_ext/array/conversions.rb +211 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +29 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +107 -0
  29. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  31. data/lib/active_support/core_ext/array/wrap.rb +46 -0
  32. data/lib/active_support/core_ext/benchmark.rb +14 -0
  33. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  35. data/lib/active_support/core_ext/class.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +128 -0
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +41 -0
  39. data/lib/active_support/core_ext/date.rb +5 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  41. data/lib/active_support/core_ext/date/blank.rb +12 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +143 -0
  43. data/lib/active_support/core_ext/date/conversions.rb +95 -0
  44. data/lib/active_support/core_ext/date/zones.rb +6 -0
  45. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  46. data/lib/active_support/core_ext/date_and_time/compatibility.rb +14 -0
  47. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  48. data/lib/active_support/core_ext/date_time.rb +5 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +14 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +199 -0
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  53. data/lib/active_support/core_ext/date_time/conversions.rb +105 -0
  54. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  55. data/lib/active_support/core_ext/enumerable.rb +146 -0
  56. data/lib/active_support/core_ext/file.rb +1 -0
  57. data/lib/active_support/core_ext/file/atomic.rb +68 -0
  58. data/lib/active_support/core_ext/hash.rb +9 -0
  59. data/lib/active_support/core_ext/hash/compact.rb +24 -0
  60. data/lib/active_support/core_ext/hash/conversions.rb +262 -0
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +38 -0
  62. data/lib/active_support/core_ext/hash/except.rb +22 -0
  63. data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -0
  64. data/lib/active_support/core_ext/hash/keys.rb +170 -0
  65. data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -0
  66. data/lib/active_support/core_ext/hash/slice.rb +48 -0
  67. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  68. data/lib/active_support/core_ext/integer.rb +3 -0
  69. data/lib/active_support/core_ext/integer/inflections.rb +29 -0
  70. data/lib/active_support/core_ext/integer/multiple.rb +10 -0
  71. data/lib/active_support/core_ext/integer/time.rb +29 -0
  72. data/lib/active_support/core_ext/kernel.rb +4 -0
  73. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  74. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  75. data/lib/active_support/core_ext/kernel/debugger.rb +3 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +43 -0
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +6 -0
  78. data/lib/active_support/core_ext/load_error.rb +31 -0
  79. data/lib/active_support/core_ext/marshal.rb +22 -0
  80. data/lib/active_support/core_ext/module.rb +12 -0
  81. data/lib/active_support/core_ext/module/aliasing.rb +74 -0
  82. data/lib/active_support/core_ext/module/anonymous.rb +28 -0
  83. data/lib/active_support/core_ext/module/attr_internal.rb +36 -0
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +212 -0
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  87. data/lib/active_support/core_ext/module/delegation.rb +216 -0
  88. data/lib/active_support/core_ext/module/deprecation.rb +23 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +68 -0
  90. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  91. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  92. data/lib/active_support/core_ext/module/reachable.rb +8 -0
  93. data/lib/active_support/core_ext/module/remove_method.rb +35 -0
  94. data/lib/active_support/core_ext/name_error.rb +31 -0
  95. data/lib/active_support/core_ext/numeric.rb +4 -0
  96. data/lib/active_support/core_ext/numeric/bytes.rb +64 -0
  97. data/lib/active_support/core_ext/numeric/conversions.rb +144 -0
  98. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  99. data/lib/active_support/core_ext/numeric/time.rb +74 -0
  100. data/lib/active_support/core_ext/object.rb +14 -0
  101. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  102. data/lib/active_support/core_ext/object/blank.rb +143 -0
  103. data/lib/active_support/core_ext/object/conversions.rb +4 -0
  104. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  105. data/lib/active_support/core_ext/object/duplicable.rb +124 -0
  106. data/lib/active_support/core_ext/object/inclusion.rb +27 -0
  107. data/lib/active_support/core_ext/object/instance_variables.rb +28 -0
  108. data/lib/active_support/core_ext/object/json.rb +205 -0
  109. data/lib/active_support/core_ext/object/to_param.rb +1 -0
  110. data/lib/active_support/core_ext/object/to_query.rb +84 -0
  111. data/lib/active_support/core_ext/object/try.rb +146 -0
  112. data/lib/active_support/core_ext/object/with_options.rb +69 -0
  113. data/lib/active_support/core_ext/range.rb +4 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +31 -0
  115. data/lib/active_support/core_ext/range/each.rb +21 -0
  116. data/lib/active_support/core_ext/range/include_range.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +8 -0
  118. data/lib/active_support/core_ext/regexp.rb +5 -0
  119. data/lib/active_support/core_ext/securerandom.rb +23 -0
  120. data/lib/active_support/core_ext/string.rb +13 -0
  121. data/lib/active_support/core_ext/string/access.rb +104 -0
  122. data/lib/active_support/core_ext/string/behavior.rb +6 -0
  123. data/lib/active_support/core_ext/string/conversions.rb +57 -0
  124. data/lib/active_support/core_ext/string/exclude.rb +11 -0
  125. data/lib/active_support/core_ext/string/filters.rb +102 -0
  126. data/lib/active_support/core_ext/string/indent.rb +43 -0
  127. data/lib/active_support/core_ext/string/inflections.rb +244 -0
  128. data/lib/active_support/core_ext/string/inquiry.rb +13 -0
  129. data/lib/active_support/core_ext/string/multibyte.rb +53 -0
  130. data/lib/active_support/core_ext/string/output_safety.rb +260 -0
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
  132. data/lib/active_support/core_ext/string/strip.rb +23 -0
  133. data/lib/active_support/core_ext/string/zones.rb +14 -0
  134. data/lib/active_support/core_ext/struct.rb +3 -0
  135. data/lib/active_support/core_ext/time.rb +5 -0
  136. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  137. data/lib/active_support/core_ext/time/calculations.rb +290 -0
  138. data/lib/active_support/core_ext/time/compatibility.rb +14 -0
  139. data/lib/active_support/core_ext/time/conversions.rb +67 -0
  140. data/lib/active_support/core_ext/time/marshal.rb +3 -0
  141. data/lib/active_support/core_ext/time/zones.rb +111 -0
  142. data/lib/active_support/core_ext/uri.rb +24 -0
  143. data/lib/active_support/dependencies.rb +755 -0
  144. data/lib/active_support/dependencies/autoload.rb +77 -0
  145. data/lib/active_support/dependencies/interlock.rb +55 -0
  146. data/lib/active_support/deprecation.rb +43 -0
  147. data/lib/active_support/deprecation/behaviors.rb +90 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +37 -0
  149. data/lib/active_support/deprecation/method_wrappers.rb +70 -0
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +149 -0
  151. data/lib/active_support/deprecation/reporting.rb +112 -0
  152. data/lib/active_support/descendants_tracker.rb +60 -0
  153. data/lib/active_support/duration.rb +235 -0
  154. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  155. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  156. data/lib/active_support/evented_file_update_checker.rb +199 -0
  157. data/lib/active_support/execution_wrapper.rb +126 -0
  158. data/lib/active_support/executor.rb +6 -0
  159. data/lib/active_support/file_update_checker.rb +157 -0
  160. data/lib/active_support/gem_version.rb +15 -0
  161. data/lib/active_support/gzip.rb +36 -0
  162. data/lib/active_support/hash_with_indifferent_access.rb +329 -0
  163. data/lib/active_support/i18n.rb +13 -0
  164. data/lib/active_support/i18n_railtie.rb +115 -0
  165. data/lib/active_support/inflections.rb +70 -0
  166. data/lib/active_support/inflector.rb +7 -0
  167. data/lib/active_support/inflector/inflections.rb +242 -0
  168. data/lib/active_support/inflector/methods.rb +390 -0
  169. data/lib/active_support/inflector/transliterate.rb +112 -0
  170. data/lib/active_support/json.rb +2 -0
  171. data/lib/active_support/json/decoding.rb +74 -0
  172. data/lib/active_support/json/encoding.rb +127 -0
  173. data/lib/active_support/key_generator.rb +71 -0
  174. data/lib/active_support/lazy_load_hooks.rb +76 -0
  175. data/lib/active_support/locale/en.yml +135 -0
  176. data/lib/active_support/log_subscriber.rb +109 -0
  177. data/lib/active_support/log_subscriber/test_helper.rb +104 -0
  178. data/lib/active_support/logger.rb +106 -0
  179. data/lib/active_support/logger_silence.rb +28 -0
  180. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  181. data/lib/active_support/message_encryptor.rb +114 -0
  182. data/lib/active_support/message_verifier.rb +134 -0
  183. data/lib/active_support/multibyte.rb +21 -0
  184. data/lib/active_support/multibyte/chars.rb +231 -0
  185. data/lib/active_support/multibyte/unicode.rb +413 -0
  186. data/lib/active_support/notifications.rb +212 -0
  187. data/lib/active_support/notifications/fanout.rb +157 -0
  188. data/lib/active_support/notifications/instrumenter.rb +91 -0
  189. data/lib/active_support/number_helper.rb +368 -0
  190. data/lib/active_support/number_helper/number_converter.rb +182 -0
  191. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  192. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  193. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  194. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  195. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  196. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  197. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  198. data/lib/active_support/option_merger.rb +25 -0
  199. data/lib/active_support/ordered_hash.rb +48 -0
  200. data/lib/active_support/ordered_options.rb +81 -0
  201. data/lib/active_support/per_thread_registry.rb +58 -0
  202. data/lib/active_support/proxy_object.rb +13 -0
  203. data/lib/active_support/rails.rb +27 -0
  204. data/lib/active_support/railtie.rb +51 -0
  205. data/lib/active_support/reloader.rb +129 -0
  206. data/lib/active_support/rescuable.rb +173 -0
  207. data/lib/active_support/security_utils.rb +27 -0
  208. data/lib/active_support/string_inquirer.rb +26 -0
  209. data/lib/active_support/subscriber.rb +120 -0
  210. data/lib/active_support/tagged_logging.rb +77 -0
  211. data/lib/active_support/test_case.rb +88 -0
  212. data/lib/active_support/testing/assertions.rb +99 -0
  213. data/lib/active_support/testing/autorun.rb +5 -0
  214. data/lib/active_support/testing/constant_lookup.rb +50 -0
  215. data/lib/active_support/testing/declarative.rb +26 -0
  216. data/lib/active_support/testing/deprecation.rb +36 -0
  217. data/lib/active_support/testing/file_fixtures.rb +34 -0
  218. data/lib/active_support/testing/isolation.rb +115 -0
  219. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  220. data/lib/active_support/testing/setup_and_teardown.rb +50 -0
  221. data/lib/active_support/testing/stream.rb +42 -0
  222. data/lib/active_support/testing/tagged_logging.rb +25 -0
  223. data/lib/active_support/testing/time_helpers.rb +136 -0
  224. data/lib/active_support/time.rb +18 -0
  225. data/lib/active_support/time_with_zone.rb +511 -0
  226. data/lib/active_support/values/time_zone.rb +484 -0
  227. data/lib/active_support/values/unicode_tables.dat +0 -0
  228. data/lib/active_support/version.rb +8 -0
  229. data/lib/active_support/xml_mini.rb +209 -0
  230. data/lib/active_support/xml_mini/jdom.rb +181 -0
  231. data/lib/active_support/xml_mini/libxml.rb +77 -0
  232. data/lib/active_support/xml_mini/libxmlsax.rb +82 -0
  233. data/lib/active_support/xml_mini/nokogiri.rb +81 -0
  234. data/lib/active_support/xml_mini/nokogirisax.rb +85 -0
  235. data/lib/active_support/xml_mini/rexml.rb +128 -0
  236. metadata +349 -0
@@ -0,0 +1,95 @@
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'
5
+
6
+ class Date
7
+ DATE_FORMATS = {
8
+ :short => '%d %b',
9
+ :long => '%B %d, %Y',
10
+ :db => '%Y-%m-%d',
11
+ :number => '%Y%m%d',
12
+ :long_ordinal => lambda { |date|
13
+ day_format = ActiveSupport::Inflector.ordinalize(date.day)
14
+ date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
15
+ },
16
+ :rfc822 => '%d %b %Y',
17
+ :iso8601 => lambda { |date| date.iso8601 }
18
+ }
19
+
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
+ # Convert to a formatted string. See DATE_FORMATS for predefined formats.
29
+ #
30
+ # This method is aliased to <tt>to_s</tt>.
31
+ #
32
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
33
+ #
34
+ # date.to_formatted_s(:db) # => "2007-11-10"
35
+ # date.to_s(:db) # => "2007-11-10"
36
+ #
37
+ # date.to_formatted_s(:short) # => "10 Nov"
38
+ # date.to_formatted_s(:number) # => "20071110"
39
+ # date.to_formatted_s(:long) # => "November 10, 2007"
40
+ # date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
41
+ # date.to_formatted_s(:rfc822) # => "10 Nov 2007"
42
+ # date.to_formatted_s(:iso8601) # => "2007-11-10"
43
+ #
44
+ # == Adding your own date formats to to_formatted_s
45
+ # You can add your own formats to the Date::DATE_FORMATS hash.
46
+ # Use the format name as the hash key and either a strftime string
47
+ # or Proc instance that takes a date argument as the value.
48
+ #
49
+ # # config/initializers/date_formats.rb
50
+ # Date::DATE_FORMATS[:month_and_year] = '%B %Y'
51
+ # Date::DATE_FORMATS[:short_ordinal] = ->(date) { date.strftime("%B #{date.day.ordinalize}") }
52
+ def to_formatted_s(format = :default)
53
+ if formatter = DATE_FORMATS[format]
54
+ if formatter.respond_to?(:call)
55
+ formatter.call(self).to_s
56
+ else
57
+ strftime(formatter)
58
+ end
59
+ else
60
+ to_default_s
61
+ end
62
+ end
63
+ alias_method :to_default_s, :to_s
64
+ alias_method :to_s, :to_formatted_s
65
+
66
+ # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
67
+ def readable_inspect
68
+ strftime('%a, %d %b %Y')
69
+ end
70
+ alias_method :default_inspect, :inspect
71
+ alias_method :inspect, :readable_inspect
72
+
73
+ # Converts a Date instance to a Time, where the time is set to the beginning of the day.
74
+ # The timezone can be either :local or :utc (default :local).
75
+ #
76
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
77
+ #
78
+ # date.to_time # => 2007-11-10 00:00:00 0800
79
+ # date.to_time(:local) # => 2007-11-10 00:00:00 0800
80
+ #
81
+ # date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
82
+ def to_time(form = :local)
83
+ raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
84
+ ::Time.send(form, year, month, day)
85
+ end
86
+
87
+ # Returns a string which represents the time in used time zone as DateTime
88
+ # defined by XML Schema:
89
+ #
90
+ # date = Date.new(2015, 05, 23) # => Sat, 23 May 2015
91
+ # date.xmlschema # => "2015-05-23T00:00:00+04:00"
92
+ def xmlschema
93
+ in_time_zone.xmlschema
94
+ end
95
+ end
@@ -0,0 +1,6 @@
1
+ require 'date'
2
+ require 'active_support/core_ext/date_and_time/zones'
3
+
4
+ class Date
5
+ include DateAndTime::Zones
6
+ end
@@ -0,0 +1,335 @@
1
+ require 'active_support/core_ext/object/try'
2
+
3
+ module DateAndTime
4
+ module Calculations
5
+ DAYS_INTO_WEEK = {
6
+ :monday => 0,
7
+ :tuesday => 1,
8
+ :wednesday => 2,
9
+ :thursday => 3,
10
+ :friday => 4,
11
+ :saturday => 5,
12
+ :sunday => 6
13
+ }
14
+ WEEKEND_DAYS = [ 6, 0 ]
15
+
16
+ # Returns a new date/time representing yesterday.
17
+ def yesterday
18
+ advance(days: -1)
19
+ end
20
+
21
+ # Returns a new date/time representing the previous day.
22
+ def prev_day
23
+ advance(days: -1)
24
+ end
25
+
26
+ # Returns a new date/time representing tomorrow.
27
+ def tomorrow
28
+ advance(days: 1)
29
+ end
30
+
31
+ # Returns a new date/time representing the next day.
32
+ def next_day
33
+ advance(days: 1)
34
+ end
35
+
36
+ # Returns true if the date/time is today.
37
+ def today?
38
+ to_date == ::Date.current
39
+ end
40
+
41
+ # Returns true if the date/time is in the past.
42
+ def past?
43
+ self < self.class.current
44
+ end
45
+
46
+ # Returns true if the date/time is in the future.
47
+ def future?
48
+ self > self.class.current
49
+ end
50
+
51
+ # Returns true if the date/time falls on a Saturday or Sunday.
52
+ def on_weekend?
53
+ WEEKEND_DAYS.include?(wday)
54
+ end
55
+
56
+ # Returns true if the date/time does not fall on a Saturday or Sunday.
57
+ def on_weekday?
58
+ !WEEKEND_DAYS.include?(wday)
59
+ end
60
+
61
+ # Returns a new date/time the specified number of days ago.
62
+ def days_ago(days)
63
+ advance(:days => -days)
64
+ end
65
+
66
+ # Returns a new date/time the specified number of days in the future.
67
+ def days_since(days)
68
+ advance(:days => days)
69
+ end
70
+
71
+ # Returns a new date/time the specified number of weeks ago.
72
+ def weeks_ago(weeks)
73
+ advance(:weeks => -weeks)
74
+ end
75
+
76
+ # Returns a new date/time the specified number of weeks in the future.
77
+ def weeks_since(weeks)
78
+ advance(:weeks => weeks)
79
+ end
80
+
81
+ # Returns a new date/time the specified number of months ago.
82
+ def months_ago(months)
83
+ advance(:months => -months)
84
+ end
85
+
86
+ # Returns a new date/time the specified number of months in the future.
87
+ def months_since(months)
88
+ advance(:months => months)
89
+ end
90
+
91
+ # Returns a new date/time the specified number of years ago.
92
+ def years_ago(years)
93
+ advance(:years => -years)
94
+ end
95
+
96
+ # Returns a new date/time the specified number of years in the future.
97
+ def years_since(years)
98
+ advance(:years => years)
99
+ end
100
+
101
+ # Returns a new date/time at the start of the month.
102
+ #
103
+ # today = Date.today # => Thu, 18 Jun 2015
104
+ # today.beginning_of_month # => Mon, 01 Jun 2015
105
+ #
106
+ # +DateTime+ objects will have a time set to 0:00.
107
+ #
108
+ # now = DateTime.current # => Thu, 18 Jun 2015 15:23:13 +0000
109
+ # now.beginning_of_month # => Mon, 01 Jun 2015 00:00:00 +0000
110
+ def beginning_of_month
111
+ first_hour(change(:day => 1))
112
+ end
113
+ alias :at_beginning_of_month :beginning_of_month
114
+
115
+ # Returns a new date/time at the start of the quarter.
116
+ #
117
+ # today = Date.today # => Fri, 10 Jul 2015
118
+ # today.beginning_of_quarter # => Wed, 01 Jul 2015
119
+ #
120
+ # +DateTime+ objects will have a time set to 0:00.
121
+ #
122
+ # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
123
+ # now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
124
+ 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)
127
+ end
128
+ alias :at_beginning_of_quarter :beginning_of_quarter
129
+
130
+ # Returns a new date/time at the end of the quarter.
131
+ #
132
+ # today = Date.today # => Fri, 10 Jul 2015
133
+ # today.end_of_quarter # => Wed, 30 Sep 2015
134
+ #
135
+ # +DateTime+ objects will have a time set to 23:59:59.
136
+ #
137
+ # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
138
+ # now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
139
+ 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
142
+ end
143
+ alias :at_end_of_quarter :end_of_quarter
144
+
145
+ # Returns a new date/time at the beginning of the year.
146
+ #
147
+ # today = Date.today # => Fri, 10 Jul 2015
148
+ # today.beginning_of_year # => Thu, 01 Jan 2015
149
+ #
150
+ # +DateTime+ objects will have a time set to 0:00.
151
+ #
152
+ # now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
153
+ # now.beginning_of_year # => Thu, 01 Jan 2015 00:00:00 +0000
154
+ def beginning_of_year
155
+ change(:month => 1).beginning_of_month
156
+ end
157
+ alias :at_beginning_of_year :beginning_of_year
158
+
159
+ # Returns a new date/time representing the given day in the next week.
160
+ #
161
+ # today = Date.today # => Thu, 07 May 2015
162
+ # today.next_week # => Mon, 11 May 2015
163
+ #
164
+ # The +given_day_in_next_week+ defaults to the beginning of the week
165
+ # which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
166
+ # when set.
167
+ #
168
+ # today = Date.today # => Thu, 07 May 2015
169
+ # today.next_week(:friday) # => Fri, 15 May 2015
170
+ #
171
+ # +DateTime+ objects have their time set to 0:00 unless +same_time+ is true.
172
+ #
173
+ # now = DateTime.current # => Thu, 07 May 2015 13:31:16 +0000
174
+ # now.next_week # => Mon, 11 May 2015 00:00:00 +0000
175
+ def next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false)
176
+ result = first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
177
+ same_time ? copy_time_to(result) : result
178
+ end
179
+
180
+ # Returns a new date/time representing the next weekday.
181
+ def next_weekday
182
+ if next_day.on_weekend?
183
+ next_week(:monday, same_time: true)
184
+ else
185
+ next_day
186
+ end
187
+ end
188
+
189
+ # Short-hand for months_since(1).
190
+ def next_month
191
+ months_since(1)
192
+ end
193
+
194
+ # Short-hand for months_since(3)
195
+ def next_quarter
196
+ months_since(3)
197
+ end
198
+
199
+ # Short-hand for years_since(1).
200
+ def next_year
201
+ years_since(1)
202
+ end
203
+
204
+ # Returns a new date/time representing the given day in the previous week.
205
+ # Week is assumed to start on +start_day+, default is
206
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
207
+ # DateTime objects have their time set to 0:00 unless +same_time+ is true.
208
+ def prev_week(start_day = Date.beginning_of_week, same_time: false)
209
+ result = first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
210
+ same_time ? copy_time_to(result) : result
211
+ end
212
+ alias_method :last_week, :prev_week
213
+
214
+ # Returns a new date/time representing the previous weekday.
215
+ def prev_weekday
216
+ if prev_day.on_weekend?
217
+ copy_time_to(beginning_of_week(:friday))
218
+ else
219
+ prev_day
220
+ end
221
+ end
222
+ alias_method :last_weekday, :prev_weekday
223
+
224
+ # Short-hand for months_ago(1).
225
+ def prev_month
226
+ months_ago(1)
227
+ end
228
+ alias_method :last_month, :prev_month
229
+
230
+ # Short-hand for months_ago(3).
231
+ def prev_quarter
232
+ months_ago(3)
233
+ end
234
+ alias_method :last_quarter, :prev_quarter
235
+
236
+ # Short-hand for years_ago(1).
237
+ def prev_year
238
+ years_ago(1)
239
+ end
240
+ alias_method :last_year, :prev_year
241
+
242
+ # Returns the number of days to the start of the week on the given day.
243
+ # Week is assumed to start on +start_day+, default is
244
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
245
+ 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
+ end
250
+
251
+ # Returns a new date/time representing the start of this week on the given day.
252
+ # Week is assumed to start on +start_day+, default is
253
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
254
+ # +DateTime+ objects have their time set to 0:00.
255
+ def beginning_of_week(start_day = Date.beginning_of_week)
256
+ result = days_ago(days_to_week_start(start_day))
257
+ acts_like?(:time) ? result.midnight : result
258
+ end
259
+ alias :at_beginning_of_week :beginning_of_week
260
+
261
+ # Returns Monday of this week assuming that week starts on Monday.
262
+ # +DateTime+ objects have their time set to 0:00.
263
+ def monday
264
+ beginning_of_week(:monday)
265
+ end
266
+
267
+ # Returns a new date/time representing the end of this week on the given day.
268
+ # Week is assumed to start on +start_day+, default is
269
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
270
+ # DateTime objects have their time set to 23:59:59.
271
+ def end_of_week(start_day = Date.beginning_of_week)
272
+ last_hour(days_since(6 - days_to_week_start(start_day)))
273
+ end
274
+ alias :at_end_of_week :end_of_week
275
+
276
+ # Returns Sunday of this week assuming that week starts on Monday.
277
+ # +DateTime+ objects have their time set to 23:59:59.
278
+ def sunday
279
+ end_of_week(:monday)
280
+ end
281
+
282
+ # Returns a new date/time representing the end of the month.
283
+ # DateTime objects will have a time set to 23:59:59.
284
+ def end_of_month
285
+ last_day = ::Time.days_in_month(month, year)
286
+ last_hour(days_since(last_day - day))
287
+ end
288
+ alias :at_end_of_month :end_of_month
289
+
290
+ # Returns a new date/time representing the end of the year.
291
+ # DateTime objects will have a time set to 23:59:59.
292
+ def end_of_year
293
+ change(:month => 12).end_of_month
294
+ end
295
+ alias :at_end_of_year :end_of_year
296
+
297
+ # 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.
299
+ def all_week(start_day = Date.beginning_of_week)
300
+ beginning_of_week(start_day)..end_of_week(start_day)
301
+ end
302
+
303
+ # Returns a Range representing the whole month of the current date/time.
304
+ def all_month
305
+ beginning_of_month..end_of_month
306
+ end
307
+
308
+ # Returns a Range representing the whole quarter of the current date/time.
309
+ def all_quarter
310
+ beginning_of_quarter..end_of_quarter
311
+ end
312
+
313
+ # Returns a Range representing the whole year of the current date/time.
314
+ def all_year
315
+ beginning_of_year..end_of_year
316
+ end
317
+
318
+ private
319
+ def first_hour(date_or_time)
320
+ date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
321
+ end
322
+
323
+ def last_hour(date_or_time)
324
+ date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
325
+ end
326
+
327
+ def days_span(day)
328
+ (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
329
+ end
330
+
331
+ def copy_time_to(other)
332
+ other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,14 @@
1
+ require 'active_support/core_ext/module/attribute_accessors'
2
+
3
+ module DateAndTime
4
+ module Compatibility
5
+ # If true, +to_time+ preserves the timezone offset of receiver.
6
+ #
7
+ # NOTE: With Ruby 2.4+ the default for +to_time+ changed from
8
+ # converting to the local system time, to preserving the offset
9
+ # of the receiver. For backwards compatibility we're overriding
10
+ # this behavior, but new apps will have an initializer that sets
11
+ # this to true, because the new behavior is preferred.
12
+ mattr_accessor(:preserve_timezone, instance_writer: false) { false }
13
+ end
14
+ end