activesupport-refinements 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/activesupport-refinements.gemspec +21 -0
- data/lib/active_support/refinements/core_ext/array.rb +7 -0
- data/lib/active_support/refinements/core_ext/array/access.rb +56 -0
- data/lib/active_support/refinements/core_ext/array/conversions.rb +224 -0
- data/lib/active_support/refinements/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/refinements/core_ext/array/grouping.rb +101 -0
- data/lib/active_support/refinements/core_ext/array/prepend_and_append.rb +9 -0
- data/lib/active_support/refinements/core_ext/array/uniq_by.rb +21 -0
- data/lib/active_support/refinements/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/refinements/core_ext/benchmark.rb +7 -0
- data/lib/active_support/refinements/core_ext/big_decimal.rb +1 -0
- data/lib/active_support/refinements/core_ext/big_decimal/conversions.rb +32 -0
- data/lib/active_support/refinements/core_ext/class.rb +4 -0
- data/lib/active_support/refinements/core_ext/class/attribute.rb +119 -0
- data/lib/active_support/refinements/core_ext/class/attribute_accessors.rb +172 -0
- data/lib/active_support/refinements/core_ext/class/delegating_attributes.rb +42 -0
- data/lib/active_support/refinements/core_ext/class/subclasses.rb +44 -0
- data/lib/active_support/refinements/core_ext/date.rb +5 -0
- data/lib/active_support/refinements/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/refinements/core_ext/date/calculations.rb +123 -0
- data/lib/active_support/refinements/core_ext/date/conversions.rb +86 -0
- data/lib/active_support/refinements/core_ext/date/zones.rb +17 -0
- data/lib/active_support/refinements/core_ext/date_and_time/calculations.rb +232 -0
- data/lib/active_support/refinements/core_ext/date_time.rb +4 -0
- data/lib/active_support/refinements/core_ext/date_time/acts_like.rb +15 -0
- data/lib/active_support/refinements/core_ext/date_time/calculations.rb +143 -0
- data/lib/active_support/refinements/core_ext/date_time/conversions.rb +93 -0
- data/lib/active_support/refinements/core_ext/date_time/zones.rb +26 -0
- data/lib/active_support/refinements/core_ext/enumerable.rb +82 -0
- data/lib/active_support/refinements/core_ext/exception.rb +5 -0
- data/lib/active_support/refinements/core_ext/file.rb +1 -0
- data/lib/active_support/refinements/core_ext/file/atomic.rb +60 -0
- data/lib/active_support/refinements/core_ext/hash.rb +8 -0
- data/lib/active_support/refinements/core_ext/hash/conversions.rb +161 -0
- data/lib/active_support/refinements/core_ext/hash/deep_merge.rb +29 -0
- data/lib/active_support/refinements/core_ext/hash/diff.rb +15 -0
- data/lib/active_support/refinements/core_ext/hash/except.rb +17 -0
- data/lib/active_support/refinements/core_ext/hash/indifferent_access.rb +24 -0
- data/lib/active_support/refinements/core_ext/hash/keys.rb +140 -0
- data/lib/active_support/refinements/core_ext/hash/reverse_merge.rb +24 -0
- data/lib/active_support/refinements/core_ext/hash/slice.rb +42 -0
- data/lib/active_support/refinements/core_ext/integer.rb +3 -0
- data/lib/active_support/refinements/core_ext/integer/inflections.rb +31 -0
- data/lib/active_support/refinements/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/refinements/core_ext/integer/time.rb +43 -0
- data/lib/active_support/refinements/core_ext/kernel.rb +4 -0
- data/lib/active_support/refinements/core_ext/kernel/agnostics.rb +13 -0
- data/lib/active_support/refinements/core_ext/kernel/debugger.rb +12 -0
- data/lib/active_support/refinements/core_ext/kernel/reporting.rb +97 -0
- data/lib/active_support/refinements/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/refinements/core_ext/load_error.rb +27 -0
- data/lib/active_support/refinements/core_ext/logger.rb +86 -0
- data/lib/active_support/refinements/core_ext/module.rb +10 -0
- data/lib/active_support/refinements/core_ext/module/aliasing.rb +69 -0
- data/lib/active_support/refinements/core_ext/module/anonymous.rb +21 -0
- data/lib/active_support/refinements/core_ext/module/attr_internal.rb +40 -0
- data/lib/active_support/refinements/core_ext/module/attribute_accessors.rb +68 -0
- data/lib/active_support/refinements/core_ext/module/delegation.rb +172 -0
- data/lib/active_support/refinements/core_ext/module/deprecation.rb +27 -0
- data/lib/active_support/refinements/core_ext/module/introspection.rb +80 -0
- data/lib/active_support/refinements/core_ext/module/qualified_const.rb +54 -0
- data/lib/active_support/refinements/core_ext/module/reachable.rb +10 -0
- data/lib/active_support/refinements/core_ext/module/remove_method.rb +14 -0
- data/lib/active_support/refinements/core_ext/name_error.rb +20 -0
- data/lib/active_support/refinements/core_ext/numeric.rb +3 -0
- data/lib/active_support/refinements/core_ext/numeric/bytes.rb +46 -0
- data/lib/active_support/refinements/core_ext/numeric/conversions.rb +137 -0
- data/lib/active_support/refinements/core_ext/numeric/time.rb +81 -0
- data/lib/active_support/refinements/core_ext/object.rb +14 -0
- data/lib/active_support/refinements/core_ext/object/acts_like.rb +12 -0
- data/lib/active_support/refinements/core_ext/object/blank.rb +107 -0
- data/lib/active_support/refinements/core_ext/object/conversions.rb +4 -0
- data/lib/active_support/refinements/core_ext/object/deep_dup.rb +48 -0
- data/lib/active_support/refinements/core_ext/object/duplicable.rb +92 -0
- data/lib/active_support/refinements/core_ext/object/inclusion.rb +27 -0
- data/lib/active_support/refinements/core_ext/object/instance_variables.rb +30 -0
- data/lib/active_support/refinements/core_ext/object/to_json.rb +27 -0
- data/lib/active_support/refinements/core_ext/object/to_param.rb +60 -0
- data/lib/active_support/refinements/core_ext/object/to_query.rb +29 -0
- data/lib/active_support/refinements/core_ext/object/try.rb +72 -0
- data/lib/active_support/refinements/core_ext/object/with_options.rb +44 -0
- data/lib/active_support/refinements/core_ext/proc.rb +19 -0
- data/lib/active_support/refinements/core_ext/range.rb +3 -0
- data/lib/active_support/refinements/core_ext/range/conversions.rb +21 -0
- data/lib/active_support/refinements/core_ext/range/include_range.rb +23 -0
- data/lib/active_support/refinements/core_ext/range/overlaps.rb +10 -0
- data/lib/active_support/refinements/core_ext/regexp.rb +7 -0
- data/lib/active_support/refinements/core_ext/string.rb +13 -0
- data/lib/active_support/refinements/core_ext/string/access.rb +106 -0
- data/lib/active_support/refinements/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/refinements/core_ext/string/conversions.rb +60 -0
- data/lib/active_support/refinements/core_ext/string/encoding.rb +10 -0
- data/lib/active_support/refinements/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/refinements/core_ext/string/filters.rb +54 -0
- data/lib/active_support/refinements/core_ext/string/indent.rb +45 -0
- data/lib/active_support/refinements/core_ext/string/inflections.rb +214 -0
- data/lib/active_support/refinements/core_ext/string/inquiry.rb +15 -0
- data/lib/active_support/refinements/core_ext/string/multibyte.rb +58 -0
- data/lib/active_support/refinements/core_ext/string/output_safety.rb +194 -0
- data/lib/active_support/refinements/core_ext/string/starts_ends_with.rb +6 -0
- data/lib/active_support/refinements/core_ext/string/strip.rb +28 -0
- data/lib/active_support/refinements/core_ext/string/xchar.rb +18 -0
- data/lib/active_support/refinements/core_ext/time.rb +5 -0
- data/lib/active_support/refinements/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/refinements/core_ext/time/calculations.rb +251 -0
- data/lib/active_support/refinements/core_ext/time/conversions.rb +65 -0
- data/lib/active_support/refinements/core_ext/time/marshal.rb +30 -0
- data/lib/active_support/refinements/core_ext/time/zones.rb +98 -0
- data/lib/active_support/refinements/core_ext/uri.rb +28 -0
- data/lib/activesupport-refinements.rb +9 -0
- data/lib/activesupport-refinements/version.rb +5 -0
- data/refine_core_ext.rb +45 -0
- data/spec/hwia_spec.rb +15 -0
- data/spec/try_spec.rb +18 -0
- metadata +182 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module ClassExt; end; module ClassExt::Subclasses
|
|
2
|
+
require 'active_support/refinements/core_ext/module/anonymous'
|
|
3
|
+
require 'active_support/refinements/core_ext/module/reachable'
|
|
4
|
+
|
|
5
|
+
refine Class do
|
|
6
|
+
begin
|
|
7
|
+
ObjectSpace.each_object(Class.new) {}
|
|
8
|
+
|
|
9
|
+
def descendants # :nodoc:
|
|
10
|
+
descendants = []
|
|
11
|
+
ObjectSpace.each_object(singleton_class) do |k|
|
|
12
|
+
descendants.unshift k unless k == self
|
|
13
|
+
end
|
|
14
|
+
descendants
|
|
15
|
+
end
|
|
16
|
+
rescue StandardError # JRuby
|
|
17
|
+
def descendants # :nodoc:
|
|
18
|
+
descendants = []
|
|
19
|
+
ObjectSpace.each_object(Class) do |k|
|
|
20
|
+
descendants.unshift k if k < self
|
|
21
|
+
end
|
|
22
|
+
descendants.uniq!
|
|
23
|
+
descendants
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns an array with the direct children of +self+.
|
|
28
|
+
#
|
|
29
|
+
# Integer.subclasses # => [Fixnum, Bignum]
|
|
30
|
+
#
|
|
31
|
+
# class Foo; end
|
|
32
|
+
# class Bar < Foo; end
|
|
33
|
+
# class Baz < Foo; end
|
|
34
|
+
#
|
|
35
|
+
# Foo.subclasses # => [Baz, Bar]
|
|
36
|
+
def subclasses
|
|
37
|
+
subclasses, chain = [], descendants
|
|
38
|
+
chain.each do |k|
|
|
39
|
+
subclasses << k unless chain.any? { |c| c > k }
|
|
40
|
+
end
|
|
41
|
+
subclasses
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module DateExt; end; module DateExt::Calculations
|
|
2
|
+
require 'date'
|
|
3
|
+
require 'active_support/duration'
|
|
4
|
+
require 'active_support/refinements/core_ext/object/acts_like'
|
|
5
|
+
require 'active_support/refinements/core_ext/date/zones'
|
|
6
|
+
require 'active_support/refinements/core_ext/time/zones'
|
|
7
|
+
require 'active_support/refinements/core_ext/date_and_time/calculations'
|
|
8
|
+
|
|
9
|
+
refine Date do
|
|
10
|
+
include DateAndTime::Calculations
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_accessor :beginning_of_week_default
|
|
14
|
+
|
|
15
|
+
# Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=).
|
|
16
|
+
# If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>.
|
|
17
|
+
# If no config.beginning_of_week was specified, returns :monday.
|
|
18
|
+
def beginning_of_week
|
|
19
|
+
Thread.current[:beginning_of_week] || beginning_of_week_default || :monday
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread.
|
|
23
|
+
#
|
|
24
|
+
# This method accepts any of the following day symbols:
|
|
25
|
+
# :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday
|
|
26
|
+
def beginning_of_week=(week_start)
|
|
27
|
+
Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns week start day symbol (e.g. :monday), or raises an ArgumentError for invalid day symbol.
|
|
31
|
+
def find_beginning_of_week!(week_start)
|
|
32
|
+
raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.key?(week_start)
|
|
33
|
+
week_start
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
|
|
37
|
+
def yesterday
|
|
38
|
+
::Date.current.yesterday
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns a new Date representing the date 1 day after today (i.e. tomorrow's date).
|
|
42
|
+
def tomorrow
|
|
43
|
+
::Date.current.tomorrow
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns Time.zone.today when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns Date.today.
|
|
47
|
+
def current
|
|
48
|
+
::Time.zone ? ::Time.zone.today : ::Date.today
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
|
|
53
|
+
# and then subtracts the specified number of seconds.
|
|
54
|
+
def ago(seconds)
|
|
55
|
+
to_time_in_current_zone.since(-seconds)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
|
|
59
|
+
# and then adds the specified number of seconds
|
|
60
|
+
def since(seconds)
|
|
61
|
+
to_time_in_current_zone.since(seconds)
|
|
62
|
+
end
|
|
63
|
+
# alias :in :since
|
|
64
|
+
|
|
65
|
+
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
|
|
66
|
+
def beginning_of_day
|
|
67
|
+
to_time_in_current_zone
|
|
68
|
+
end
|
|
69
|
+
# alias :midnight :beginning_of_day
|
|
70
|
+
# alias :at_midnight :beginning_of_day
|
|
71
|
+
# alias :at_beginning_of_day :beginning_of_day
|
|
72
|
+
|
|
73
|
+
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)
|
|
74
|
+
def end_of_day
|
|
75
|
+
to_time_in_current_zone.end_of_day
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def plus_with_duration(other) #:nodoc:
|
|
79
|
+
if ActiveSupport::Duration === other
|
|
80
|
+
other.since(self)
|
|
81
|
+
else
|
|
82
|
+
plus_without_duration(other)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
# alias_method :plus_without_duration, :+
|
|
86
|
+
# alias_method :+, :plus_with_duration
|
|
87
|
+
|
|
88
|
+
def minus_with_duration(other) #:nodoc:
|
|
89
|
+
if ActiveSupport::Duration === other
|
|
90
|
+
plus_with_duration(-other)
|
|
91
|
+
else
|
|
92
|
+
minus_without_duration(other)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
# alias_method :minus_without_duration, :-
|
|
96
|
+
# alias_method :-, :minus_with_duration
|
|
97
|
+
|
|
98
|
+
# Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
|
|
99
|
+
# any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
|
|
100
|
+
def advance(options)
|
|
101
|
+
options = options.dup
|
|
102
|
+
d = self
|
|
103
|
+
d = d >> options.delete(:years) * 12 if options[:years]
|
|
104
|
+
d = d >> options.delete(:months) if options[:months]
|
|
105
|
+
d = d + options.delete(:weeks) * 7 if options[:weeks]
|
|
106
|
+
d = d + options.delete(:days) if options[:days]
|
|
107
|
+
d
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
|
|
111
|
+
# The +options+ parameter is a hash with a combination of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>.
|
|
112
|
+
#
|
|
113
|
+
# Date.new(2007, 5, 12).change(day: 1) # => Date.new(2007, 5, 1)
|
|
114
|
+
# Date.new(2007, 5, 12).change(year: 2005, month: 1) # => Date.new(2005, 1, 12)
|
|
115
|
+
def change(options)
|
|
116
|
+
::Date.new(
|
|
117
|
+
options.fetch(:year, year),
|
|
118
|
+
options.fetch(:month, month),
|
|
119
|
+
options.fetch(:day, day)
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module DateExt; end; module DateExt::Conversions
|
|
2
|
+
require 'date'
|
|
3
|
+
require 'active_support/inflector/methods'
|
|
4
|
+
require 'active_support/refinements/core_ext/date/zones'
|
|
5
|
+
require 'active_support/refinements/core_ext/module/remove_method'
|
|
6
|
+
|
|
7
|
+
refine Date do
|
|
8
|
+
DATE_FORMATS = {
|
|
9
|
+
:short => '%e %b',
|
|
10
|
+
:long => '%B %e, %Y',
|
|
11
|
+
:db => '%Y-%m-%d',
|
|
12
|
+
:number => '%Y%m%d',
|
|
13
|
+
:long_ordinal => lambda { |date|
|
|
14
|
+
day_format = ActiveSupport::Inflector.ordinalize(date.day)
|
|
15
|
+
date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
|
|
16
|
+
},
|
|
17
|
+
:rfc822 => '%e %b %Y'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Ruby 1.9 has Date#to_time which converts to localtime only.
|
|
21
|
+
remove_possible_method :to_time
|
|
22
|
+
|
|
23
|
+
# Ruby 1.9 has Date#xmlschema which converts to a string without the time component.
|
|
24
|
+
remove_possible_method :xmlschema
|
|
25
|
+
|
|
26
|
+
# Convert to a formatted string. See DATE_FORMATS for predefined formats.
|
|
27
|
+
#
|
|
28
|
+
# This method is aliased to <tt>to_s</tt>.
|
|
29
|
+
#
|
|
30
|
+
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
|
31
|
+
#
|
|
32
|
+
# date.to_formatted_s(:db) # => "2007-11-10"
|
|
33
|
+
# date.to_s(:db) # => "2007-11-10"
|
|
34
|
+
#
|
|
35
|
+
# date.to_formatted_s(:short) # => "10 Nov"
|
|
36
|
+
# date.to_formatted_s(:long) # => "November 10, 2007"
|
|
37
|
+
# date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
|
|
38
|
+
# date.to_formatted_s(:rfc822) # => "10 Nov 2007"
|
|
39
|
+
#
|
|
40
|
+
# == Adding your own time formats to to_formatted_s
|
|
41
|
+
# You can add your own formats to the Date::DATE_FORMATS hash.
|
|
42
|
+
# Use the format name as the hash key and either a strftime string
|
|
43
|
+
# or Proc instance that takes a date argument as the value.
|
|
44
|
+
#
|
|
45
|
+
# # config/initializers/time_formats.rb
|
|
46
|
+
# Date::DATE_FORMATS[:month_and_year] = '%B %Y'
|
|
47
|
+
# Date::DATE_FORMATS[:short_ordinal] = ->(date) { date.strftime("%B #{date.day.ordinalize}") }
|
|
48
|
+
def to_formatted_s(format = :default)
|
|
49
|
+
if formatter = DATE_FORMATS[format]
|
|
50
|
+
if formatter.respond_to?(:call)
|
|
51
|
+
formatter.call(self).to_s
|
|
52
|
+
else
|
|
53
|
+
strftime(formatter)
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
to_default_s
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
# alias_method :to_default_s, :to_s
|
|
60
|
+
# alias_method :to_s, :to_formatted_s
|
|
61
|
+
|
|
62
|
+
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
|
|
63
|
+
def readable_inspect
|
|
64
|
+
strftime('%a, %d %b %Y')
|
|
65
|
+
end
|
|
66
|
+
# alias_method :default_inspect, :inspect
|
|
67
|
+
# alias_method :inspect, :readable_inspect
|
|
68
|
+
|
|
69
|
+
# Converts a Date instance to a Time, where the time is set to the beginning of the day.
|
|
70
|
+
# The timezone can be either :local or :utc (default :local).
|
|
71
|
+
#
|
|
72
|
+
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
|
73
|
+
#
|
|
74
|
+
# date.to_time # => Sat Nov 10 00:00:00 0800 2007
|
|
75
|
+
# date.to_time(:local) # => Sat Nov 10 00:00:00 0800 2007
|
|
76
|
+
#
|
|
77
|
+
# date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007
|
|
78
|
+
def to_time(form = :local)
|
|
79
|
+
::Time.send("#{form}_time", year, month, day)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def xmlschema
|
|
83
|
+
to_time_in_current_zone.xmlschema
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module DateExt; end; module DateExt::Zones
|
|
2
|
+
require 'date'
|
|
3
|
+
require 'active_support/refinements/core_ext/time/zones'
|
|
4
|
+
|
|
5
|
+
refine Date do
|
|
6
|
+
# Converts Date to a TimeWithZone in the current zone if <tt>Time.zone</tt> or
|
|
7
|
+
# <tt>Time.zone_default</tt> is set, otherwise converts Date to a Time via
|
|
8
|
+
# Date#to_time.
|
|
9
|
+
def to_time_in_current_zone
|
|
10
|
+
if ::Time.zone
|
|
11
|
+
::Time.zone.local(year, month, day)
|
|
12
|
+
else
|
|
13
|
+
to_time
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
module DateAndTime
|
|
2
|
+
module Calculations
|
|
3
|
+
DAYS_INTO_WEEK = {
|
|
4
|
+
:monday => 0,
|
|
5
|
+
:tuesday => 1,
|
|
6
|
+
:wednesday => 2,
|
|
7
|
+
:thursday => 3,
|
|
8
|
+
:friday => 4,
|
|
9
|
+
:saturday => 5,
|
|
10
|
+
:sunday => 6
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
# Returns a new date/time representing yesterday.
|
|
14
|
+
def yesterday
|
|
15
|
+
advance(:days => -1)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Returns a new date/time representing tomorrow.
|
|
19
|
+
def tomorrow
|
|
20
|
+
advance(:days => 1)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns true if the date/time is today.
|
|
24
|
+
def today?
|
|
25
|
+
to_date == ::Date.current
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Returns true if the date/time is in the past.
|
|
29
|
+
def past?
|
|
30
|
+
self < self.class.current
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns true if the date/time is in the future.
|
|
34
|
+
def future?
|
|
35
|
+
self > self.class.current
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Returns a new date/time the specified number of days ago.
|
|
39
|
+
def days_ago(days)
|
|
40
|
+
advance(:days => -days)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns a new date/time the specified number of days in the future.
|
|
44
|
+
def days_since(days)
|
|
45
|
+
advance(:days => days)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns a new date/time the specified number of weeks ago.
|
|
49
|
+
def weeks_ago(weeks)
|
|
50
|
+
advance(:weeks => -weeks)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns a new date/time the specified number of weeks in the future.
|
|
54
|
+
def weeks_since(weeks)
|
|
55
|
+
advance(:weeks => weeks)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns a new date/time the specified number of months ago.
|
|
59
|
+
def months_ago(months)
|
|
60
|
+
advance(:months => -months)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Returns a new date/time the specified number of months in the future.
|
|
64
|
+
def months_since(months)
|
|
65
|
+
advance(:months => months)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns a new date/time the specified number of years ago.
|
|
69
|
+
def years_ago(years)
|
|
70
|
+
advance(:years => -years)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns a new date/time the specified number of years in the future.
|
|
74
|
+
def years_since(years)
|
|
75
|
+
advance(:years => years)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Returns a new date/time at the start of the month.
|
|
79
|
+
# DateTime objects will have a time set to 0:00.
|
|
80
|
+
def beginning_of_month
|
|
81
|
+
first_hour{ change(:day => 1) }
|
|
82
|
+
end
|
|
83
|
+
alias :at_beginning_of_month :beginning_of_month
|
|
84
|
+
|
|
85
|
+
# 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.
|
|
88
|
+
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)
|
|
91
|
+
end
|
|
92
|
+
alias :at_beginning_of_quarter :beginning_of_quarter
|
|
93
|
+
|
|
94
|
+
# 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.
|
|
97
|
+
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
|
|
100
|
+
end
|
|
101
|
+
alias :at_end_of_quarter :end_of_quarter
|
|
102
|
+
|
|
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.
|
|
106
|
+
def beginning_of_year
|
|
107
|
+
change(:month => 1).beginning_of_month
|
|
108
|
+
end
|
|
109
|
+
alias :at_beginning_of_year :beginning_of_year
|
|
110
|
+
|
|
111
|
+
# Returns a new date/time representing the given day in the next week.
|
|
112
|
+
# Week is assumed to start on +start_day+, default is
|
|
113
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
114
|
+
# DateTime objects have their time set to 0:00.
|
|
115
|
+
def next_week(start_day = Date.beginning_of_week)
|
|
116
|
+
first_hour{ weeks_since(1).beginning_of_week.days_since(days_span(start_day)) }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Short-hand for months_since(1).
|
|
120
|
+
def next_month
|
|
121
|
+
months_since(1)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Short-hand for months_since(3)
|
|
125
|
+
def next_quarter
|
|
126
|
+
months_since(3)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Short-hand for years_since(1).
|
|
130
|
+
def next_year
|
|
131
|
+
years_since(1)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Returns a new date/time representing the given day in the previous week.
|
|
135
|
+
# Week is assumed to start on +start_day+, default is
|
|
136
|
+
# +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)) }
|
|
140
|
+
end
|
|
141
|
+
alias_method :last_week, :prev_week
|
|
142
|
+
|
|
143
|
+
# Short-hand for months_ago(1).
|
|
144
|
+
def prev_month
|
|
145
|
+
months_ago(1)
|
|
146
|
+
end
|
|
147
|
+
alias_method :last_month, :prev_month
|
|
148
|
+
|
|
149
|
+
# Short-hand for months_ago(3).
|
|
150
|
+
def prev_quarter
|
|
151
|
+
months_ago(3)
|
|
152
|
+
end
|
|
153
|
+
alias_method :last_quarter, :prev_quarter
|
|
154
|
+
|
|
155
|
+
# Short-hand for years_ago(1).
|
|
156
|
+
def prev_year
|
|
157
|
+
years_ago(1)
|
|
158
|
+
end
|
|
159
|
+
alias_method :last_year, :prev_year
|
|
160
|
+
|
|
161
|
+
# Returns the number of days to the start of the week on the given day.
|
|
162
|
+
# Week is assumed to start on +start_day+, default is
|
|
163
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
164
|
+
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
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Returns a new date/time representing the start of this week on the given day.
|
|
171
|
+
# Week is assumed to start on +start_day+, default is
|
|
172
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
173
|
+
# +DateTime+ objects have their time set to 0:00.
|
|
174
|
+
def beginning_of_week(start_day = Date.beginning_of_week)
|
|
175
|
+
result = days_ago(days_to_week_start(start_day))
|
|
176
|
+
acts_like?(:time) ? result.midnight : result
|
|
177
|
+
end
|
|
178
|
+
alias :at_beginning_of_week :beginning_of_week
|
|
179
|
+
|
|
180
|
+
# Returns Monday of this week assuming that week starts on Monday.
|
|
181
|
+
# +DateTime+ objects have their time set to 0:00.
|
|
182
|
+
def monday
|
|
183
|
+
beginning_of_week(:monday)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Returns a new date/time representing the end of this week on the given day.
|
|
187
|
+
# Week is assumed to start on +start_day+, default is
|
|
188
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
189
|
+
# DateTime objects have their time set to 23:59:59.
|
|
190
|
+
def end_of_week(start_day = Date.beginning_of_week)
|
|
191
|
+
last_hour{ days_since(6 - days_to_week_start(start_day)) }
|
|
192
|
+
end
|
|
193
|
+
alias :at_end_of_week :end_of_week
|
|
194
|
+
|
|
195
|
+
# Returns Sunday of this week assuming that week starts on Monday.
|
|
196
|
+
# +DateTime+ objects have their time set to 23:59:59.
|
|
197
|
+
def sunday
|
|
198
|
+
end_of_week(:monday)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Returns a new date/time representing the end of the month.
|
|
202
|
+
# DateTime objects will have a time set to 23:59:59.
|
|
203
|
+
def end_of_month
|
|
204
|
+
last_day = ::Time.days_in_month(month, year)
|
|
205
|
+
last_hour{ days_since(last_day - day) }
|
|
206
|
+
end
|
|
207
|
+
alias :at_end_of_month :end_of_month
|
|
208
|
+
|
|
209
|
+
# Returns a new date/time representing the end of the year.
|
|
210
|
+
# DateTime objects will have a time set to 23:59:59.
|
|
211
|
+
def end_of_year
|
|
212
|
+
change(:month => 12).end_of_month
|
|
213
|
+
end
|
|
214
|
+
alias :at_end_of_year :end_of_year
|
|
215
|
+
|
|
216
|
+
private
|
|
217
|
+
|
|
218
|
+
def first_hour
|
|
219
|
+
result = yield
|
|
220
|
+
acts_like?(:time) ? result.change(:hour => 0) : result
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def last_hour
|
|
224
|
+
result = yield
|
|
225
|
+
acts_like?(:time) ? result.end_of_day : result
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def days_span(day)
|
|
229
|
+
(DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|