activesupport 3.2.22.5 → 4.0.0.beta1
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 +325 -136
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -2
- data/lib/active_support.rb +8 -21
- data/lib/active_support/backtrace_cleaner.rb +33 -25
- data/lib/active_support/basic_object.rb +7 -17
- data/lib/active_support/benchmarkable.rb +19 -15
- data/lib/active_support/buffered_logger.rb +9 -113
- data/lib/active_support/cache.rb +203 -171
- data/lib/active_support/cache/file_store.rb +12 -12
- data/lib/active_support/cache/mem_cache_store.rb +24 -30
- data/lib/active_support/cache/memory_store.rb +2 -0
- data/lib/active_support/callbacks.rb +195 -247
- data/lib/active_support/concern.rb +16 -23
- data/lib/active_support/concurrency/latch.rb +27 -0
- data/lib/active_support/configurable.rb +69 -12
- data/lib/active_support/core_ext.rb +1 -0
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/array/access.rb +17 -9
- data/lib/active_support/core_ext/array/conversions.rb +113 -55
- data/lib/active_support/core_ext/array/extract_options.rb +2 -2
- data/lib/active_support/core_ext/array/grouping.rb +21 -22
- data/lib/active_support/core_ext/array/uniq_by.rb +12 -9
- data/lib/active_support/core_ext/array/wrap.rb +11 -14
- data/lib/active_support/core_ext/big_decimal/conversions.rb +7 -24
- data/lib/active_support/core_ext/class/attribute.rb +12 -8
- data/lib/active_support/core_ext/class/attribute_accessors.rb +14 -12
- data/lib/active_support/core_ext/class/delegating_attributes.rb +15 -19
- data/lib/active_support/core_ext/class/subclasses.rb +11 -5
- data/lib/active_support/core_ext/date.rb +6 -0
- data/lib/active_support/core_ext/date/calculations.rb +34 -188
- data/lib/active_support/core_ext/date/conversions.rb +16 -38
- data/lib/active_support/core_ext/date/infinite_comparable.rb +5 -0
- data/lib/active_support/core_ext/date/zones.rb +25 -2
- data/lib/active_support/core_ext/date_and_time/calculations.rb +232 -0
- data/lib/active_support/core_ext/date_time.rb +5 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +0 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +73 -65
- data/lib/active_support/core_ext/date_time/conversions.rb +21 -33
- data/lib/active_support/core_ext/date_time/infinite_comparable.rb +5 -0
- data/lib/active_support/core_ext/date_time/zones.rb +11 -8
- data/lib/active_support/core_ext/enumerable.rb +26 -73
- data/lib/active_support/core_ext/file.rb +0 -1
- data/lib/active_support/core_ext/file/atomic.rb +27 -11
- data/lib/active_support/core_ext/hash.rb +0 -1
- data/lib/active_support/core_ext/hash/conversions.rb +145 -79
- data/lib/active_support/core_ext/hash/deep_merge.rb +14 -8
- data/lib/active_support/core_ext/hash/diff.rb +5 -4
- data/lib/active_support/core_ext/hash/except.rb +1 -9
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -5
- data/lib/active_support/core_ext/hash/keys.rb +108 -24
- data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
- data/lib/active_support/core_ext/hash/slice.rb +12 -12
- data/lib/active_support/core_ext/infinite_comparable.rb +35 -0
- data/lib/active_support/core_ext/integer/inflections.rb +13 -1
- data/lib/active_support/core_ext/integer/time.rb +17 -12
- data/lib/active_support/core_ext/kernel/debugger.rb +2 -2
- data/lib/active_support/core_ext/kernel/reporting.rb +36 -22
- data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
- data/lib/active_support/core_ext/load_error.rb +7 -5
- data/lib/active_support/core_ext/logger.rb +7 -23
- data/lib/active_support/core_ext/marshal.rb +19 -0
- data/lib/active_support/core_ext/module.rb +1 -3
- data/lib/active_support/core_ext/module/aliasing.rb +8 -9
- data/lib/active_support/core_ext/module/anonymous.rb +2 -7
- data/lib/active_support/core_ext/module/attr_internal.rb +0 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +12 -10
- data/lib/active_support/core_ext/module/delegation.rb +57 -40
- data/lib/active_support/core_ext/module/deprecation.rb +19 -3
- data/lib/active_support/core_ext/module/introspection.rb +17 -27
- data/lib/active_support/core_ext/module/qualified_const.rb +8 -20
- data/lib/active_support/core_ext/module/remove_method.rb +1 -5
- data/lib/active_support/core_ext/numeric.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +135 -0
- data/lib/active_support/core_ext/numeric/infinite_comparable.rb +9 -0
- data/lib/active_support/core_ext/numeric/time.rb +6 -6
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/object/acts_like.rb +4 -4
- data/lib/active_support/core_ext/object/blank.rb +7 -23
- data/lib/active_support/core_ext/object/deep_dup.rb +46 -0
- data/lib/active_support/core_ext/object/duplicable.rb +1 -30
- data/lib/active_support/core_ext/object/inclusion.rb +6 -6
- data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
- data/lib/active_support/core_ext/object/to_json.rb +8 -0
- data/lib/active_support/core_ext/object/to_param.rb +5 -2
- data/lib/active_support/core_ext/object/try.rb +46 -25
- data/lib/active_support/core_ext/object/with_options.rb +7 -8
- data/lib/active_support/core_ext/proc.rb +3 -0
- data/lib/active_support/core_ext/range.rb +0 -2
- data/lib/active_support/core_ext/range/conversions.rb +0 -2
- data/lib/active_support/core_ext/range/include_range.rb +1 -1
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/string.rb +2 -2
- data/lib/active_support/core_ext/string/access.rb +95 -90
- data/lib/active_support/core_ext/string/conversions.rb +29 -38
- data/lib/active_support/core_ext/string/encoding.rb +6 -9
- data/lib/active_support/core_ext/string/filters.rb +24 -18
- data/lib/active_support/core_ext/string/indent.rb +43 -0
- data/lib/active_support/core_ext/string/inflections.rb +70 -60
- data/lib/active_support/core_ext/string/inquiry.rb +2 -2
- data/lib/active_support/core_ext/string/multibyte.rb +41 -64
- data/lib/active_support/core_ext/string/output_safety.rb +59 -51
- data/lib/active_support/core_ext/string/zones.rb +13 -0
- data/lib/active_support/core_ext/struct.rb +6 -0
- data/lib/active_support/core_ext/thread.rb +74 -0
- data/lib/active_support/core_ext/time.rb +6 -0
- data/lib/active_support/core_ext/time/calculations.rb +105 -193
- data/lib/active_support/core_ext/time/conversions.rb +27 -51
- data/lib/active_support/core_ext/time/infinite_comparable.rb +5 -0
- data/lib/active_support/core_ext/time/marshal.rb +0 -27
- data/lib/active_support/core_ext/time/zones.rb +27 -17
- data/lib/active_support/core_ext/uri.rb +13 -17
- data/lib/active_support/dependencies.rb +160 -141
- data/lib/active_support/dependencies/autoload.rb +47 -20
- data/lib/active_support/deprecation.rb +39 -14
- data/lib/active_support/deprecation/behaviors.rb +44 -30
- data/lib/active_support/deprecation/instance_delegator.rb +24 -0
- data/lib/active_support/deprecation/method_wrappers.rb +33 -18
- data/lib/active_support/deprecation/proxy_wrappers.rb +58 -13
- data/lib/active_support/deprecation/reporting.rb +40 -11
- data/lib/active_support/descendants_tracker.rb +34 -19
- data/lib/active_support/duration.rb +6 -8
- data/lib/active_support/file_update_checker.rb +63 -47
- data/lib/active_support/gzip.rb +11 -5
- data/lib/active_support/hash_with_indifferent_access.rb +112 -37
- data/lib/active_support/i18n.rb +4 -0
- data/lib/active_support/i18n_railtie.rb +5 -22
- data/lib/active_support/inflections.rb +14 -12
- data/lib/active_support/inflector/inflections.rb +108 -71
- data/lib/active_support/inflector/methods.rb +181 -160
- data/lib/active_support/inflector/transliterate.rb +16 -17
- data/lib/active_support/json/decoding.rb +18 -17
- data/lib/active_support/json/encoding.rb +93 -39
- data/lib/active_support/json/variable.rb +10 -1
- data/lib/active_support/key_generator.rb +75 -0
- data/lib/active_support/lazy_load_hooks.rb +21 -19
- data/lib/active_support/locale/en.yml +100 -3
- data/lib/active_support/log_subscriber.rb +56 -36
- data/lib/active_support/log_subscriber/test_helper.rb +18 -15
- data/lib/active_support/logger.rb +57 -0
- data/lib/active_support/logger_silence.rb +24 -0
- data/lib/active_support/message_encryptor.rb +32 -29
- data/lib/active_support/message_verifier.rb +8 -14
- data/lib/active_support/multibyte.rb +5 -28
- data/lib/active_support/multibyte/chars.rb +80 -333
- data/lib/active_support/multibyte/unicode.rb +74 -64
- data/lib/active_support/notifications.rb +57 -25
- data/lib/active_support/notifications/fanout.rb +105 -18
- data/lib/active_support/notifications/instrumenter.rb +32 -13
- data/lib/active_support/number_helper.rb +636 -0
- data/lib/active_support/ordered_hash.rb +8 -190
- data/lib/active_support/ordered_options.rb +21 -23
- data/lib/active_support/proxy_object.rb +13 -0
- data/lib/active_support/rails.rb +27 -0
- data/lib/active_support/railtie.rb +12 -32
- data/lib/active_support/rescuable.rb +9 -4
- data/lib/active_support/string_inquirer.rb +13 -8
- data/lib/active_support/tagged_logging.rb +51 -73
- data/lib/active_support/test_case.rb +46 -17
- data/lib/active_support/testing/assertions.rb +56 -26
- data/lib/active_support/testing/autorun.rb +5 -0
- data/lib/active_support/testing/constant_lookup.rb +52 -0
- data/lib/active_support/testing/declarative.rb +1 -1
- data/lib/active_support/testing/deprecation.rb +0 -19
- data/lib/active_support/testing/isolation.rb +25 -58
- data/lib/active_support/testing/pending.rb +5 -43
- data/lib/active_support/testing/setup_and_teardown.rb +6 -92
- data/lib/active_support/testing/tagged_logging.rb +25 -0
- data/lib/active_support/time.rb +6 -21
- data/lib/active_support/time_with_zone.rb +78 -43
- data/lib/active_support/values/time_zone.rb +77 -58
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +4 -4
- data/lib/active_support/xml_mini.rb +35 -17
- data/lib/active_support/xml_mini/jdom.rb +9 -17
- data/lib/active_support/xml_mini/libxml.rb +1 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -2
- data/lib/active_support/xml_mini/nokogiri.rb +1 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -2
- data/lib/active_support/xml_mini/rexml.rb +6 -8
- metadata +107 -77
- data/lib/active_support/base64.rb +0 -54
- data/lib/active_support/core_ext/array/random_access.rb +0 -30
- data/lib/active_support/core_ext/date/freeze.rb +0 -33
- data/lib/active_support/core_ext/exception.rb +0 -3
- data/lib/active_support/core_ext/file/path.rb +0 -5
- data/lib/active_support/core_ext/float.rb +0 -1
- data/lib/active_support/core_ext/float/rounding.rb +0 -19
- data/lib/active_support/core_ext/hash/deep_dup.rb +0 -18
- data/lib/active_support/core_ext/io.rb +0 -15
- data/lib/active_support/core_ext/module/method_names.rb +0 -14
- data/lib/active_support/core_ext/module/synchronization.rb +0 -45
- data/lib/active_support/core_ext/process.rb +0 -1
- data/lib/active_support/core_ext/process/daemon.rb +0 -23
- data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
- data/lib/active_support/core_ext/range/cover.rb +0 -3
- data/lib/active_support/core_ext/rexml.rb +0 -46
- data/lib/active_support/core_ext/string/interpolation.rb +0 -2
- data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
- data/lib/active_support/memoizable.rb +0 -116
- data/lib/active_support/multibyte/exceptions.rb +0 -8
- data/lib/active_support/multibyte/utils.rb +0 -60
- data/lib/active_support/ruby/shim.rb +0 -22
- data/lib/active_support/security_utils.rb +0 -27
- data/lib/active_support/testing/mochaing.rb +0 -7
- data/lib/active_support/testing/performance.rb +0 -317
- data/lib/active_support/testing/performance/jruby.rb +0 -115
- data/lib/active_support/testing/performance/rubinius.rb +0 -113
- data/lib/active_support/testing/performance/ruby.rb +0 -152
- data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
- data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
- data/lib/active_support/time/autoload.rb +0 -5
- data/lib/active_support/whiny_nil.rb +0 -24
@@ -2,9 +2,9 @@ require 'active_support/string_inquirer'
|
|
2
2
|
|
3
3
|
class String
|
4
4
|
# Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
|
5
|
-
# which gives you a prettier way to test for equality.
|
5
|
+
# which gives you a prettier way to test for equality.
|
6
6
|
#
|
7
|
-
# env =
|
7
|
+
# env = 'production'.inquiry
|
8
8
|
# env.production? # => true
|
9
9
|
# env.development? # => false
|
10
10
|
def inquiry
|
@@ -2,71 +2,48 @@
|
|
2
2
|
require 'active_support/multibyte'
|
3
3
|
|
4
4
|
class String
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# information about how to change the default Multibyte behavior see ActiveSupport::Multibyte.
|
39
|
-
def mb_chars
|
40
|
-
if ActiveSupport::Multibyte.proxy_class.consumes?(self)
|
41
|
-
ActiveSupport::Multibyte.proxy_class.new(self)
|
42
|
-
else
|
43
|
-
self
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def is_utf8?
|
48
|
-
case encoding
|
49
|
-
when Encoding::UTF_8
|
50
|
-
valid_encoding?
|
51
|
-
when Encoding::ASCII_8BIT, Encoding::US_ASCII
|
52
|
-
dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
53
|
-
else
|
54
|
-
false
|
55
|
-
end
|
56
|
-
end
|
57
|
-
else
|
58
|
-
def mb_chars
|
59
|
-
if ActiveSupport::Multibyte.proxy_class.wants?(self)
|
60
|
-
ActiveSupport::Multibyte.proxy_class.new(self)
|
61
|
-
else
|
62
|
-
self
|
63
|
-
end
|
64
|
-
end
|
5
|
+
# == Multibyte proxy
|
6
|
+
#
|
7
|
+
# +mb_chars+ is a multibyte safe proxy for string methods.
|
8
|
+
#
|
9
|
+
# It creates and returns an instance of the ActiveSupport::Multibyte::Chars class which
|
10
|
+
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
11
|
+
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
12
|
+
#
|
13
|
+
# name = 'Claus Müller'
|
14
|
+
# name.reverse # => "rell??M sualC"
|
15
|
+
# name.length # => 13
|
16
|
+
#
|
17
|
+
# name.mb_chars.reverse.to_s # => "rellüM sualC"
|
18
|
+
# name.mb_chars.length # => 12
|
19
|
+
#
|
20
|
+
# == Method chaining
|
21
|
+
#
|
22
|
+
# All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
|
23
|
+
# method chaining on the result of any of these methods.
|
24
|
+
#
|
25
|
+
# name.mb_chars.reverse.length # => 12
|
26
|
+
#
|
27
|
+
# == Interoperability and configuration
|
28
|
+
#
|
29
|
+
# The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
|
30
|
+
# String and Char work like expected. The bang! methods change the internal string representation in the Chars
|
31
|
+
# object. Interoperability problems can be resolved easily with a +to_s+ call.
|
32
|
+
#
|
33
|
+
# For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars. For
|
34
|
+
# information about how to change the default Multibyte behavior see ActiveSupport::Multibyte.
|
35
|
+
def mb_chars
|
36
|
+
ActiveSupport::Multibyte.proxy_class.new(self)
|
37
|
+
end
|
65
38
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
39
|
+
def is_utf8?
|
40
|
+
case encoding
|
41
|
+
when Encoding::UTF_8
|
42
|
+
valid_encoding?
|
43
|
+
when Encoding::ASCII_8BIT, Encoding::US_ASCII
|
44
|
+
dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
45
|
+
else
|
46
|
+
false
|
70
47
|
end
|
71
48
|
end
|
72
49
|
end
|
@@ -3,35 +3,25 @@ require 'active_support/core_ext/kernel/singleton_class'
|
|
3
3
|
|
4
4
|
class ERB
|
5
5
|
module Util
|
6
|
-
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => '&#
|
6
|
+
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' }
|
7
7
|
JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
|
8
|
+
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
|
9
|
+
JSON_ESCAPE_REGEXP = /[&"><]/
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
s
|
21
|
-
|
22
|
-
|
23
|
-
else
|
24
|
-
s.gsub(/[&"'><]/, HTML_ESCAPE).html_safe
|
25
|
-
end
|
26
|
-
end
|
27
|
-
else
|
28
|
-
def html_escape(s) #:nodoc:
|
29
|
-
s = s.to_s
|
30
|
-
if s.html_safe?
|
31
|
-
s
|
32
|
-
else
|
33
|
-
s.gsub(/[&"'><]/n) { |special| HTML_ESCAPE[special] }.html_safe
|
34
|
-
end
|
11
|
+
# A utility method for escaping HTML tag characters.
|
12
|
+
# This method is also aliased as <tt>h</tt>.
|
13
|
+
#
|
14
|
+
# In your ERB templates, use this method to escape any unsafe content. For example:
|
15
|
+
# <%=h @person.name %>
|
16
|
+
#
|
17
|
+
# puts html_escape('is a > 0 & a < 10?')
|
18
|
+
# # => is a > 0 & a < 10?
|
19
|
+
def html_escape(s)
|
20
|
+
s = s.to_s
|
21
|
+
if s.html_safe?
|
22
|
+
s
|
23
|
+
else
|
24
|
+
s.gsub(/[&"'><]/, HTML_ESCAPE).html_safe
|
35
25
|
end
|
36
26
|
end
|
37
27
|
|
@@ -44,10 +34,24 @@ class ERB
|
|
44
34
|
singleton_class.send(:remove_method, :html_escape)
|
45
35
|
module_function :html_escape
|
46
36
|
|
37
|
+
# A utility method for escaping HTML without affecting existing escaped entities.
|
38
|
+
#
|
39
|
+
# html_escape_once('1 < 2 & 3')
|
40
|
+
# # => "1 < 2 & 3"
|
41
|
+
#
|
42
|
+
# html_escape_once('<< Accept & Checkout')
|
43
|
+
# # => "<< Accept & Checkout"
|
44
|
+
def html_escape_once(s)
|
45
|
+
result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP) { |special| HTML_ESCAPE[special] }
|
46
|
+
s.html_safe? ? result.html_safe : result
|
47
|
+
end
|
48
|
+
|
49
|
+
module_function :html_escape_once
|
50
|
+
|
47
51
|
# A utility method for escaping HTML entities in JSON strings
|
48
52
|
# using \uXXXX JavaScript escape sequences for string literals:
|
49
53
|
#
|
50
|
-
# json_escape(
|
54
|
+
# json_escape('is a > 0 & a < 10?')
|
51
55
|
# # => is a \u003E 0 \u0026 a \u003C 10?
|
52
56
|
#
|
53
57
|
# Note that after this operation is performed the output is not
|
@@ -55,19 +59,11 @@ class ERB
|
|
55
59
|
#
|
56
60
|
# json_escape('{"name":"john","created_at":"2010-04-28T01:39:31Z","id":1}')
|
57
61
|
# # => {name:john,created_at:2010-04-28T01:39:31Z,id:1}
|
58
|
-
#
|
59
|
-
# This method is also aliased as +j+, and available as a helper
|
60
|
-
# in Rails templates:
|
61
|
-
#
|
62
|
-
# <%=j @person.to_json %>
|
63
|
-
#
|
64
62
|
def json_escape(s)
|
65
|
-
result = s.to_s.gsub(
|
63
|
+
result = s.to_s.gsub(JSON_ESCAPE_REGEXP) { |special| JSON_ESCAPE[special] }
|
66
64
|
s.html_safe? ? result.html_safe : result
|
67
65
|
end
|
68
66
|
|
69
|
-
alias j json_escape
|
70
|
-
module_function :j
|
71
67
|
module_function :json_escape
|
72
68
|
end
|
73
69
|
end
|
@@ -86,26 +82,31 @@ end
|
|
86
82
|
|
87
83
|
module ActiveSupport #:nodoc:
|
88
84
|
class SafeBuffer < String
|
89
|
-
UNSAFE_STRING_METHODS =
|
85
|
+
UNSAFE_STRING_METHODS = %w(
|
86
|
+
capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
|
87
|
+
slice squeeze strip sub succ swapcase tr tr_s upcase prepend
|
88
|
+
)
|
90
89
|
|
91
90
|
alias_method :original_concat, :concat
|
92
91
|
private :original_concat
|
93
92
|
|
94
93
|
class SafeConcatError < StandardError
|
95
94
|
def initialize
|
96
|
-
super
|
95
|
+
super 'Could not concatenate to the buffer because it is not html safe.'
|
97
96
|
end
|
98
97
|
end
|
99
98
|
|
100
99
|
def [](*args)
|
101
|
-
|
102
|
-
|
103
|
-
if html_safe?
|
104
|
-
new_safe_buffer = super
|
105
|
-
new_safe_buffer.instance_eval { @html_safe = true }
|
106
|
-
new_safe_buffer
|
100
|
+
if args.size < 2
|
101
|
+
super
|
107
102
|
else
|
108
|
-
|
103
|
+
if html_safe?
|
104
|
+
new_safe_buffer = super
|
105
|
+
new_safe_buffer.instance_eval { @html_safe = true }
|
106
|
+
new_safe_buffer
|
107
|
+
else
|
108
|
+
to_str[*args]
|
109
|
+
end
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
@@ -141,6 +142,18 @@ module ActiveSupport #:nodoc:
|
|
141
142
|
dup.concat(other)
|
142
143
|
end
|
143
144
|
|
145
|
+
def %(args)
|
146
|
+
args = Array(args).map do |arg|
|
147
|
+
if !html_safe? || arg.html_safe?
|
148
|
+
arg
|
149
|
+
else
|
150
|
+
ERB::Util.h(arg)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
self.class.new(super(args))
|
155
|
+
end
|
156
|
+
|
144
157
|
def html_safe?
|
145
158
|
defined?(@html_safe) && @html_safe
|
146
159
|
end
|
@@ -157,11 +170,6 @@ module ActiveSupport #:nodoc:
|
|
157
170
|
coder.represent_scalar nil, to_str
|
158
171
|
end
|
159
172
|
|
160
|
-
def to_yaml(*args)
|
161
|
-
return super() if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
|
162
|
-
to_str.to_yaml(*args)
|
163
|
-
end
|
164
|
-
|
165
173
|
UNSAFE_STRING_METHODS.each do |unsafe_method|
|
166
174
|
if 'String'.respond_to?(unsafe_method)
|
167
175
|
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_support/core_ext/time/zones'
|
2
|
+
|
3
|
+
class String
|
4
|
+
# Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default
|
5
|
+
# is set, otherwise converts String to a Time via String#to_time
|
6
|
+
def in_time_zone(zone = ::Time.zone)
|
7
|
+
if zone
|
8
|
+
::Time.find_zone!(zone).parse(self)
|
9
|
+
else
|
10
|
+
to_time
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class Thread
|
2
|
+
LOCK = Mutex.new # :nodoc:
|
3
|
+
|
4
|
+
# Returns the value of a thread local variable that has been set. Note that
|
5
|
+
# these are different than fiber local values.
|
6
|
+
#
|
7
|
+
# Thread local values are carried along with threads, and do not respect
|
8
|
+
# fibers. For example:
|
9
|
+
#
|
10
|
+
# Thread.new {
|
11
|
+
# Thread.current.thread_variable_set("foo", "bar") # set a thread local
|
12
|
+
# Thread.current["foo"] = "bar" # set a fiber local
|
13
|
+
#
|
14
|
+
# Fiber.new {
|
15
|
+
# Fiber.yield [
|
16
|
+
# Thread.current.thread_variable_get("foo"), # get the thread local
|
17
|
+
# Thread.current["foo"], # get the fiber local
|
18
|
+
# ]
|
19
|
+
# }.resume
|
20
|
+
# }.join.value # => ['bar', nil]
|
21
|
+
#
|
22
|
+
# The value <tt>"bar"</tt> is returned for the thread local, where +nil+ is returned
|
23
|
+
# for the fiber local. The fiber is executed in the same thread, so the
|
24
|
+
# thread local values are available.
|
25
|
+
def thread_variable_get(key)
|
26
|
+
locals[key.to_sym]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sets a thread local with +key+ to +value+. Note that these are local to
|
30
|
+
# threads, and not to fibers. Please see Thread#thread_variable_get for
|
31
|
+
# more information.
|
32
|
+
def thread_variable_set(key, value)
|
33
|
+
locals[key.to_sym] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns an an array of the names of the thread-local variables (as Symbols).
|
37
|
+
#
|
38
|
+
# thr = Thread.new do
|
39
|
+
# Thread.current.thread_variable_set(:cat, 'meow')
|
40
|
+
# Thread.current.thread_variable_set("dog", 'woof')
|
41
|
+
# end
|
42
|
+
# thr.join #=> #<Thread:0x401b3f10 dead>
|
43
|
+
# thr.thread_variables #=> [:dog, :cat]
|
44
|
+
#
|
45
|
+
# Note that these are not fiber local variables. Please see Thread#thread_variable_get
|
46
|
+
# for more details.
|
47
|
+
def thread_variables
|
48
|
+
locals.keys
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns <tt>true</tt> if the given string (or symbol) exists as a
|
52
|
+
# thread-local variable.
|
53
|
+
#
|
54
|
+
# me = Thread.current
|
55
|
+
# me.thread_variable_set(:oliver, "a")
|
56
|
+
# me.thread_variable?(:oliver) #=> true
|
57
|
+
# me.thread_variable?(:stanley) #=> false
|
58
|
+
#
|
59
|
+
# Note that these are not fiber local variables. Please see Thread#thread_variable_get
|
60
|
+
# for more details.
|
61
|
+
def thread_variable?(key)
|
62
|
+
locals.has_key?(key.to_sym)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def locals
|
68
|
+
if defined?(@locals)
|
69
|
+
@locals
|
70
|
+
else
|
71
|
+
LOCK.synchronize { @locals ||= {} }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end unless Thread.instance_methods.include?(:thread_variable_set)
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require 'active_support/core_ext/time/acts_like'
|
2
|
+
require 'active_support/core_ext/time/calculations'
|
3
|
+
require 'active_support/core_ext/time/conversions'
|
4
|
+
require 'active_support/core_ext/time/marshal'
|
5
|
+
require 'active_support/core_ext/time/zones'
|
6
|
+
require 'active_support/core_ext/time/infinite_comparable'
|
@@ -2,10 +2,13 @@ require 'active_support/duration'
|
|
2
2
|
require 'active_support/core_ext/time/conversions'
|
3
3
|
require 'active_support/time_with_zone'
|
4
4
|
require 'active_support/core_ext/time/zones'
|
5
|
+
require 'active_support/core_ext/date_and_time/calculations'
|
6
|
+
require 'active_support/deprecation'
|
5
7
|
|
6
8
|
class Time
|
9
|
+
include DateAndTime::Calculations
|
10
|
+
|
7
11
|
COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
8
|
-
DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
|
9
12
|
|
10
13
|
class << self
|
11
14
|
# Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
|
@@ -16,28 +19,45 @@ class Time
|
|
16
19
|
# Return the number of days in the given month.
|
17
20
|
# If no year is specified, it will use the current year.
|
18
21
|
def days_in_month(month, year = now.year)
|
19
|
-
|
20
|
-
|
22
|
+
if month == 2 && ::Date.gregorian_leap?(year)
|
23
|
+
29
|
24
|
+
else
|
25
|
+
COMMON_YEAR_DAYS_IN_MONTH[month]
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
29
|
+
# *DEPRECATED*: Use +Time#utc+ or +Time#local+ instead.
|
30
|
+
#
|
23
31
|
# Returns a new Time if requested year can be accommodated by Ruby's Time class
|
24
32
|
# (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture);
|
25
33
|
# otherwise returns a DateTime.
|
26
34
|
def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
|
35
|
+
ActiveSupport::Deprecation.warn 'time_with_datetime_fallback is deprecated. Use Time#utc or Time#local instead', caller
|
27
36
|
time = ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
|
37
|
+
|
28
38
|
# This check is needed because Time.utc(y) returns a time object in the 2000s for 0 <= y <= 138.
|
29
|
-
time.year == year
|
39
|
+
if time.year == year
|
40
|
+
time
|
41
|
+
else
|
42
|
+
::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
|
43
|
+
end
|
30
44
|
rescue
|
31
45
|
::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec)
|
32
46
|
end
|
33
47
|
|
48
|
+
# *DEPRECATED*: Use +Time#utc+ instead.
|
49
|
+
#
|
34
50
|
# Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:utc</tt>.
|
35
51
|
def utc_time(*args)
|
52
|
+
ActiveSupport::Deprecation.warn 'utc_time is deprecated. Use Time#utc instead', caller
|
36
53
|
time_with_datetime_fallback(:utc, *args)
|
37
54
|
end
|
38
55
|
|
56
|
+
# *DEPRECATED*: Use +Time#local+ instead.
|
57
|
+
#
|
39
58
|
# Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:local</tt>.
|
40
59
|
def local_time(*args)
|
60
|
+
ActiveSupport::Deprecation.warn 'local_time is deprecated. Use Time#local instead', caller
|
41
61
|
time_with_datetime_fallback(:local, *args)
|
42
62
|
end
|
43
63
|
|
@@ -45,38 +65,6 @@ class Time
|
|
45
65
|
def current
|
46
66
|
::Time.zone ? ::Time.zone.now : ::Time.now
|
47
67
|
end
|
48
|
-
|
49
|
-
# Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
|
50
|
-
# instances can be used when called with a single argument
|
51
|
-
def at_with_coercion(*args)
|
52
|
-
return at_without_coercion(*args) if args.size != 1
|
53
|
-
|
54
|
-
# Time.at can be called with a time or numerical value
|
55
|
-
time_or_number = args.first
|
56
|
-
|
57
|
-
if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime)
|
58
|
-
at_without_coercion(time_or_number.to_f).getlocal
|
59
|
-
else
|
60
|
-
at_without_coercion(time_or_number)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
alias_method :at_without_coercion, :at
|
64
|
-
alias_method :at, :at_with_coercion
|
65
|
-
end
|
66
|
-
|
67
|
-
# Tells whether the Time object's time lies in the past
|
68
|
-
def past?
|
69
|
-
self < ::Time.current
|
70
|
-
end
|
71
|
-
|
72
|
-
# Tells whether the Time object's time is today
|
73
|
-
def today?
|
74
|
-
to_date == ::Date.current
|
75
|
-
end
|
76
|
-
|
77
|
-
# Tells whether the Time object's time lies in the future
|
78
|
-
def future?
|
79
|
-
self > ::Time.current
|
80
68
|
end
|
81
69
|
|
82
70
|
# Seconds since midnight: Time.now.seconds_since_midnight
|
@@ -84,20 +72,42 @@ class Time
|
|
84
72
|
to_i - change(:hour => 0).to_i + (usec / 1.0e+6)
|
85
73
|
end
|
86
74
|
|
87
|
-
# Returns
|
88
|
-
#
|
89
|
-
#
|
75
|
+
# Returns the number of seconds until 23:59:59.
|
76
|
+
#
|
77
|
+
# Time.new(2012, 8, 29, 0, 0, 0).seconds_until_end_of_day # => 86399
|
78
|
+
# Time.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
|
79
|
+
# Time.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
|
80
|
+
def seconds_until_end_of_day
|
81
|
+
end_of_day.to_i - to_i
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns a new Time where one or more of the elements have been changed according
|
85
|
+
# to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
|
86
|
+
# <tt>:sec</tt>, <tt>:usec</tt>) reset cascadingly, so if only the hour is passed,
|
87
|
+
# then minute, sec, and usec is set to 0. If the hour and minute is passed, then
|
88
|
+
# sec and usec is set to 0. The +options+ parameter takes a hash with any of these
|
89
|
+
# keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>,
|
90
|
+
# <tt>:sec</tt>, <tt>:usec</tt>.
|
91
|
+
#
|
92
|
+
# Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
|
93
|
+
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
|
94
|
+
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
|
90
95
|
def change(options)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
96
|
+
new_year = options.fetch(:year, year)
|
97
|
+
new_month = options.fetch(:month, month)
|
98
|
+
new_day = options.fetch(:day, day)
|
99
|
+
new_hour = options.fetch(:hour, hour)
|
100
|
+
new_min = options.fetch(:min, options[:hour] ? 0 : min)
|
101
|
+
new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
|
102
|
+
new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
|
103
|
+
|
104
|
+
if utc?
|
105
|
+
::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
|
106
|
+
elsif zone
|
107
|
+
::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
|
108
|
+
else
|
109
|
+
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
|
110
|
+
end
|
101
111
|
end
|
102
112
|
|
103
113
|
# Uses Date to provide precise Time calculations for years, months, and days.
|
@@ -107,18 +117,26 @@ class Time
|
|
107
117
|
def advance(options)
|
108
118
|
unless options[:weeks].nil?
|
109
119
|
options[:weeks], partial_weeks = options[:weeks].divmod(1)
|
110
|
-
options[:days] = (
|
120
|
+
options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
|
111
121
|
end
|
112
122
|
|
113
123
|
unless options[:days].nil?
|
114
124
|
options[:days], partial_days = options[:days].divmod(1)
|
115
|
-
options[:hours] = (
|
125
|
+
options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
|
116
126
|
end
|
117
127
|
|
118
128
|
d = to_date.advance(options)
|
119
129
|
time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
|
120
|
-
seconds_to_advance =
|
121
|
-
|
130
|
+
seconds_to_advance = \
|
131
|
+
options.fetch(:seconds, 0) +
|
132
|
+
options.fetch(:minutes, 0) * 60 +
|
133
|
+
options.fetch(:hours, 0) * 3600
|
134
|
+
|
135
|
+
if seconds_to_advance.zero?
|
136
|
+
time_advanced_by_date
|
137
|
+
else
|
138
|
+
time_advanced_by_date.since(seconds_to_advance)
|
139
|
+
end
|
122
140
|
end
|
123
141
|
|
124
142
|
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
|
@@ -134,98 +152,9 @@ class Time
|
|
134
152
|
end
|
135
153
|
alias :in :since
|
136
154
|
|
137
|
-
# Returns a new Time representing the time a number of specified weeks ago.
|
138
|
-
def weeks_ago(weeks)
|
139
|
-
advance(:weeks => -weeks)
|
140
|
-
end
|
141
|
-
|
142
|
-
# Returns a new Time representing the time a number of specified months ago
|
143
|
-
def months_ago(months)
|
144
|
-
advance(:months => -months)
|
145
|
-
end
|
146
|
-
|
147
|
-
# Returns a new Time representing the time a number of specified months in the future
|
148
|
-
def months_since(months)
|
149
|
-
advance(:months => months)
|
150
|
-
end
|
151
|
-
|
152
|
-
# Returns a new Time representing the time a number of specified years ago
|
153
|
-
def years_ago(years)
|
154
|
-
advance(:years => -years)
|
155
|
-
end
|
156
|
-
|
157
|
-
# Returns a new Time representing the time a number of specified years in the future
|
158
|
-
def years_since(years)
|
159
|
-
advance(:years => years)
|
160
|
-
end
|
161
|
-
|
162
|
-
# Short-hand for years_ago(1)
|
163
|
-
def prev_year
|
164
|
-
years_ago(1)
|
165
|
-
end
|
166
|
-
|
167
|
-
# Short-hand for years_since(1)
|
168
|
-
def next_year
|
169
|
-
years_since(1)
|
170
|
-
end
|
171
|
-
|
172
|
-
# Short-hand for months_ago(1)
|
173
|
-
def prev_month
|
174
|
-
months_ago(1)
|
175
|
-
end
|
176
|
-
|
177
|
-
# Short-hand for months_since(1)
|
178
|
-
def next_month
|
179
|
-
months_since(1)
|
180
|
-
end
|
181
|
-
|
182
|
-
# Returns number of days to start of this week, week starts on start_day (default is :monday).
|
183
|
-
def days_to_week_start(start_day = :monday)
|
184
|
-
start_day_number = DAYS_INTO_WEEK[start_day]
|
185
|
-
current_day_number = wday != 0 ? wday - 1 : 6
|
186
|
-
days_span = current_day_number - start_day_number
|
187
|
-
days_span >= 0 ? days_span : 7 + days_span
|
188
|
-
end
|
189
|
-
|
190
|
-
# Returns a new Time representing the "start" of this week, week starts on start_day (default is :monday, i.e. Monday, 0:00).
|
191
|
-
def beginning_of_week(start_day = :monday)
|
192
|
-
days_to_start = days_to_week_start(start_day)
|
193
|
-
(self - days_to_start.days).midnight
|
194
|
-
end
|
195
|
-
alias :at_beginning_of_week :beginning_of_week
|
196
|
-
|
197
|
-
# Returns a new +Date+/+DateTime+ representing the start of this week. Week is
|
198
|
-
# assumed to start on a Monday. +DateTime+ objects have their time set to 0:00.
|
199
|
-
def monday
|
200
|
-
beginning_of_week
|
201
|
-
end
|
202
|
-
|
203
|
-
# Returns a new Time representing the end of this week, week starts on start_day (default is :monday, i.e. end of Sunday).
|
204
|
-
def end_of_week(start_day = :monday)
|
205
|
-
days_to_end = 6 - days_to_week_start(start_day)
|
206
|
-
(self + days_to_end.days).end_of_day
|
207
|
-
end
|
208
|
-
alias :at_end_of_week :end_of_week
|
209
|
-
|
210
|
-
# Returns a new +Date+/+DateTime+ representing the end of this week. Week is
|
211
|
-
# assumed to start on a Monday. +DateTime+ objects have their time set to 23:59:59.
|
212
|
-
def sunday
|
213
|
-
end_of_week
|
214
|
-
end
|
215
|
-
|
216
|
-
# Returns a new Time representing the start of the given day in the previous week (default is :monday).
|
217
|
-
def prev_week(day = :monday)
|
218
|
-
ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
|
219
|
-
end
|
220
|
-
|
221
|
-
# Returns a new Time representing the start of the given day in next week (default is :monday).
|
222
|
-
def next_week(day = :monday)
|
223
|
-
since(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
|
224
|
-
end
|
225
|
-
|
226
155
|
# Returns a new Time representing the start of the day (0:00)
|
227
156
|
def beginning_of_day
|
228
|
-
#(self - seconds_since_midnight).change(:
|
157
|
+
#(self - seconds_since_midnight).change(usec: 0)
|
229
158
|
change(:hour => 0)
|
230
159
|
end
|
231
160
|
alias :midnight :beginning_of_day
|
@@ -234,8 +163,14 @@ class Time
|
|
234
163
|
|
235
164
|
# Returns a new Time representing the end of the day, 23:59:59.999999 (.999999999 in ruby1.9)
|
236
165
|
def end_of_day
|
237
|
-
change(
|
166
|
+
change(
|
167
|
+
:hour => 23,
|
168
|
+
:min => 59,
|
169
|
+
:sec => 59,
|
170
|
+
:usec => Rational(999999999, 1000)
|
171
|
+
)
|
238
172
|
end
|
173
|
+
alias :at_end_of_day :end_of_day
|
239
174
|
|
240
175
|
# Returns a new Time representing the start of the hour (x:00)
|
241
176
|
def beginning_of_hour
|
@@ -245,65 +180,37 @@ class Time
|
|
245
180
|
|
246
181
|
# Returns a new Time representing the end of the hour, x:59:59.999999 (.999999999 in ruby1.9)
|
247
182
|
def end_of_hour
|
248
|
-
change(
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
254
|
-
change(:day => 1, :hour => 0)
|
255
|
-
end
|
256
|
-
alias :at_beginning_of_month :beginning_of_month
|
257
|
-
|
258
|
-
# Returns a new Time representing the end of the month (end of the last day of the month)
|
259
|
-
def end_of_month
|
260
|
-
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
261
|
-
last_day = ::Time.days_in_month(month, year)
|
262
|
-
change(:day => last_day, :hour => 23, :min => 59, :sec => 59, :usec => Rational(999999999, 1000))
|
263
|
-
end
|
264
|
-
alias :at_end_of_month :end_of_month
|
265
|
-
|
266
|
-
# Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
|
267
|
-
def beginning_of_quarter
|
268
|
-
beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= month })
|
269
|
-
end
|
270
|
-
alias :at_beginning_of_quarter :beginning_of_quarter
|
271
|
-
|
272
|
-
# Returns a new Time representing the end of the quarter (end of the last day of march, june, september, december)
|
273
|
-
def end_of_quarter
|
274
|
-
beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= month }).end_of_month
|
275
|
-
end
|
276
|
-
alias :at_end_of_quarter :end_of_quarter
|
277
|
-
|
278
|
-
# Returns a new Time representing the start of the year (1st of january, 0:00)
|
279
|
-
def beginning_of_year
|
280
|
-
change(:month => 1, :day => 1, :hour => 0)
|
281
|
-
end
|
282
|
-
alias :at_beginning_of_year :beginning_of_year
|
283
|
-
|
284
|
-
# Returns a new Time representing the end of the year (end of the 31st of december)
|
285
|
-
def end_of_year
|
286
|
-
change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59, :usec => Rational(999999999, 1000))
|
183
|
+
change(
|
184
|
+
:min => 59,
|
185
|
+
:sec => 59,
|
186
|
+
:usec => Rational(999999999, 1000)
|
187
|
+
)
|
287
188
|
end
|
288
|
-
alias :
|
189
|
+
alias :at_end_of_hour :end_of_hour
|
289
190
|
|
290
|
-
#
|
291
|
-
def
|
292
|
-
|
191
|
+
# Returns a new Time representing the start of the minute (x:xx:00)
|
192
|
+
def beginning_of_minute
|
193
|
+
change(:sec => 0)
|
293
194
|
end
|
195
|
+
alias :at_beginning_of_minute :beginning_of_minute
|
294
196
|
|
295
|
-
#
|
296
|
-
def
|
297
|
-
|
197
|
+
# Returns a new Time representing the end of the minute, x:xx:59.999999 (.999999999 in ruby1.9)
|
198
|
+
def end_of_minute
|
199
|
+
change(
|
200
|
+
:sec => 59,
|
201
|
+
:usec => Rational(999999999, 1000)
|
202
|
+
)
|
298
203
|
end
|
204
|
+
alias :at_end_of_minute :end_of_minute
|
299
205
|
|
300
206
|
# Returns a Range representing the whole day of the current time.
|
301
207
|
def all_day
|
302
208
|
beginning_of_day..end_of_day
|
303
209
|
end
|
304
210
|
|
305
|
-
# Returns a Range representing the whole week of the current time.
|
306
|
-
|
211
|
+
# Returns a Range representing the whole week of the current time.
|
212
|
+
# Week starts on start_day, default is <tt>Date.week_start</tt> or <tt>config.week_start</tt> when set.
|
213
|
+
def all_week(start_day = Date.beginning_of_week)
|
307
214
|
beginning_of_week(start_day)..end_of_week(start_day)
|
308
215
|
end
|
309
216
|
|
@@ -356,7 +263,11 @@ class Time
|
|
356
263
|
# can be chronologically compared with a Time
|
357
264
|
def compare_with_coercion(other)
|
358
265
|
# we're avoiding Time#to_datetime cause it's expensive
|
359
|
-
other.is_a?(Time)
|
266
|
+
if other.is_a?(Time)
|
267
|
+
compare_without_coercion(other.to_time)
|
268
|
+
else
|
269
|
+
to_datetime <=> other
|
270
|
+
end
|
360
271
|
end
|
361
272
|
alias_method :compare_without_coercion, :<=>
|
362
273
|
alias_method :<=>, :compare_with_coercion
|
@@ -370,4 +281,5 @@ class Time
|
|
370
281
|
end
|
371
282
|
alias_method :eql_without_coercion, :eql?
|
372
283
|
alias_method :eql?, :eql_with_coercion
|
284
|
+
|
373
285
|
end
|