activesupport 5.0.0 → 6.1.0
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 +5 -5
- data/CHANGELOG.md +343 -590
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +11 -5
- data/lib/active_support/backtrace_cleaner.rb +33 -5
- data/lib/active_support/benchmarkable.rb +5 -3
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +45 -53
- data/lib/active_support/cache/mem_cache_store.rb +81 -79
- data/lib/active_support/cache/memory_store.rb +69 -41
- data/lib/active_support/cache/null_store.rb +11 -4
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +74 -37
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +332 -161
- data/lib/active_support/callbacks.rb +657 -586
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +59 -19
- data/lib/active_support/configurable.rb +15 -17
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +20 -18
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +3 -1
- data/lib/active_support/core_ext/array/inquiry.rb +3 -1
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +9 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -26
- data/lib/active_support/core_ext/class.rb +4 -2
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +3 -1
- data/lib/active_support/core_ext/date/calculations.rb +16 -13
- data/lib/active_support/core_ext/date/conversions.rb +23 -21
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +7 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
- data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +3 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
- data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +165 -29
- data/lib/active_support/core_ext/file/atomic.rb +7 -5
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +40 -39
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
- data/lib/active_support/core_ext/hash/keys.rb +9 -36
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +3 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +2 -23
- data/lib/active_support/core_ext/marshal.rb +6 -2
- data/lib/active_support/core_ext/module/aliasing.rb +5 -48
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
- data/lib/active_support/core_ext/module/concerning.rb +16 -11
- data/lib/active_support/core_ext/module/delegation.rb +159 -44
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +23 -26
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +13 -12
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
- data/lib/active_support/core_ext/numeric/time.rb +18 -26
- data/lib/active_support/core_ext/numeric.rb +5 -4
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +14 -2
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
- data/lib/active_support/core_ext/object/duplicable.rb +13 -62
- data/lib/active_support/core_ext/object/inclusion.rb +3 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +42 -15
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +20 -8
- data/lib/active_support/core_ext/object/with_options.rb +15 -2
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +28 -6
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +5 -2
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +47 -4
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +78 -29
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +10 -5
- data/lib/active_support/core_ext/string/output_safety.rb +86 -31
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +117 -45
- data/lib/active_support/core_ext/time/compatibility.rb +13 -2
- data/lib/active_support/core_ext/time/conversions.rb +18 -12
- data/lib/active_support/core_ext/time/zones.rb +9 -7
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/uri.rb +12 -7
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +7 -1
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +172 -98
- data/lib/active_support/deprecation/behaviors.rb +45 -13
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +32 -17
- data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
- data/lib/active_support/deprecation/reporting.rb +61 -16
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +67 -66
- data/lib/active_support/duration/iso8601_serializer.rb +25 -17
- data/lib/active_support/duration.rb +349 -46
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +88 -112
- data/lib/active_support/execution_wrapper.rb +25 -13
- data/lib/active_support/executor.rb +3 -1
- data/lib/active_support/file_update_checker.rb +56 -51
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +4 -2
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +153 -49
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +30 -20
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +28 -15
- data/lib/active_support/inflector/methods.rb +120 -109
- data/lib/active_support/inflector/transliterate.rb +60 -25
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +30 -29
- data/lib/active_support/json/encoding.rb +22 -11
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +6 -36
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +11 -9
- data/lib/active_support/log_subscriber.rb +51 -18
- data/lib/active_support/logger.rb +9 -22
- data/lib/active_support/logger_silence.rb +14 -21
- data/lib/active_support/logger_thread_safe_level.rb +55 -8
- data/lib/active_support/message_encryptor.rb +170 -53
- data/lib/active_support/message_verifier.rb +91 -20
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +24 -78
- data/lib/active_support/multibyte/unicode.rb +21 -352
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +121 -19
- data/lib/active_support/notifications/instrumenter.rb +78 -14
- data/lib/active_support/notifications.rb +80 -12
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +45 -16
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +23 -9
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +7 -5
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +8 -9
- data/lib/active_support/railtie.rb +62 -11
- data/lib/active_support/reloader.rb +12 -11
- data/lib/active_support/rescuable.rb +20 -11
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +12 -3
- data/lib/active_support/subscriber.rb +77 -23
- data/lib/active_support/tagged_logging.rb +52 -17
- data/lib/active_support/test_case.rb +106 -29
- data/lib/active_support/testing/assertions.rb +144 -8
- data/lib/active_support/testing/autorun.rb +5 -10
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +4 -2
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +19 -24
- data/lib/active_support/testing/method_call_assertions.rb +31 -2
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +30 -29
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +125 -24
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +142 -55
- data/lib/active_support/values/time_zone.rb +160 -53
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +115 -114
- data/lib/active_support/xml_mini/libxml.rb +15 -14
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +13 -13
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +18 -9
- data/lib/active_support/xml_mini.rb +44 -42
- data/lib/active_support.rb +19 -10
- metadata +79 -37
- data/lib/active_support/concurrency/latch.rb +0 -19
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -20
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/struct.rb +0 -3
- data/lib/active_support/core_ext/time/marshal.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,48 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module/redefine_method"
|
4
|
+
require "active_support/core_ext/time/calculations"
|
5
|
+
require "concurrent/map"
|
6
|
+
|
1
7
|
module ActiveSupport
|
2
8
|
module Testing
|
9
|
+
# Manages stubs for TimeHelpers
|
3
10
|
class SimpleStubs # :nodoc:
|
4
11
|
Stub = Struct.new(:object, :method_name, :original_method)
|
5
12
|
|
6
13
|
def initialize
|
7
|
-
@stubs = {}
|
14
|
+
@stubs = Concurrent::Map.new { |h, k| h[k] = {} }
|
8
15
|
end
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
17
|
+
# Stubs object.method_name with the given block
|
18
|
+
# If the method is already stubbed, remove that stub
|
19
|
+
# so that removing this stub will restore the original implementation.
|
20
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
21
|
+
# target = Time.zone.local(2004, 11, 24, 1, 4, 44)
|
22
|
+
# simple_stubs.stub_object(Time, :now) { at(target.to_i) }
|
23
|
+
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
24
|
+
def stub_object(object, method_name, &block)
|
25
|
+
if stub = stubbing(object, method_name)
|
14
26
|
unstub_object(stub)
|
15
27
|
end
|
16
28
|
|
17
29
|
new_name = "__simple_stub__#{method_name}"
|
18
30
|
|
19
|
-
@stubs[
|
31
|
+
@stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
|
20
32
|
|
21
|
-
object.singleton_class.
|
22
|
-
object.define_singleton_method(method_name)
|
33
|
+
object.singleton_class.alias_method new_name, method_name
|
34
|
+
object.define_singleton_method(method_name, &block)
|
23
35
|
end
|
24
36
|
|
37
|
+
# Remove all object-method stubs held by this instance
|
25
38
|
def unstub_all!
|
26
|
-
@stubs.each_value do |
|
27
|
-
|
39
|
+
@stubs.each_value do |object_stubs|
|
40
|
+
object_stubs.each_value do |stub|
|
41
|
+
unstub_object(stub)
|
42
|
+
end
|
28
43
|
end
|
29
|
-
@stubs
|
44
|
+
@stubs.clear
|
30
45
|
end
|
31
46
|
|
32
|
-
|
47
|
+
# Returns the Stub for object#method_name
|
48
|
+
# (nil if it is not stubbed)
|
49
|
+
def stubbing(object, method_name)
|
50
|
+
@stubs[object.object_id][method_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns true if any stubs are set, false if there are none
|
54
|
+
def stubbed?
|
55
|
+
!@stubs.empty?
|
56
|
+
end
|
33
57
|
|
58
|
+
private
|
59
|
+
# Restores the original object.method described by the Stub
|
34
60
|
def unstub_object(stub)
|
35
61
|
singleton_class = stub.object.singleton_class
|
36
|
-
singleton_class.
|
37
|
-
singleton_class.
|
38
|
-
singleton_class.
|
62
|
+
singleton_class.silence_redefinition_of_method stub.method_name
|
63
|
+
singleton_class.alias_method stub.method_name, stub.original_method
|
64
|
+
singleton_class.undef_method stub.original_method
|
39
65
|
end
|
40
66
|
end
|
41
67
|
|
42
68
|
# Contains helpers that help you test passage of time.
|
43
69
|
module TimeHelpers
|
70
|
+
def after_teardown
|
71
|
+
travel_back
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
44
75
|
# Changes current time to the time in the future or in the past by a given time difference by
|
45
|
-
# stubbing +Time.now+, +Date.today+, and +DateTime.now+.
|
76
|
+
# stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
|
77
|
+
# at the end of the test.
|
46
78
|
#
|
47
79
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
48
80
|
# travel 1.day
|
@@ -64,9 +96,10 @@ module ActiveSupport
|
|
64
96
|
|
65
97
|
# Changes current time to the given time by stubbing +Time.now+,
|
66
98
|
# +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
|
99
|
+
# The stubs are automatically removed at the end of the test.
|
67
100
|
#
|
68
101
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
69
|
-
# travel_to Time.
|
102
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
|
70
103
|
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
71
104
|
# Date.current # => Wed, 24 Nov 2004
|
72
105
|
# DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
|
@@ -88,20 +121,48 @@ module ActiveSupport
|
|
88
121
|
# state at the end of the block:
|
89
122
|
#
|
90
123
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
91
|
-
# travel_to Time.
|
124
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44) do
|
92
125
|
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
93
126
|
# end
|
94
127
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
95
128
|
def travel_to(date_or_time)
|
129
|
+
if block_given? && simple_stubs.stubbing(Time, :now)
|
130
|
+
travel_to_nested_block_call = <<~MSG
|
131
|
+
|
132
|
+
Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
|
133
|
+
|
134
|
+
Instead of:
|
135
|
+
|
136
|
+
travel_to 2.days.from_now do
|
137
|
+
# 2 days from today
|
138
|
+
travel_to 3.days.from_now do
|
139
|
+
# 5 days from today
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
preferred way to achieve above is:
|
144
|
+
|
145
|
+
travel 2.days do
|
146
|
+
# 2 days from today
|
147
|
+
end
|
148
|
+
|
149
|
+
travel 5.days do
|
150
|
+
# 5 days from today
|
151
|
+
end
|
152
|
+
|
153
|
+
MSG
|
154
|
+
raise travel_to_nested_block_call
|
155
|
+
end
|
156
|
+
|
96
157
|
if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
|
97
158
|
now = date_or_time.midnight.to_time
|
98
159
|
else
|
99
160
|
now = date_or_time.to_time.change(usec: 0)
|
100
161
|
end
|
101
162
|
|
102
|
-
simple_stubs.stub_object(Time, :now
|
103
|
-
simple_stubs.stub_object(Date, :today
|
104
|
-
simple_stubs.stub_object(DateTime, :now, now.
|
163
|
+
simple_stubs.stub_object(Time, :now) { at(now.to_i) }
|
164
|
+
simple_stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
|
165
|
+
simple_stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
|
105
166
|
|
106
167
|
if block_given?
|
107
168
|
begin
|
@@ -113,19 +174,59 @@ module ActiveSupport
|
|
113
174
|
end
|
114
175
|
|
115
176
|
# Returns the current time back to its original state, by removing the stubs added by
|
116
|
-
#
|
177
|
+
# +travel+, +travel_to+, and +freeze_time+.
|
117
178
|
#
|
118
179
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
119
|
-
#
|
180
|
+
#
|
181
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
|
120
182
|
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
183
|
+
#
|
121
184
|
# travel_back
|
122
185
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
186
|
+
#
|
187
|
+
# This method also accepts a block, which brings the stubs back at the end of the block:
|
188
|
+
#
|
189
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
190
|
+
#
|
191
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
|
192
|
+
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
193
|
+
#
|
194
|
+
# travel_back do
|
195
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
123
199
|
def travel_back
|
200
|
+
stubbed_time = Time.current if block_given? && simple_stubs.stubbed?
|
201
|
+
|
124
202
|
simple_stubs.unstub_all!
|
203
|
+
yield if block_given?
|
204
|
+
ensure
|
205
|
+
travel_to stubbed_time if stubbed_time
|
125
206
|
end
|
207
|
+
alias_method :unfreeze_time, :travel_back
|
126
208
|
|
127
|
-
|
209
|
+
# Calls +travel_to+ with +Time.now+.
|
210
|
+
#
|
211
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
212
|
+
# freeze_time
|
213
|
+
# sleep(1)
|
214
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
215
|
+
#
|
216
|
+
# This method also accepts a block, which will return the current time back to its original
|
217
|
+
# state at the end of the block:
|
218
|
+
#
|
219
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
220
|
+
# freeze_time do
|
221
|
+
# sleep(1)
|
222
|
+
# User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
223
|
+
# end
|
224
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
|
225
|
+
def freeze_time(&block)
|
226
|
+
travel_to Time.now, &block
|
227
|
+
end
|
128
228
|
|
229
|
+
private
|
129
230
|
def simple_stubs
|
130
231
|
@simple_stubs ||= SimpleStubs.new
|
131
232
|
end
|
data/lib/active_support/time.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
|
-
autoload :Duration,
|
3
|
-
autoload :TimeWithZone,
|
4
|
-
autoload :TimeZone,
|
4
|
+
autoload :Duration, "active_support/duration"
|
5
|
+
autoload :TimeWithZone, "active_support/time_with_zone"
|
6
|
+
autoload :TimeZone, "active_support/values/time_zone"
|
5
7
|
end
|
6
8
|
|
7
|
-
require
|
8
|
-
require
|
9
|
+
require "date"
|
10
|
+
require "time"
|
9
11
|
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
12
|
+
require "active_support/core_ext/time"
|
13
|
+
require "active_support/core_ext/date"
|
14
|
+
require "active_support/core_ext/date_time"
|
13
15
|
|
14
|
-
require
|
15
|
-
require
|
16
|
+
require "active_support/core_ext/integer/time"
|
17
|
+
require "active_support/core_ext/numeric/time"
|
16
18
|
|
17
|
-
require
|
18
|
-
require
|
19
|
+
require "active_support/core_ext/string/conversions"
|
20
|
+
require "active_support/core_ext/string/zones"
|
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/duration"
|
4
|
+
require "active_support/values/time_zone"
|
5
|
+
require "active_support/core_ext/object/acts_like"
|
6
|
+
require "active_support/core_ext/date_and_time/compatibility"
|
5
7
|
|
6
8
|
module ActiveSupport
|
7
9
|
# A Time-like class that can represent a time in any time zone. Necessary
|
@@ -13,37 +15,36 @@ module ActiveSupport
|
|
13
15
|
# and +in_time_zone+ on Time and DateTime instances.
|
14
16
|
#
|
15
17
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
16
|
-
# Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
17
|
-
# Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
18
|
-
# Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
19
|
-
# Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
|
20
|
-
# Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
18
|
+
# Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
|
19
|
+
# Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
|
20
|
+
# Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
|
21
|
+
# Time.zone.now # => Sun, 18 May 2008 13:07:55.754107581 EDT -04:00
|
22
|
+
# Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
|
21
23
|
#
|
22
24
|
# See Time and TimeZone for further documentation of these methods.
|
23
25
|
#
|
24
26
|
# TimeWithZone instances implement the same API as Ruby Time instances, so
|
25
27
|
# that Time and TimeWithZone instances are interchangeable.
|
26
28
|
#
|
27
|
-
# t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00
|
29
|
+
# t = Time.zone.now # => Sun, 18 May 2008 13:27:25.031505668 EDT -04:00
|
28
30
|
# t.hour # => 13
|
29
31
|
# t.dst? # => true
|
30
32
|
# t.utc_offset # => -14400
|
31
33
|
# t.zone # => "EDT"
|
32
34
|
# t.to_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400"
|
33
|
-
# t + 1.day # => Mon, 19 May 2008 13:27:25 EDT -04:00
|
34
|
-
# t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00 EST -05:00
|
35
|
+
# t + 1.day # => Mon, 19 May 2008 13:27:25.031505668 EDT -04:00
|
36
|
+
# t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00.000000000 EST -05:00
|
35
37
|
# t > Time.utc(1999) # => true
|
36
38
|
# t.is_a?(Time) # => true
|
37
39
|
# t.is_a?(ActiveSupport::TimeWithZone) # => true
|
38
40
|
class TimeWithZone
|
39
|
-
|
40
41
|
# Report class name as 'Time' to thwart type checking.
|
41
42
|
def self.name
|
42
|
-
|
43
|
+
"Time"
|
43
44
|
end
|
44
45
|
|
45
|
-
PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N"
|
46
|
-
PRECISIONS[0] =
|
46
|
+
PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N" }
|
47
|
+
PRECISIONS[0] = "%FT%T"
|
47
48
|
|
48
49
|
include Comparable, DateAndTime::Compatibility
|
49
50
|
attr_reader :time_zone
|
@@ -56,12 +57,12 @@ module ActiveSupport
|
|
56
57
|
|
57
58
|
# Returns a <tt>Time</tt> instance that represents the time in +time_zone+.
|
58
59
|
def time
|
59
|
-
@time ||=
|
60
|
+
@time ||= incorporate_utc_offset(@utc, utc_offset)
|
60
61
|
end
|
61
62
|
|
62
63
|
# Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
|
63
64
|
def utc
|
64
|
-
@utc ||=
|
65
|
+
@utc ||= incorporate_utc_offset(@time, -utc_offset)
|
65
66
|
end
|
66
67
|
alias_method :comparable_time, :utc
|
67
68
|
alias_method :getgm, :utc
|
@@ -103,13 +104,13 @@ module ActiveSupport
|
|
103
104
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
104
105
|
# Time.zone.now.utc? # => false
|
105
106
|
def utc?
|
106
|
-
|
107
|
+
zone == "UTC" || zone == "UCT"
|
107
108
|
end
|
108
109
|
alias_method :gmt?, :utc?
|
109
110
|
|
110
111
|
# Returns the offset from current time to UTC time in seconds.
|
111
112
|
def utc_offset
|
112
|
-
period.
|
113
|
+
period.observed_utc_offset
|
113
114
|
end
|
114
115
|
alias_method :gmt_offset, :utc_offset
|
115
116
|
alias_method :gmtoff, :utc_offset
|
@@ -131,14 +132,14 @@ module ActiveSupport
|
|
131
132
|
# Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
|
132
133
|
# Time.zone.now.zone # => "EST"
|
133
134
|
def zone
|
134
|
-
period.
|
135
|
+
period.abbreviation
|
135
136
|
end
|
136
137
|
|
137
|
-
# Returns a string of the object's date, time, zone and offset from UTC.
|
138
|
+
# Returns a string of the object's date, time, zone, and offset from UTC.
|
138
139
|
#
|
139
|
-
# Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
|
140
|
+
# Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25.624541392 EST -05:00"
|
140
141
|
def inspect
|
141
|
-
"#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
|
142
|
+
"#{time.strftime('%a, %d %b %Y %H:%M:%S.%9N')} #{zone} #{formatted_offset}"
|
142
143
|
end
|
143
144
|
|
144
145
|
# Returns a string of the object's date and time in the ISO 8601 standard
|
@@ -146,9 +147,10 @@ module ActiveSupport
|
|
146
147
|
#
|
147
148
|
# Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00"
|
148
149
|
def xmlschema(fraction_digits = 0)
|
149
|
-
"#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'
|
150
|
+
"#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z')}"
|
150
151
|
end
|
151
152
|
alias_method :iso8601, :xmlschema
|
153
|
+
alias_method :rfc3339, :xmlschema
|
152
154
|
|
153
155
|
# Coerces time to a string for JSON encoding. The default format is ISO 8601.
|
154
156
|
# You can get %Y/%m/%d %H:%M:%S +offset style by setting
|
@@ -171,12 +173,12 @@ module ActiveSupport
|
|
171
173
|
end
|
172
174
|
|
173
175
|
def init_with(coder) #:nodoc:
|
174
|
-
initialize(coder[
|
176
|
+
initialize(coder["utc"], coder["zone"], coder["time"])
|
175
177
|
end
|
176
178
|
|
177
179
|
def encode_with(coder) #:nodoc:
|
178
|
-
coder.tag =
|
179
|
-
coder.map = {
|
180
|
+
coder.tag = "!ruby/object:ActiveSupport::TimeWithZone"
|
181
|
+
coder.map = { "utc" => utc, "zone" => time_zone, "time" => time }
|
180
182
|
end
|
181
183
|
|
182
184
|
# Returns a string of the object's date and time in the format used by
|
@@ -223,6 +225,8 @@ module ActiveSupport
|
|
223
225
|
def <=>(other)
|
224
226
|
utc <=> other
|
225
227
|
end
|
228
|
+
alias_method :before?, :<
|
229
|
+
alias_method :after?, :>
|
226
230
|
|
227
231
|
# Returns true if the current object's time is within the specified
|
228
232
|
# +min+ and +max+ time.
|
@@ -241,6 +245,20 @@ module ActiveSupport
|
|
241
245
|
time.today?
|
242
246
|
end
|
243
247
|
|
248
|
+
# Returns true if the current object's time falls within
|
249
|
+
# the next day (tomorrow).
|
250
|
+
def tomorrow?
|
251
|
+
time.tomorrow?
|
252
|
+
end
|
253
|
+
alias :next_day? :tomorrow?
|
254
|
+
|
255
|
+
# Returns true if the current object's time falls within
|
256
|
+
# the previous day (yesterday).
|
257
|
+
def yesterday?
|
258
|
+
time.yesterday?
|
259
|
+
end
|
260
|
+
alias :prev_day? :yesterday?
|
261
|
+
|
244
262
|
# Returns true if the current object's time is in the future.
|
245
263
|
def future?
|
246
264
|
utc.future?
|
@@ -259,8 +277,8 @@ module ActiveSupport
|
|
259
277
|
# value as a new TimeWithZone object.
|
260
278
|
#
|
261
279
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
262
|
-
# now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
|
263
|
-
# now + 1000 # => Sun, 02 Nov 2014 01:43:08 EDT -04:00
|
280
|
+
# now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28.725182881 EDT -04:00
|
281
|
+
# now + 1000 # => Sun, 02 Nov 2014 01:43:08.725182881 EDT -04:00
|
264
282
|
#
|
265
283
|
# If we're adding a Duration of variable length (i.e., years, months, days),
|
266
284
|
# move forward from #time, otherwise move forward from #utc, for accuracy
|
@@ -269,8 +287,8 @@ module ActiveSupport
|
|
269
287
|
# For instance, a time + 24.hours will advance exactly 24 hours, while a
|
270
288
|
# time + 1.day will advance 23-25 hours, depending on the day.
|
271
289
|
#
|
272
|
-
# now + 24.hours # => Mon, 03 Nov 2014 00:26:28 EST -05:00
|
273
|
-
# now + 1.day # => Mon, 03 Nov 2014 01:26:28 EST -05:00
|
290
|
+
# now + 24.hours # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
|
291
|
+
# now + 1.day # => Mon, 03 Nov 2014 01:26:28.725182881 EST -05:00
|
274
292
|
def +(other)
|
275
293
|
if duration_of_variable_length?(other)
|
276
294
|
method_missing(:+, other)
|
@@ -280,13 +298,16 @@ module ActiveSupport
|
|
280
298
|
end
|
281
299
|
end
|
282
300
|
alias_method :since, :+
|
301
|
+
alias_method :in, :+
|
283
302
|
|
284
|
-
#
|
285
|
-
# the
|
303
|
+
# Subtracts an interval of time and returns a new TimeWithZone object unless
|
304
|
+
# the other value `acts_like?` time. Then it will return a Float of the difference
|
305
|
+
# between the two times that represents the difference between the current
|
306
|
+
# object's time and the +other+ time.
|
286
307
|
#
|
287
308
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
288
|
-
# now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
|
289
|
-
# now - 1000 # => Mon, 03 Nov 2014 00:09:48 EST -05:00
|
309
|
+
# now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
|
310
|
+
# now - 1000 # => Mon, 03 Nov 2014 00:09:48.725182881 EST -05:00
|
290
311
|
#
|
291
312
|
# If subtracting a Duration of variable length (i.e., years, months, days),
|
292
313
|
# move backward from #time, otherwise move backward from #utc, for accuracy
|
@@ -295,8 +316,14 @@ module ActiveSupport
|
|
295
316
|
# For instance, a time - 24.hours will go subtract exactly 24 hours, while a
|
296
317
|
# time - 1.day will subtract 23-25 hours, depending on the day.
|
297
318
|
#
|
298
|
-
# now - 24.hours # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
|
299
|
-
# now - 1.day # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
|
319
|
+
# now - 24.hours # => Sun, 02 Nov 2014 01:26:28.725182881 EDT -04:00
|
320
|
+
# now - 1.day # => Sun, 02 Nov 2014 00:26:28.725182881 EDT -04:00
|
321
|
+
#
|
322
|
+
# If both the TimeWithZone object and the other value act like Time, a Float
|
323
|
+
# will be returned.
|
324
|
+
#
|
325
|
+
# Time.zone.now - 1.day.ago # => 86399.999967
|
326
|
+
#
|
300
327
|
def -(other)
|
301
328
|
if other.acts_like?(:time)
|
302
329
|
to_time - other.to_time
|
@@ -312,8 +339,8 @@ module ActiveSupport
|
|
312
339
|
# the result as a new TimeWithZone object.
|
313
340
|
#
|
314
341
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
315
|
-
# now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00
|
316
|
-
# now.ago(1000) # => Mon, 03 Nov 2014 00:09:48 EST -05:00
|
342
|
+
# now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
|
343
|
+
# now.ago(1000) # => Mon, 03 Nov 2014 00:09:48.725182881 EST -05:00
|
317
344
|
#
|
318
345
|
# If we're subtracting a Duration of variable length (i.e., years, months,
|
319
346
|
# days), move backward from #time, otherwise move backward from #utc, for
|
@@ -323,12 +350,48 @@ module ActiveSupport
|
|
323
350
|
# while <tt>time.ago(1.day)</tt> will move back 23-25 hours, depending on
|
324
351
|
# the day.
|
325
352
|
#
|
326
|
-
# now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
|
327
|
-
# now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
|
353
|
+
# now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28.725182881 EDT -04:00
|
354
|
+
# now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28.725182881 EDT -04:00
|
328
355
|
def ago(other)
|
329
356
|
since(-other)
|
330
357
|
end
|
331
358
|
|
359
|
+
# Returns a new +ActiveSupport::TimeWithZone+ where one or more of the elements have
|
360
|
+
# been changed according to the +options+ parameter. The time options (<tt>:hour</tt>,
|
361
|
+
# <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly,
|
362
|
+
# so if only the hour is passed, then minute, sec, usec and nsec is set to 0. If the
|
363
|
+
# hour and minute is passed, then sec, usec and nsec is set to 0. The +options+
|
364
|
+
# parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
|
365
|
+
# <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>,
|
366
|
+
# <tt>:nsec</tt>, <tt>:offset</tt>, <tt>:zone</tt>. Pass either <tt>:usec</tt>
|
367
|
+
# or <tt>:nsec</tt>, not both. Similarly, pass either <tt>:zone</tt> or
|
368
|
+
# <tt>:offset</tt>, not both.
|
369
|
+
#
|
370
|
+
# t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15.116992711 EST -05:00
|
371
|
+
# t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15.116992711 EST -05:00
|
372
|
+
# t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00.116992711 EST -05:00
|
373
|
+
# t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00.116992711 EST -05:00
|
374
|
+
# t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
|
375
|
+
# t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
|
376
|
+
def change(options)
|
377
|
+
if options[:zone] && options[:offset]
|
378
|
+
raise ArgumentError, "Can't change both :offset and :zone at the same time: #{options.inspect}"
|
379
|
+
end
|
380
|
+
|
381
|
+
new_time = time.change(options)
|
382
|
+
|
383
|
+
if options[:zone]
|
384
|
+
new_zone = ::Time.find_zone(options[:zone])
|
385
|
+
elsif options[:offset]
|
386
|
+
new_zone = ::Time.find_zone(new_time.utc_offset)
|
387
|
+
end
|
388
|
+
|
389
|
+
new_zone ||= time_zone
|
390
|
+
periods = new_zone.periods_for_local(new_time)
|
391
|
+
|
392
|
+
self.class.new(nil, new_zone, new_time, periods.include?(period) ? period : nil)
|
393
|
+
end
|
394
|
+
|
332
395
|
# Uses Date to provide precise Time calculations for years, months, and days
|
333
396
|
# according to the proleptic Gregorian calendar. The result is returned as a
|
334
397
|
# new TimeWithZone object.
|
@@ -342,14 +405,14 @@ module ActiveSupport
|
|
342
405
|
# accuracy when moving across DST boundaries.
|
343
406
|
#
|
344
407
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
345
|
-
# now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00
|
346
|
-
# now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29 EDT -04:00
|
347
|
-
# now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28 EDT -04:00
|
348
|
-
# now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28 EST -05:00
|
349
|
-
# now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28 EST -05:00
|
350
|
-
# now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28 EST -05:00
|
351
|
-
# now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28 EST -05:00
|
352
|
-
# now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28 EST -05:00
|
408
|
+
# now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28.558049687 EDT -04:00
|
409
|
+
# now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29.558049687 EDT -04:00
|
410
|
+
# now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28.558049687 EDT -04:00
|
411
|
+
# now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28.558049687 EST -05:00
|
412
|
+
# now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28.558049687 EST -05:00
|
413
|
+
# now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28.558049687 EST -05:00
|
414
|
+
# now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28.558049687 EST -05:00
|
415
|
+
# now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28.558049687 EST -05:00
|
353
416
|
def advance(options)
|
354
417
|
# If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
|
355
418
|
# otherwise advance from #utc, for accuracy when moving across DST boundaries
|
@@ -371,7 +434,7 @@ module ActiveSupport
|
|
371
434
|
# Returns Array of parts of Time in sequence of
|
372
435
|
# [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].
|
373
436
|
#
|
374
|
-
# now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00
|
437
|
+
# now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27.485278555 UTC +00:00
|
375
438
|
# now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
|
376
439
|
def to_a
|
377
440
|
[time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
|
@@ -407,7 +470,18 @@ module ActiveSupport
|
|
407
470
|
# Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
|
408
471
|
# Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
|
409
472
|
def to_datetime
|
410
|
-
utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
|
473
|
+
@to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
|
474
|
+
end
|
475
|
+
|
476
|
+
# Returns an instance of +Time+, either with the same UTC offset
|
477
|
+
# as +self+ or in the local system timezone depending on the setting
|
478
|
+
# of +ActiveSupport.to_time_preserves_timezone+.
|
479
|
+
def to_time
|
480
|
+
if preserve_timezone
|
481
|
+
@to_time_with_instance_offset ||= getlocal(utc_offset)
|
482
|
+
else
|
483
|
+
@to_time_with_system_offset ||= getlocal
|
484
|
+
end
|
411
485
|
end
|
412
486
|
|
413
487
|
# So that +self+ <tt>acts_like?(:time)</tt>.
|
@@ -427,7 +501,8 @@ module ActiveSupport
|
|
427
501
|
end
|
428
502
|
|
429
503
|
def freeze
|
430
|
-
|
504
|
+
# preload instance variables before freezing
|
505
|
+
period; utc; time; to_datetime; to_time
|
431
506
|
super
|
432
507
|
end
|
433
508
|
|
@@ -459,10 +534,20 @@ module ActiveSupport
|
|
459
534
|
def method_missing(sym, *args, &block)
|
460
535
|
wrap_with_time_zone time.__send__(sym, *args, &block)
|
461
536
|
rescue NoMethodError => e
|
462
|
-
raise e, e.message.sub(time.inspect,
|
537
|
+
raise e, e.message.sub(time.inspect, inspect), e.backtrace
|
463
538
|
end
|
464
539
|
|
465
540
|
private
|
541
|
+
SECONDS_PER_DAY = 86400
|
542
|
+
|
543
|
+
def incorporate_utc_offset(time, offset)
|
544
|
+
if time.kind_of?(Date)
|
545
|
+
time + Rational(offset, SECONDS_PER_DAY)
|
546
|
+
else
|
547
|
+
time + offset
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
466
551
|
def get_period_and_ensure_valid_local_time(period)
|
467
552
|
# we don't want a Time.local instance enforcing its own DST rules as well,
|
468
553
|
# so transfer time values to a utc constructor if necessary
|
@@ -477,11 +562,13 @@ module ActiveSupport
|
|
477
562
|
end
|
478
563
|
|
479
564
|
def transfer_time_values_to_utc_constructor(time)
|
565
|
+
# avoid creating another Time object if possible
|
566
|
+
return time if time.instance_of?(::Time) && time.utc?
|
480
567
|
::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + time.subsec)
|
481
568
|
end
|
482
569
|
|
483
570
|
def duration_of_variable_length?(obj)
|
484
|
-
ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include?(p[0]) }
|
571
|
+
ActiveSupport::Duration === obj && obj.parts.any? { |p| [:years, :months, :weeks, :days].include?(p[0]) }
|
485
572
|
end
|
486
573
|
|
487
574
|
def wrap_with_time_zone(time)
|