activesupport 4.2.11.3 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +678 -348
- data/MIT-LICENSE +2 -2
- data/README.rdoc +2 -3
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +36 -22
- data/lib/active_support/cache/mem_cache_store.rb +63 -54
- data/lib/active_support/cache/memory_store.rb +16 -21
- data/lib/active_support/cache/null_store.rb +1 -4
- data/lib/active_support/cache/strategy/local_cache.rb +31 -20
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +4 -4
- data/lib/active_support/cache.rb +71 -87
- data/lib/active_support/callbacks.rb +109 -113
- data/lib/active_support/concern.rb +1 -1
- data/lib/active_support/concurrency/latch.rb +11 -12
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +27 -1
- data/lib/active_support/core_ext/array/conversions.rb +6 -4
- data/lib/active_support/core_ext/array/grouping.rb +9 -18
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +5 -4
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
- data/lib/active_support/core_ext/class/attribute.rb +10 -9
- data/lib/active_support/core_ext/class/subclasses.rb +3 -2
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +1 -1
- data/lib/active_support/core_ext/date/conversions.rb +7 -6
- data/lib/active_support/core_ext/date.rb +1 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +100 -27
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +3 -4
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +14 -8
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_time.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +75 -25
- data/lib/active_support/core_ext/file/atomic.rb +30 -25
- data/lib/active_support/core_ext/hash/conversions.rb +22 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +9 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +25 -21
- data/lib/active_support/core_ext/hash/slice.rb +1 -1
- data/lib/active_support/core_ext/hash/transform_values.rb +11 -5
- data/lib/active_support/core_ext/integer/time.rb +2 -2
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -84
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +5 -2
- data/lib/active_support/core_ext/marshal.rb +7 -9
- data/lib/active_support/core_ext/module/aliasing.rb +6 -1
- data/lib/active_support/core_ext/module/anonymous.rb +10 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +15 -15
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +4 -4
- data/lib/active_support/core_ext/module/delegation.rb +11 -20
- data/lib/active_support/core_ext/module/deprecation.rb +2 -2
- data/lib/active_support/core_ext/module/introspection.rb +8 -2
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
- data/lib/active_support/core_ext/module/remove_method.rb +23 -0
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +78 -77
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +26 -6
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/blank.rb +15 -3
- data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
- data/lib/active_support/core_ext/object/duplicable.rb +7 -12
- data/lib/active_support/core_ext/object/inclusion.rb +2 -2
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +15 -7
- data/lib/active_support/core_ext/object/to_query.rb +1 -1
- data/lib/active_support/core_ext/object/try.rb +67 -21
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/object.rb +0 -1
- data/lib/active_support/core_ext/range/conversions.rb +18 -6
- data/lib/active_support/core_ext/range/each.rb +16 -18
- data/lib/active_support/core_ext/range/include_range.rb +20 -20
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +3 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -2
- data/lib/active_support/core_ext/string/inflections.rb +32 -5
- data/lib/active_support/core_ext/string/multibyte.rb +11 -7
- data/lib/active_support/core_ext/string/output_safety.rb +12 -14
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/struct.rb +3 -6
- data/lib/active_support/core_ext/time/calculations.rb +18 -9
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/marshal.rb +2 -29
- data/lib/active_support/core_ext/time/zones.rb +36 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/core_ext/uri.rb +1 -3
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/dependencies/interlock.rb +55 -0
- data/lib/active_support/dependencies.rb +88 -95
- data/lib/active_support/deprecation/behaviors.rb +15 -1
- data/lib/active_support/deprecation/instance_delegator.rb +13 -0
- data/lib/active_support/deprecation/method_wrappers.rb +42 -16
- data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
- data/lib/active_support/deprecation/reporting.rb +23 -5
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/duration/iso8601_parser.rb +122 -0
- data/lib/active_support/duration/iso8601_serializer.rb +51 -0
- data/lib/active_support/duration.rb +90 -15
- data/lib/active_support/evented_file_update_checker.rb +199 -0
- data/lib/active_support/execution_wrapper.rb +126 -0
- data/lib/active_support/executor.rb +6 -0
- data/lib/active_support/file_update_checker.rb +23 -3
- data/lib/active_support/gem_version.rb +5 -5
- data/lib/active_support/gzip.rb +1 -1
- data/lib/active_support/hash_with_indifferent_access.rb +40 -11
- data/lib/active_support/i18n_railtie.rb +25 -4
- data/lib/active_support/inflector/inflections.rb +36 -5
- data/lib/active_support/inflector/methods.rb +97 -90
- data/lib/active_support/inflector/transliterate.rb +36 -21
- data/lib/active_support/json/decoding.rb +11 -10
- data/lib/active_support/json/encoding.rb +1 -51
- data/lib/active_support/key_generator.rb +7 -9
- data/lib/active_support/lazy_load_hooks.rb +46 -18
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +3 -3
- data/lib/active_support/log_subscriber.rb +1 -1
- data/lib/active_support/logger.rb +3 -4
- data/lib/active_support/logger_silence.rb +2 -1
- data/lib/active_support/logger_thread_safe_level.rb +2 -3
- data/lib/active_support/message_encryptor.rb +7 -7
- data/lib/active_support/message_verifier.rb +70 -8
- data/lib/active_support/multibyte/chars.rb +12 -3
- data/lib/active_support/multibyte/unicode.rb +44 -21
- data/lib/active_support/notifications/fanout.rb +5 -5
- data/lib/active_support/notifications/instrumenter.rb +20 -2
- data/lib/active_support/notifications.rb +2 -2
- data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +8 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -2
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +11 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +30 -25
- data/lib/active_support/number_helper.rb +90 -67
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/per_thread_registry.rb +3 -0
- data/lib/active_support/rails.rb +2 -2
- data/lib/active_support/railtie.rb +6 -1
- data/lib/active_support/reloader.rb +129 -0
- data/lib/active_support/rescuable.rb +101 -47
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +5 -10
- data/lib/active_support/tagged_logging.rb +8 -7
- data/lib/active_support/test_case.rb +17 -29
- data/lib/active_support/testing/assertions.rb +15 -13
- data/lib/active_support/testing/deprecation.rb +9 -8
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +22 -8
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/time_helpers.rb +3 -1
- data/lib/active_support/time_with_zone.rb +123 -33
- data/lib/active_support/values/time_zone.rb +101 -47
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support.rb +11 -6
- metadata +36 -17
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/thread.rb +0 -86
@@ -21,12 +21,24 @@ class Array
|
|
21
21
|
# %w( a b c ).to(-10) # => []
|
22
22
|
def to(position)
|
23
23
|
if position >= 0
|
24
|
-
|
24
|
+
take position + 1
|
25
25
|
else
|
26
26
|
self[0..position]
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
# Returns a copy of the Array without the specified elements.
|
31
|
+
#
|
32
|
+
# people = ["David", "Rafael", "Aaron", "Todd"]
|
33
|
+
# people.without "Aaron", "Todd"
|
34
|
+
# => ["David", "Rafael"]
|
35
|
+
#
|
36
|
+
# Note: This is an optimization of `Enumerable#without` that uses `Array#-`
|
37
|
+
# instead of `Array#reject` for performance reasons.
|
38
|
+
def without(*elements)
|
39
|
+
self - elements
|
40
|
+
end
|
41
|
+
|
30
42
|
# Equal to <tt>self[1]</tt>.
|
31
43
|
#
|
32
44
|
# %w( a b c d e ).second # => "b"
|
@@ -61,4 +73,18 @@ class Array
|
|
61
73
|
def forty_two
|
62
74
|
self[41]
|
63
75
|
end
|
76
|
+
|
77
|
+
# Equal to <tt>self[-3]</tt>.
|
78
|
+
#
|
79
|
+
# %w( a b c d e ).third_to_last # => "c"
|
80
|
+
def third_to_last
|
81
|
+
self[-3]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Equal to <tt>self[-2]</tt>.
|
85
|
+
#
|
86
|
+
# %w( a b c d e ).second_to_last # => "d"
|
87
|
+
def second_to_last
|
88
|
+
self[-2]
|
89
|
+
end
|
64
90
|
end
|
@@ -32,7 +32,7 @@ class Array
|
|
32
32
|
# ['one', 'two', 'three'].to_sentence # => "one, two, and three"
|
33
33
|
#
|
34
34
|
# ['one', 'two'].to_sentence(passing: 'invalid option')
|
35
|
-
# # => ArgumentError: Unknown key :passing
|
35
|
+
# # => ArgumentError: Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale
|
36
36
|
#
|
37
37
|
# ['one', 'two'].to_sentence(two_words_connector: '-')
|
38
38
|
# # => "one-two"
|
@@ -74,7 +74,7 @@ class Array
|
|
74
74
|
when 0
|
75
75
|
''
|
76
76
|
when 1
|
77
|
-
self[0]
|
77
|
+
"#{self[0]}"
|
78
78
|
when 2
|
79
79
|
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
80
80
|
else
|
@@ -85,14 +85,16 @@ class Array
|
|
85
85
|
# Extends <tt>Array#to_s</tt> to convert a collection of elements into a
|
86
86
|
# comma separated id list if <tt>:db</tt> argument is given as the format.
|
87
87
|
#
|
88
|
-
# Blog.all.to_formatted_s(:db)
|
88
|
+
# Blog.all.to_formatted_s(:db) # => "1,2,3"
|
89
|
+
# Blog.none.to_formatted_s(:db) # => "null"
|
90
|
+
# [1,2].to_formatted_s # => "[1, 2]"
|
89
91
|
def to_formatted_s(format = :default)
|
90
92
|
case format
|
91
93
|
when :db
|
92
94
|
if empty?
|
93
95
|
'null'
|
94
96
|
else
|
95
|
-
collect
|
97
|
+
collect(&:id).join(',')
|
96
98
|
end
|
97
99
|
else
|
98
100
|
to_default_s
|
@@ -89,28 +89,19 @@ class Array
|
|
89
89
|
# [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
|
90
90
|
# (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
|
91
91
|
def split(value = nil)
|
92
|
+
arr = self.dup
|
93
|
+
result = []
|
92
94
|
if block_given?
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
else
|
97
|
-
results.last << element
|
98
|
-
end
|
99
|
-
|
100
|
-
results
|
95
|
+
while (idx = arr.index { |i| yield i })
|
96
|
+
result << arr.shift(idx)
|
97
|
+
arr.shift
|
101
98
|
end
|
102
99
|
else
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
results.last.concat(arr.shift(idx))
|
107
|
-
arr.shift
|
108
|
-
results << []
|
109
|
-
else
|
110
|
-
results.last.concat(arr.shift(arr.size))
|
111
|
-
end
|
100
|
+
while (idx = arr.index(value))
|
101
|
+
result << arr.shift(idx)
|
102
|
+
arr.shift
|
112
103
|
end
|
113
|
-
results
|
114
104
|
end
|
105
|
+
result << arr
|
115
106
|
end
|
116
107
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'active_support/array_inquirer'
|
2
|
+
|
3
|
+
class Array
|
4
|
+
# Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
|
5
|
+
# to check its string-like contents.
|
6
|
+
#
|
7
|
+
# pets = [:cat, :dog].inquiry
|
8
|
+
#
|
9
|
+
# pets.cat? # => true
|
10
|
+
# pets.ferret? # => false
|
11
|
+
#
|
12
|
+
# pets.any?(:cat, :ferret) # => true
|
13
|
+
# pets.any?(:ferret, :alligator) # => false
|
14
|
+
def inquiry
|
15
|
+
ActiveSupport::ArrayInquirer.new(self)
|
16
|
+
end
|
17
|
+
end
|
@@ -3,7 +3,7 @@ class Array
|
|
3
3
|
#
|
4
4
|
# Specifically:
|
5
5
|
#
|
6
|
-
# * If the argument is +nil+ an empty
|
6
|
+
# * If the argument is +nil+ an empty array is returned.
|
7
7
|
# * Otherwise, if the argument responds to +to_ary+ it is invoked, and its result returned.
|
8
8
|
# * Otherwise, returns an array with the argument as its single element.
|
9
9
|
#
|
@@ -15,12 +15,13 @@ class Array
|
|
15
15
|
#
|
16
16
|
# * If the argument responds to +to_ary+ the method is invoked. <tt>Kernel#Array</tt>
|
17
17
|
# moves on to try +to_a+ if the returned value is +nil+, but <tt>Array.wrap</tt> returns
|
18
|
-
#
|
18
|
+
# an array with the argument as its single element right away.
|
19
19
|
# * If the returned value from +to_ary+ is neither +nil+ nor an +Array+ object, <tt>Kernel#Array</tt>
|
20
20
|
# raises an exception, while <tt>Array.wrap</tt> does not, it just returns the value.
|
21
|
-
# * It does not call +to_a+ on the argument,
|
21
|
+
# * It does not call +to_a+ on the argument, if the argument does not respond to +to_ary+
|
22
|
+
# it returns an array with the argument as its single element.
|
22
23
|
#
|
23
|
-
# The
|
24
|
+
# The last point is easily explained with some enumerables:
|
24
25
|
#
|
25
26
|
# Array(foo: :bar) # => [[:foo, :bar]]
|
26
27
|
# Array.wrap(foo: :bar) # => [{:foo=>:bar}]
|
@@ -1,16 +1,14 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
require 'bigdecimal/util'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
format = args[0] || DEFAULT_STRING_FORMAT
|
11
|
-
_original_to_s(format)
|
4
|
+
module ActiveSupport
|
5
|
+
module BigDecimalWithDefaultFormat #:nodoc:
|
6
|
+
DEFAULT_STRING_FORMAT = 'F'
|
7
|
+
|
8
|
+
def to_s(format = nil)
|
9
|
+
super(format || DEFAULT_STRING_FORMAT)
|
12
10
|
end
|
13
11
|
end
|
14
|
-
alias_method :_original_to_s, :to_s
|
15
|
-
alias_method :to_s, :to_formatted_s
|
16
12
|
end
|
13
|
+
|
14
|
+
BigDecimal.prepend(ActiveSupport::BigDecimalWithDefaultFormat)
|
@@ -75,11 +75,15 @@ class Class
|
|
75
75
|
instance_predicate = options.fetch(:instance_predicate, true)
|
76
76
|
|
77
77
|
attrs.each do |name|
|
78
|
+
remove_possible_singleton_method(name)
|
78
79
|
define_singleton_method(name) { nil }
|
80
|
+
|
81
|
+
remove_possible_singleton_method("#{name}?")
|
79
82
|
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
|
80
83
|
|
81
84
|
ivar = "@#{name}"
|
82
85
|
|
86
|
+
remove_possible_singleton_method("#{name}=")
|
83
87
|
define_singleton_method("#{name}=") do |val|
|
84
88
|
singleton_class.class_eval do
|
85
89
|
remove_possible_method(name)
|
@@ -110,18 +114,15 @@ class Class
|
|
110
114
|
self.class.public_send name
|
111
115
|
end
|
112
116
|
end
|
117
|
+
|
118
|
+
remove_possible_method "#{name}?"
|
113
119
|
define_method("#{name}?") { !!public_send(name) } if instance_predicate
|
114
120
|
end
|
115
121
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
private
|
121
|
-
|
122
|
-
unless respond_to?(:singleton_class?)
|
123
|
-
def singleton_class?
|
124
|
-
ancestors.first != self
|
122
|
+
if instance_writer
|
123
|
+
remove_possible_method "#{name}="
|
124
|
+
attr_writer name
|
125
125
|
end
|
126
126
|
end
|
127
|
+
end
|
127
128
|
end
|
@@ -3,7 +3,8 @@ require 'active_support/core_ext/module/reachable'
|
|
3
3
|
|
4
4
|
class Class
|
5
5
|
begin
|
6
|
-
|
6
|
+
# Test if this Ruby supports each_object against singleton_class
|
7
|
+
ObjectSpace.each_object(Numeric.singleton_class) {}
|
7
8
|
|
8
9
|
def descendants # :nodoc:
|
9
10
|
descendants = []
|
@@ -12,7 +13,7 @@ class Class
|
|
12
13
|
end
|
13
14
|
descendants
|
14
15
|
end
|
15
|
-
rescue StandardError # JRuby
|
16
|
+
rescue StandardError # JRuby 9.0.4.0 and earlier
|
16
17
|
def descendants # :nodoc:
|
17
18
|
descendants = []
|
18
19
|
ObjectSpace.each_object(Class) do |k|
|
@@ -26,7 +26,7 @@ class Date
|
|
26
26
|
Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start)
|
27
27
|
end
|
28
28
|
|
29
|
-
# Returns week start day symbol (e.g. :monday), or raises an ArgumentError for invalid day symbol.
|
29
|
+
# Returns week start day symbol (e.g. :monday), or raises an +ArgumentError+ for invalid day symbol.
|
30
30
|
def find_beginning_of_week!(week_start)
|
31
31
|
raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.key?(week_start)
|
32
32
|
week_start
|
@@ -5,15 +5,15 @@ require 'active_support/core_ext/module/remove_method'
|
|
5
5
|
|
6
6
|
class Date
|
7
7
|
DATE_FORMATS = {
|
8
|
-
:short => '%
|
9
|
-
:long => '%B %
|
8
|
+
:short => '%d %b',
|
9
|
+
:long => '%B %d, %Y',
|
10
10
|
:db => '%Y-%m-%d',
|
11
11
|
:number => '%Y%m%d',
|
12
12
|
:long_ordinal => lambda { |date|
|
13
13
|
day_format = ActiveSupport::Inflector.ordinalize(date.day)
|
14
14
|
date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
|
15
15
|
},
|
16
|
-
:rfc822 => '%
|
16
|
+
:rfc822 => '%d %b %Y',
|
17
17
|
:iso8601 => lambda { |date| date.iso8601 }
|
18
18
|
}
|
19
19
|
|
@@ -75,11 +75,12 @@ class Date
|
|
75
75
|
#
|
76
76
|
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
77
77
|
#
|
78
|
-
# date.to_time # =>
|
79
|
-
# date.to_time(:local) # =>
|
78
|
+
# date.to_time # => 2007-11-10 00:00:00 0800
|
79
|
+
# date.to_time(:local) # => 2007-11-10 00:00:00 0800
|
80
80
|
#
|
81
|
-
# date.to_time(:utc) # =>
|
81
|
+
# date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
|
82
82
|
def to_time(form = :local)
|
83
|
+
raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
|
83
84
|
::Time.send(form, year, month, day)
|
84
85
|
end
|
85
86
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/object/try'
|
2
|
+
|
1
3
|
module DateAndTime
|
2
4
|
module Calculations
|
3
5
|
DAYS_INTO_WEEK = {
|
@@ -9,15 +11,26 @@ module DateAndTime
|
|
9
11
|
:saturday => 5,
|
10
12
|
:sunday => 6
|
11
13
|
}
|
14
|
+
WEEKEND_DAYS = [ 6, 0 ]
|
12
15
|
|
13
16
|
# Returns a new date/time representing yesterday.
|
14
17
|
def yesterday
|
15
|
-
advance(:
|
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)
|
16
24
|
end
|
17
25
|
|
18
26
|
# Returns a new date/time representing tomorrow.
|
19
27
|
def tomorrow
|
20
|
-
advance(:
|
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)
|
21
34
|
end
|
22
35
|
|
23
36
|
# Returns true if the date/time is today.
|
@@ -35,6 +48,16 @@ module DateAndTime
|
|
35
48
|
self > self.class.current
|
36
49
|
end
|
37
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
|
+
|
38
61
|
# Returns a new date/time the specified number of days ago.
|
39
62
|
def days_ago(days)
|
40
63
|
advance(:days => -days)
|
@@ -76,15 +99,28 @@ module DateAndTime
|
|
76
99
|
end
|
77
100
|
|
78
101
|
# Returns a new date/time at the start of the month.
|
79
|
-
#
|
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
|
80
110
|
def beginning_of_month
|
81
111
|
first_hour(change(:day => 1))
|
82
112
|
end
|
83
113
|
alias :at_beginning_of_month :beginning_of_month
|
84
114
|
|
85
115
|
# Returns a new date/time at the start of the quarter.
|
86
|
-
#
|
87
|
-
#
|
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
|
88
124
|
def beginning_of_quarter
|
89
125
|
first_quarter_month = [10, 7, 4, 1].detect { |m| m <= month }
|
90
126
|
beginning_of_month.change(:month => first_quarter_month)
|
@@ -92,17 +128,29 @@ module DateAndTime
|
|
92
128
|
alias :at_beginning_of_quarter :beginning_of_quarter
|
93
129
|
|
94
130
|
# Returns a new date/time at the end of the quarter.
|
95
|
-
#
|
96
|
-
#
|
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
|
97
139
|
def end_of_quarter
|
98
140
|
last_quarter_month = [3, 6, 9, 12].detect { |m| m >= month }
|
99
141
|
beginning_of_month.change(:month => last_quarter_month).end_of_month
|
100
142
|
end
|
101
143
|
alias :at_end_of_quarter :end_of_quarter
|
102
144
|
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
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
|
106
154
|
def beginning_of_year
|
107
155
|
change(:month => 1).beginning_of_month
|
108
156
|
end
|
@@ -115,16 +163,27 @@ module DateAndTime
|
|
115
163
|
#
|
116
164
|
# The +given_day_in_next_week+ defaults to the beginning of the week
|
117
165
|
# which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
|
166
|
+
# when set.
|
118
167
|
#
|
119
168
|
# today = Date.today # => Thu, 07 May 2015
|
120
169
|
# today.next_week(:friday) # => Fri, 15 May 2015
|
121
170
|
#
|
122
|
-
#
|
171
|
+
# +DateTime+ objects have their time set to 0:00 unless +same_time+ is true.
|
123
172
|
#
|
124
|
-
# now =
|
125
|
-
# now.next_week # => Mon, 11 May 2015 00:00:00
|
126
|
-
def next_week(given_day_in_next_week = Date.beginning_of_week)
|
127
|
-
first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
|
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
|
128
187
|
end
|
129
188
|
|
130
189
|
# Short-hand for months_since(1).
|
@@ -145,12 +204,23 @@ module DateAndTime
|
|
145
204
|
# Returns a new date/time representing the given day in the previous week.
|
146
205
|
# Week is assumed to start on +start_day+, default is
|
147
206
|
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
148
|
-
# DateTime objects have their time set to 0:00.
|
149
|
-
def prev_week(start_day = Date.beginning_of_week)
|
150
|
-
first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
|
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
|
151
211
|
end
|
152
212
|
alias_method :last_week, :prev_week
|
153
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
|
+
|
154
224
|
# Short-hand for months_ago(1).
|
155
225
|
def prev_month
|
156
226
|
months_ago(1)
|
@@ -246,17 +316,20 @@ module DateAndTime
|
|
246
316
|
end
|
247
317
|
|
248
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
|
249
322
|
|
250
|
-
|
251
|
-
|
252
|
-
|
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
|
253
326
|
|
254
|
-
|
255
|
-
|
256
|
-
|
327
|
+
def days_span(day)
|
328
|
+
(DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
|
329
|
+
end
|
257
330
|
|
258
|
-
|
259
|
-
|
260
|
-
|
331
|
+
def copy_time_to(other)
|
332
|
+
other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
|
333
|
+
end
|
261
334
|
end
|
262
335
|
end
|
@@ -4,8 +4,8 @@ module DateAndTime
|
|
4
4
|
# if Time.zone_default is set. Otherwise, it returns the current time.
|
5
5
|
#
|
6
6
|
# Time.zone = 'Hawaii' # => 'Hawaii'
|
7
|
-
#
|
8
|
-
# Date.new(2000).in_time_zone
|
7
|
+
# Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
8
|
+
# Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00
|
9
9
|
#
|
10
10
|
# This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
|
11
11
|
# instead of the operating system's time zone.
|
@@ -14,8 +14,7 @@ module DateAndTime
|
|
14
14
|
# and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
|
15
15
|
#
|
16
16
|
# Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
|
17
|
-
#
|
18
|
-
# Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
|
17
|
+
# Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
|
19
18
|
def in_time_zone(zone = ::Time.zone)
|
20
19
|
time_zone = ::Time.find_zone! zone
|
21
20
|
time = acts_like?(:time) ? self : nil
|
@@ -10,7 +10,11 @@ class DateTime
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
#
|
13
|
+
# Returns the number of seconds since 00:00:00.
|
14
|
+
#
|
15
|
+
# DateTime.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0
|
16
|
+
# DateTime.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296
|
17
|
+
# DateTime.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399
|
14
18
|
def seconds_since_midnight
|
15
19
|
sec + (min * 60) + (hour * 3600)
|
16
20
|
end
|
@@ -157,12 +161,17 @@ class DateTime
|
|
157
161
|
end
|
158
162
|
alias_method :getlocal, :localtime
|
159
163
|
|
160
|
-
# Returns a <tt>
|
164
|
+
# Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
|
161
165
|
#
|
162
166
|
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
|
163
167
|
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
|
164
168
|
def utc
|
165
|
-
new_offset(0)
|
169
|
+
utc = new_offset(0)
|
170
|
+
|
171
|
+
Time.utc(
|
172
|
+
utc.year, utc.month, utc.day,
|
173
|
+
utc.hour, utc.min, utc.sec + utc.sec_fraction
|
174
|
+
)
|
166
175
|
end
|
167
176
|
alias_method :getgm, :utc
|
168
177
|
alias_method :getutc, :utc
|
@@ -181,13 +190,10 @@ class DateTime
|
|
181
190
|
# Layers additional behavior on DateTime#<=> so that Time and
|
182
191
|
# ActiveSupport::TimeWithZone instances can be compared with a DateTime.
|
183
192
|
def <=>(other)
|
184
|
-
if other.
|
185
|
-
super
|
186
|
-
elsif other.respond_to? :to_datetime
|
193
|
+
if other.respond_to? :to_datetime
|
187
194
|
super other.to_datetime rescue nil
|
188
195
|
else
|
189
|
-
|
196
|
+
super
|
190
197
|
end
|
191
198
|
end
|
192
|
-
|
193
199
|
end
|
@@ -40,6 +40,8 @@ class DateTime
|
|
40
40
|
alias_method :to_default_s, :to_s if instance_methods(false).include?(:to_s)
|
41
41
|
alias_method :to_s, :to_formatted_s
|
42
42
|
|
43
|
+
# Returns a formatted string of the offset from UTC, or an alternative
|
44
|
+
# string if the time zone is already UTC.
|
43
45
|
#
|
44
46
|
# datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
|
45
47
|
# datetime.formatted_offset # => "-06:00"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/date_time/acts_like'
|
2
|
+
require 'active_support/core_ext/date_time/blank'
|
2
3
|
require 'active_support/core_ext/date_time/calculations'
|
3
4
|
require 'active_support/core_ext/date_time/compatibility'
|
4
5
|
require 'active_support/core_ext/date_time/conversions'
|
5
|
-
require 'active_support/core_ext/date_time/zones'
|