activesupport 4.2.0 → 5.0.0.1
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 +630 -220
- 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.rb +73 -89
- data/lib/active_support/callbacks.rb +195 -155
- data/lib/active_support/concern.rb +2 -2
- data/lib/active_support/concurrency/latch.rb +7 -15
- data/lib/active_support/concurrency/share_lock.rb +186 -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 -4
- 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 +13 -6
- data/lib/active_support/core_ext/date.rb +1 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +109 -25
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
- 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 +36 -10
- data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_time.rb +2 -1
- data/lib/active_support/core_ext/enumerable.rb +49 -5
- data/lib/active_support/core_ext/file/atomic.rb +30 -25
- data/lib/active_support/core_ext/hash/conversions.rb +23 -4
- 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 +23 -19
- 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 +1 -16
- 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 -83
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +4 -2
- data/lib/active_support/core_ext/marshal.rb +12 -11
- 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 +35 -25
- data/lib/active_support/core_ext/module/deprecation.rb +2 -2
- data/lib/active_support/core_ext/module/introspection.rb +4 -0
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -11
- 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 +74 -64
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +24 -19
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/blank.rb +17 -5
- data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
- data/lib/active_support/core_ext/object/duplicable.rb +8 -13
- 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 +68 -22
- 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/access.rb +1 -1
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +4 -3
- data/lib/active_support/core_ext/string/filters.rb +5 -5
- 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 +18 -16
- 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 +36 -11
- data/lib/active_support/core_ext/time/compatibility.rb +5 -0
- 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 +1 -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 +51 -0
- data/lib/active_support/dependencies.rb +87 -95
- data/lib/active_support/deprecation/behaviors.rb +16 -2
- 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 +55 -10
- data/lib/active_support/evented_file_update_checker.rb +194 -0
- data/lib/active_support/execution_wrapper.rb +117 -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 +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +46 -13
- 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 +4 -49
- data/lib/active_support/key_generator.rb +7 -9
- 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 +50 -1
- data/lib/active_support/logger_silence.rb +8 -4
- data/lib/active_support/logger_thread_safe_level.rb +31 -0
- data/lib/active_support/message_encryptor.rb +4 -4
- data/lib/active_support/message_verifier.rb +70 -8
- data/lib/active_support/multibyte/chars.rb +13 -4
- data/lib/active_support/multibyte/unicode.rb +44 -21
- data/lib/active_support/notifications/fanout.rb +6 -6
- 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 +8 -3
- 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 +93 -47
- data/lib/active_support/security_utils.rb +7 -0
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +5 -10
- data/lib/active_support/tagged_logging.rb +3 -1
- data/lib/active_support/test_case.rb +15 -29
- data/lib/active_support/testing/assertions.rb +15 -13
- data/lib/active_support/testing/autorun.rb +8 -1
- 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 +13 -10
- data/lib/active_support/time_with_zone.rb +135 -46
- data/lib/active_support/values/time_zone.rb +95 -47
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/xml_mini/jdom.rb +7 -6
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +7 -8
- data/lib/active_support/xml_mini.rb +22 -14
- data/lib/active_support.rb +20 -6
- metadata +33 -35
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
- 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
@@ -39,15 +39,16 @@ module ActiveSupport
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
42
|
+
# Contains helpers that help you test passage of time.
|
43
43
|
module TimeHelpers
|
44
44
|
# Changes current time to the time in the future or in the past by a given time difference by
|
45
|
-
# stubbing +Time.now+ and +
|
45
|
+
# stubbing +Time.now+, +Date.today+, and +DateTime.now+.
|
46
46
|
#
|
47
|
-
# Time.current
|
47
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
48
48
|
# travel 1.day
|
49
|
-
# Time.current
|
50
|
-
# Date.current
|
49
|
+
# Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
|
50
|
+
# Date.current # => Sun, 10 Nov 2013
|
51
|
+
# DateTime.current # => Sun, 10 Nov 2013 15:34:49 -0500
|
51
52
|
#
|
52
53
|
# This method also accepts a block, which will return the current time back to its original
|
53
54
|
# state at the end of the block:
|
@@ -61,13 +62,14 @@ module ActiveSupport
|
|
61
62
|
travel_to Time.now + duration, &block
|
62
63
|
end
|
63
64
|
|
64
|
-
# Changes current time to the given time by stubbing +Time.now
|
65
|
-
# +Date.today+ to return the time or date passed into this method.
|
65
|
+
# Changes current time to the given time by stubbing +Time.now+,
|
66
|
+
# +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
|
66
67
|
#
|
67
|
-
# Time.current
|
68
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
68
69
|
# travel_to Time.new(2004, 11, 24, 01, 04, 44)
|
69
|
-
# Time.current
|
70
|
-
# Date.current
|
70
|
+
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
71
|
+
# Date.current # => Wed, 24 Nov 2004
|
72
|
+
# DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
|
71
73
|
#
|
72
74
|
# Dates are taken as their timestamp at the beginning of the day in the
|
73
75
|
# application time zone. <tt>Time.current</tt> returns said timestamp,
|
@@ -99,6 +101,7 @@ module ActiveSupport
|
|
99
101
|
|
100
102
|
simple_stubs.stub_object(Time, :now, now)
|
101
103
|
simple_stubs.stub_object(Date, :today, now.to_date)
|
104
|
+
simple_stubs.stub_object(DateTime, :now, now.to_datetime)
|
102
105
|
|
103
106
|
if block_given?
|
104
107
|
begin
|
@@ -1,5 +1,7 @@
|
|
1
|
+
require 'active_support/duration'
|
1
2
|
require 'active_support/values/time_zone'
|
2
3
|
require 'active_support/core_ext/object/acts_like'
|
4
|
+
require 'active_support/core_ext/date_and_time/compatibility'
|
3
5
|
|
4
6
|
module ActiveSupport
|
5
7
|
# A Time-like class that can represent a time in any time zone. Necessary
|
@@ -13,7 +15,7 @@ module ActiveSupport
|
|
13
15
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
14
16
|
# Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
15
17
|
# Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
16
|
-
# Time.zone.at(
|
18
|
+
# Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
17
19
|
# Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
|
18
20
|
# Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
|
19
21
|
#
|
@@ -40,20 +42,24 @@ module ActiveSupport
|
|
40
42
|
'Time'
|
41
43
|
end
|
42
44
|
|
43
|
-
|
45
|
+
PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N".freeze }
|
46
|
+
PRECISIONS[0] = '%FT%T'.freeze
|
47
|
+
|
48
|
+
include Comparable, DateAndTime::Compatibility
|
44
49
|
attr_reader :time_zone
|
45
50
|
|
46
51
|
def initialize(utc_time, time_zone, local_time = nil, period = nil)
|
47
|
-
@utc
|
52
|
+
@utc = utc_time ? transfer_time_values_to_utc_constructor(utc_time) : nil
|
53
|
+
@time_zone, @time = time_zone, local_time
|
48
54
|
@period = @utc ? period : get_period_and_ensure_valid_local_time(period)
|
49
55
|
end
|
50
56
|
|
51
|
-
# Returns a Time
|
57
|
+
# Returns a <tt>Time</tt> instance that represents the time in +time_zone+.
|
52
58
|
def time
|
53
59
|
@time ||= period.to_local(@utc)
|
54
60
|
end
|
55
61
|
|
56
|
-
# Returns a Time
|
62
|
+
# Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
|
57
63
|
def utc
|
58
64
|
@utc ||= period.to_utc(@time)
|
59
65
|
end
|
@@ -73,10 +79,9 @@ module ActiveSupport
|
|
73
79
|
utc.in_time_zone(new_zone)
|
74
80
|
end
|
75
81
|
|
76
|
-
# Returns a <tt>Time
|
77
|
-
# system's <tt>ENV['TZ']</tt> zone.
|
82
|
+
# Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
|
78
83
|
def localtime(utc_offset = nil)
|
79
|
-
utc.
|
84
|
+
utc.getlocal(utc_offset)
|
80
85
|
end
|
81
86
|
alias_method :getlocal, :localtime
|
82
87
|
|
@@ -98,7 +103,7 @@ module ActiveSupport
|
|
98
103
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
99
104
|
# Time.zone.now.utc? # => false
|
100
105
|
def utc?
|
101
|
-
|
106
|
+
period.offset.abbreviation == :UTC || period.offset.abbreviation == :UCT
|
102
107
|
end
|
103
108
|
alias_method :gmt?, :utc?
|
104
109
|
|
@@ -121,22 +126,27 @@ module ActiveSupport
|
|
121
126
|
utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
|
122
127
|
end
|
123
128
|
|
124
|
-
#
|
125
|
-
#
|
129
|
+
# Returns the time zone abbreviation.
|
130
|
+
#
|
131
|
+
# Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
|
132
|
+
# Time.zone.now.zone # => "EST"
|
126
133
|
def zone
|
127
134
|
period.zone_identifier.to_s
|
128
135
|
end
|
129
136
|
|
137
|
+
# Returns a string of the object's date, time, zone and offset from UTC.
|
138
|
+
#
|
139
|
+
# Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
|
130
140
|
def inspect
|
131
141
|
"#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
|
132
142
|
end
|
133
143
|
|
144
|
+
# Returns a string of the object's date and time in the ISO 8601 standard
|
145
|
+
# format.
|
146
|
+
#
|
147
|
+
# Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00"
|
134
148
|
def xmlschema(fraction_digits = 0)
|
135
|
-
|
136
|
-
(".%06i" % time.usec)[0, fraction_digits.to_i + 1]
|
137
|
-
end
|
138
|
-
|
139
|
-
"#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}#{formatted_offset(true, 'Z')}"
|
149
|
+
"#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'.freeze)}"
|
140
150
|
end
|
141
151
|
alias_method :iso8601, :xmlschema
|
142
152
|
|
@@ -160,12 +170,13 @@ module ActiveSupport
|
|
160
170
|
end
|
161
171
|
end
|
162
172
|
|
163
|
-
def
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
173
|
+
def init_with(coder) #:nodoc:
|
174
|
+
initialize(coder['utc'], coder['zone'], coder['time'])
|
175
|
+
end
|
176
|
+
|
177
|
+
def encode_with(coder) #:nodoc:
|
178
|
+
coder.tag = '!ruby/object:ActiveSupport::TimeWithZone'
|
179
|
+
coder.map = { 'utc' => utc, 'zone' => time_zone, 'time' => time }
|
169
180
|
end
|
170
181
|
|
171
182
|
# Returns a string of the object's date and time in the format used by
|
@@ -187,7 +198,7 @@ module ActiveSupport
|
|
187
198
|
|
188
199
|
# Returns a string of the object's date and time.
|
189
200
|
# Accepts an optional <tt>format</tt>:
|
190
|
-
# * <tt>:default</tt> - default value, mimics Ruby
|
201
|
+
# * <tt>:default</tt> - default value, mimics Ruby Time#to_s format.
|
191
202
|
# * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_formatted_s(:db).
|
192
203
|
# * Any key in <tt>Time::DATE_FORMATS</tt> can be used. See active_support/core_ext/time/conversions.rb.
|
193
204
|
def to_s(format = :default)
|
@@ -196,7 +207,7 @@ module ActiveSupport
|
|
196
207
|
elsif formatter = ::Time::DATE_FORMATS[format]
|
197
208
|
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
198
209
|
else
|
199
|
-
"#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby
|
210
|
+
"#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
|
200
211
|
end
|
201
212
|
end
|
202
213
|
alias_method :to_formatted_s, :to_s
|
@@ -235,17 +246,32 @@ module ActiveSupport
|
|
235
246
|
utc.future?
|
236
247
|
end
|
237
248
|
|
249
|
+
# Returns +true+ if +other+ is equal to current object.
|
238
250
|
def eql?(other)
|
239
|
-
|
251
|
+
other.eql?(utc)
|
240
252
|
end
|
241
253
|
|
242
254
|
def hash
|
243
255
|
utc.hash
|
244
256
|
end
|
245
257
|
|
258
|
+
# Adds an interval of time to the current object's time and returns that
|
259
|
+
# value as a new TimeWithZone object.
|
260
|
+
#
|
261
|
+
# 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
|
264
|
+
#
|
265
|
+
# If we're adding a Duration of variable length (i.e., years, months, days),
|
266
|
+
# move forward from #time, otherwise move forward from #utc, for accuracy
|
267
|
+
# when moving across DST boundaries.
|
268
|
+
#
|
269
|
+
# For instance, a time + 24.hours will advance exactly 24 hours, while a
|
270
|
+
# time + 1.day will advance 23-25 hours, depending on the day.
|
271
|
+
#
|
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
|
246
274
|
def +(other)
|
247
|
-
# If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
|
248
|
-
# otherwise move forward from #utc, for accuracy when moving across DST boundaries
|
249
275
|
if duration_of_variable_length?(other)
|
250
276
|
method_missing(:+, other)
|
251
277
|
else
|
@@ -253,10 +279,25 @@ module ActiveSupport
|
|
253
279
|
result.in_time_zone(time_zone)
|
254
280
|
end
|
255
281
|
end
|
282
|
+
alias_method :since, :+
|
256
283
|
|
284
|
+
# Returns a new TimeWithZone object that represents the difference between
|
285
|
+
# the current object's time and the +other+ time.
|
286
|
+
#
|
287
|
+
# 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
|
290
|
+
#
|
291
|
+
# If subtracting a Duration of variable length (i.e., years, months, days),
|
292
|
+
# move backward from #time, otherwise move backward from #utc, for accuracy
|
293
|
+
# when moving across DST boundaries.
|
294
|
+
#
|
295
|
+
# For instance, a time - 24.hours will go subtract exactly 24 hours, while a
|
296
|
+
# time - 1.day will subtract 23-25 hours, depending on the day.
|
297
|
+
#
|
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
|
257
300
|
def -(other)
|
258
|
-
# If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time,
|
259
|
-
# otherwise move backwards #utc, for accuracy when moving across DST boundaries
|
260
301
|
if other.acts_like?(:time)
|
261
302
|
to_time - other.to_time
|
262
303
|
elsif duration_of_variable_length?(other)
|
@@ -267,20 +308,48 @@ module ActiveSupport
|
|
267
308
|
end
|
268
309
|
end
|
269
310
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
311
|
+
# Subtracts an interval of time from the current object's time and returns
|
312
|
+
# the result as a new TimeWithZone object.
|
313
|
+
#
|
314
|
+
# 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
|
317
|
+
#
|
318
|
+
# If we're subtracting a Duration of variable length (i.e., years, months,
|
319
|
+
# days), move backward from #time, otherwise move backward from #utc, for
|
320
|
+
# accuracy when moving across DST boundaries.
|
321
|
+
#
|
322
|
+
# For instance, <tt>time.ago(24.hours)</tt> will move back exactly 24 hours,
|
323
|
+
# while <tt>time.ago(1.day)</tt> will move back 23-25 hours, depending on
|
324
|
+
# the day.
|
325
|
+
#
|
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
|
280
328
|
def ago(other)
|
281
329
|
since(-other)
|
282
330
|
end
|
283
331
|
|
332
|
+
# Uses Date to provide precise Time calculations for years, months, and days
|
333
|
+
# according to the proleptic Gregorian calendar. The result is returned as a
|
334
|
+
# new TimeWithZone object.
|
335
|
+
#
|
336
|
+
# The +options+ parameter takes a hash with any of these keys:
|
337
|
+
# <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>,
|
338
|
+
# <tt>:hours</tt>, <tt>:minutes</tt>, <tt>:seconds</tt>.
|
339
|
+
#
|
340
|
+
# If advancing by a value of variable length (i.e., years, weeks, months,
|
341
|
+
# days), move forward from #time, otherwise move forward from #utc, for
|
342
|
+
# accuracy when moving across DST boundaries.
|
343
|
+
#
|
344
|
+
# 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
|
284
353
|
def advance(options)
|
285
354
|
# If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
|
286
355
|
# otherwise advance from #utc, for accuracy when moving across DST boundaries
|
@@ -299,28 +368,44 @@ module ActiveSupport
|
|
299
368
|
EOV
|
300
369
|
end
|
301
370
|
|
371
|
+
# Returns Array of parts of Time in sequence of
|
372
|
+
# [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].
|
373
|
+
#
|
374
|
+
# now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00
|
375
|
+
# now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
|
302
376
|
def to_a
|
303
377
|
[time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
|
304
378
|
end
|
305
379
|
|
380
|
+
# Returns the object's date and time as a floating point number of seconds
|
381
|
+
# since the Epoch (January 1, 1970 00:00 UTC).
|
382
|
+
#
|
383
|
+
# Time.zone.now.to_f # => 1417709320.285418
|
306
384
|
def to_f
|
307
385
|
utc.to_f
|
308
386
|
end
|
309
387
|
|
388
|
+
# Returns the object's date and time as an integer number of seconds
|
389
|
+
# since the Epoch (January 1, 1970 00:00 UTC).
|
390
|
+
#
|
391
|
+
# Time.zone.now.to_i # => 1417709320
|
310
392
|
def to_i
|
311
393
|
utc.to_i
|
312
394
|
end
|
313
395
|
alias_method :tv_sec, :to_i
|
314
396
|
|
397
|
+
# Returns the object's date and time as a rational number of seconds
|
398
|
+
# since the Epoch (January 1, 1970 00:00 UTC).
|
399
|
+
#
|
400
|
+
# Time.zone.now.to_r # => (708854548642709/500000)
|
315
401
|
def to_r
|
316
402
|
utc.to_r
|
317
403
|
end
|
318
404
|
|
319
|
-
#
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
405
|
+
# Returns an instance of DateTime with the timezone's UTC offset
|
406
|
+
#
|
407
|
+
# Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
|
408
|
+
# Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
|
324
409
|
def to_datetime
|
325
410
|
utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
|
326
411
|
end
|
@@ -336,6 +421,11 @@ module ActiveSupport
|
|
336
421
|
end
|
337
422
|
alias_method :kind_of?, :is_a?
|
338
423
|
|
424
|
+
# An instance of ActiveSupport::TimeWithZone is never blank
|
425
|
+
def blank?
|
426
|
+
false
|
427
|
+
end
|
428
|
+
|
339
429
|
def freeze
|
340
430
|
period; utc; time # preload instance variables before freezing
|
341
431
|
super
|
@@ -360,7 +450,6 @@ module ActiveSupport
|
|
360
450
|
# Ensure proxy class responds to all methods that underlying time instance
|
361
451
|
# responds to.
|
362
452
|
def respond_to_missing?(sym, include_priv)
|
363
|
-
# consistently respond false to acts_like?(:date), regardless of whether #time is a Time or DateTime
|
364
453
|
return false if sym.to_sym == :acts_like_date?
|
365
454
|
time.respond_to?(sym, include_priv)
|
366
455
|
end
|
@@ -388,7 +477,7 @@ module ActiveSupport
|
|
388
477
|
end
|
389
478
|
|
390
479
|
def transfer_time_values_to_utc_constructor(time)
|
391
|
-
::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec
|
480
|
+
::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + time.subsec)
|
392
481
|
end
|
393
482
|
|
394
483
|
def duration_of_variable_length?(obj)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'tzinfo'
|
2
|
-
require '
|
2
|
+
require 'concurrent/map'
|
3
3
|
require 'active_support/core_ext/object/blank'
|
4
|
-
require 'active_support/core_ext/object/try'
|
5
4
|
|
6
5
|
module ActiveSupport
|
7
6
|
# The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
|
@@ -23,15 +22,9 @@ module ActiveSupport
|
|
23
22
|
# config.time_zone = 'Eastern Time (US & Canada)'
|
24
23
|
# end
|
25
24
|
#
|
26
|
-
# Time.zone # => #<TimeZone:0x514834...>
|
25
|
+
# Time.zone # => #<ActiveSupport::TimeZone:0x514834...>
|
27
26
|
# Time.zone.name # => "Eastern Time (US & Canada)"
|
28
27
|
# Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00
|
29
|
-
#
|
30
|
-
# The version of TZInfo bundled with Active Support only includes the
|
31
|
-
# definitions necessary to support the zones defined by the TimeZone class.
|
32
|
-
# If you need to use zones that aren't defined by TimeZone, you'll need to
|
33
|
-
# install the TZInfo gem (if a recent version of the gem is installed locally,
|
34
|
-
# this will be used instead of the bundled version.)
|
35
28
|
class TimeZone
|
36
29
|
# Keys are Rails TimeZone names, values are TZInfo identifiers.
|
37
30
|
MAPPING = {
|
@@ -92,7 +85,8 @@ module ActiveSupport
|
|
92
85
|
"Paris" => "Europe/Paris",
|
93
86
|
"Amsterdam" => "Europe/Amsterdam",
|
94
87
|
"Berlin" => "Europe/Berlin",
|
95
|
-
"Bern" => "Europe/
|
88
|
+
"Bern" => "Europe/Zurich",
|
89
|
+
"Zurich" => "Europe/Zurich",
|
96
90
|
"Rome" => "Europe/Rome",
|
97
91
|
"Stockholm" => "Europe/Stockholm",
|
98
92
|
"Vienna" => "Europe/Vienna",
|
@@ -111,9 +105,11 @@ module ActiveSupport
|
|
111
105
|
"Jerusalem" => "Asia/Jerusalem",
|
112
106
|
"Harare" => "Africa/Harare",
|
113
107
|
"Pretoria" => "Africa/Johannesburg",
|
108
|
+
"Kaliningrad" => "Europe/Kaliningrad",
|
114
109
|
"Moscow" => "Europe/Moscow",
|
115
110
|
"St. Petersburg" => "Europe/Moscow",
|
116
|
-
"Volgograd" => "Europe/
|
111
|
+
"Volgograd" => "Europe/Volgograd",
|
112
|
+
"Samara" => "Europe/Samara",
|
117
113
|
"Kuwait" => "Asia/Kuwait",
|
118
114
|
"Riyadh" => "Asia/Riyadh",
|
119
115
|
"Nairobi" => "Africa/Nairobi",
|
@@ -170,6 +166,7 @@ module ActiveSupport
|
|
170
166
|
"Guam" => "Pacific/Guam",
|
171
167
|
"Port Moresby" => "Pacific/Port_Moresby",
|
172
168
|
"Magadan" => "Asia/Magadan",
|
169
|
+
"Srednekolymsk" => "Asia/Srednekolymsk",
|
173
170
|
"Solomon Is." => "Pacific/Guadalcanal",
|
174
171
|
"New Caledonia" => "Pacific/Noumea",
|
175
172
|
"Fiji" => "Pacific/Fiji",
|
@@ -186,13 +183,14 @@ module ActiveSupport
|
|
186
183
|
UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
|
187
184
|
UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(':', '')
|
188
185
|
|
189
|
-
@lazy_zones_map =
|
186
|
+
@lazy_zones_map = Concurrent::Map.new
|
187
|
+
@country_zones = Concurrent::Map.new
|
190
188
|
|
191
189
|
class << self
|
192
190
|
# Assumes self represents an offset from UTC in seconds (as returned from
|
193
191
|
# Time#utc_offset) and turns this into an +HH:MM formatted string.
|
194
192
|
#
|
195
|
-
# TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
|
193
|
+
# ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
|
196
194
|
def seconds_to_utc_offset(seconds, colon = true)
|
197
195
|
format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
|
198
196
|
sign = (seconds < 0 ? '-' : '+')
|
@@ -202,7 +200,7 @@ module ActiveSupport
|
|
202
200
|
end
|
203
201
|
|
204
202
|
def find_tzinfo(name)
|
205
|
-
TZInfo::
|
203
|
+
TZInfo::Timezone.new(MAPPING[name] || name)
|
206
204
|
end
|
207
205
|
|
208
206
|
alias_method :create, :new
|
@@ -221,13 +219,6 @@ module ActiveSupport
|
|
221
219
|
@zones ||= zones_map.values.sort
|
222
220
|
end
|
223
221
|
|
224
|
-
def zones_map
|
225
|
-
@zones_map ||= begin
|
226
|
-
MAPPING.each_key {|place| self[place]} # load all the zones
|
227
|
-
@lazy_zones_map
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
222
|
# Locate a specific time zone object. If the argument is a string, it
|
232
223
|
# is interpreted to mean the name of the timezone to locate. If it is a
|
233
224
|
# numeric value it is either the hour offset, or the second offset, of the
|
@@ -237,7 +228,7 @@ module ActiveSupport
|
|
237
228
|
case arg
|
238
229
|
when String
|
239
230
|
begin
|
240
|
-
@lazy_zones_map[arg] ||= create(arg)
|
231
|
+
@lazy_zones_map[arg] ||= create(arg)
|
241
232
|
rescue TZInfo::InvalidTimezoneIdentifier
|
242
233
|
nil
|
243
234
|
end
|
@@ -252,8 +243,27 @@ module ActiveSupport
|
|
252
243
|
# A convenience method for returning a collection of TimeZone objects
|
253
244
|
# for time zones in the USA.
|
254
245
|
def us_zones
|
255
|
-
|
246
|
+
country_zones(:us)
|
256
247
|
end
|
248
|
+
|
249
|
+
# A convenience method for returning a collection of TimeZone objects
|
250
|
+
# for time zones in the country specified by its ISO 3166-1 Alpha2 code.
|
251
|
+
def country_zones(country_code)
|
252
|
+
code = country_code.to_s.upcase
|
253
|
+
@country_zones[code] ||=
|
254
|
+
TZInfo::Country.get(code).zone_identifiers.map do |tz_id|
|
255
|
+
name = MAPPING.key(tz_id)
|
256
|
+
name && self[name]
|
257
|
+
end.compact.sort!
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
def zones_map
|
262
|
+
@zones_map ||= begin
|
263
|
+
MAPPING.each_key {|place| self[place]} # load all the zones
|
264
|
+
@lazy_zones_map
|
265
|
+
end
|
266
|
+
end
|
257
267
|
end
|
258
268
|
|
259
269
|
include Comparable
|
@@ -268,7 +278,6 @@ module ActiveSupport
|
|
268
278
|
@name = name
|
269
279
|
@utc_offset = utc_offset
|
270
280
|
@tzinfo = tzinfo || TimeZone.find_tzinfo(name)
|
271
|
-
@current_period = nil
|
272
281
|
end
|
273
282
|
|
274
283
|
# Returns the offset of this time zone from UTC in seconds.
|
@@ -276,13 +285,16 @@ module ActiveSupport
|
|
276
285
|
if @utc_offset
|
277
286
|
@utc_offset
|
278
287
|
else
|
279
|
-
|
280
|
-
@current_period.utc_offset if @current_period
|
288
|
+
tzinfo.current_period.utc_offset if tzinfo && tzinfo.current_period
|
281
289
|
end
|
282
290
|
end
|
283
291
|
|
284
|
-
# Returns
|
285
|
-
#
|
292
|
+
# Returns a formatted string of the offset from UTC, or an alternative
|
293
|
+
# string if the time zone is already UTC.
|
294
|
+
#
|
295
|
+
# zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
|
296
|
+
# zone.formatted_offset # => "-06:00"
|
297
|
+
# zone.formatted_offset(false) # => "-0600"
|
286
298
|
def formatted_offset(colon=true, alternate_utc_string = nil)
|
287
299
|
utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
|
288
300
|
end
|
@@ -344,24 +356,31 @@ module ActiveSupport
|
|
344
356
|
#
|
345
357
|
# Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
|
346
358
|
def parse(str, now=now())
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
359
|
+
parts_to_time(Date._parse(str, false), now)
|
360
|
+
end
|
361
|
+
|
362
|
+
# Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
|
363
|
+
#
|
364
|
+
# Assumes that +str+ is a time in the time zone +self+,
|
365
|
+
# unless +format+ includes an explicit time zone.
|
366
|
+
# (This is the same behavior as +parse+.)
|
367
|
+
# In either case, the returned TimeWithZone has the timezone of +self+.
|
368
|
+
#
|
369
|
+
# Time.zone = 'Hawaii' # => "Hawaii"
|
370
|
+
# Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
371
|
+
#
|
372
|
+
# If upper components are missing from the string, they are supplied from
|
373
|
+
# TimeZone#now:
|
374
|
+
#
|
375
|
+
# Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
376
|
+
# Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
|
377
|
+
#
|
378
|
+
# However, if the date component is not provided, but any other upper
|
379
|
+
# components are supplied, then the day of the month defaults to 1:
|
380
|
+
#
|
381
|
+
# Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
|
382
|
+
def strptime(str, format, now=now())
|
383
|
+
parts_to_time(DateTime._strptime(str, format), now)
|
365
384
|
end
|
366
385
|
|
367
386
|
# Returns an ActiveSupport::TimeWithZone instance representing the current
|
@@ -373,7 +392,7 @@ module ActiveSupport
|
|
373
392
|
time_now.utc.in_time_zone(self)
|
374
393
|
end
|
375
394
|
|
376
|
-
#
|
395
|
+
# Returns the current date in this time zone.
|
377
396
|
def today
|
378
397
|
tzinfo.now.to_date
|
379
398
|
end
|
@@ -417,7 +436,36 @@ module ActiveSupport
|
|
417
436
|
tzinfo.periods_for_local(time)
|
418
437
|
end
|
419
438
|
|
439
|
+
def init_with(coder) #:nodoc:
|
440
|
+
initialize(coder['name'])
|
441
|
+
end
|
442
|
+
|
443
|
+
def encode_with(coder) #:nodoc:
|
444
|
+
coder.tag ="!ruby/object:#{self.class}"
|
445
|
+
coder.map = { 'name' => tzinfo.name }
|
446
|
+
end
|
447
|
+
|
420
448
|
private
|
449
|
+
def parts_to_time(parts, now)
|
450
|
+
return if parts.empty?
|
451
|
+
|
452
|
+
time = Time.new(
|
453
|
+
parts.fetch(:year, now.year),
|
454
|
+
parts.fetch(:mon, now.month),
|
455
|
+
parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
|
456
|
+
parts.fetch(:hour, 0),
|
457
|
+
parts.fetch(:min, 0),
|
458
|
+
parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
|
459
|
+
parts.fetch(:offset, 0)
|
460
|
+
)
|
461
|
+
|
462
|
+
if parts[:offset]
|
463
|
+
TimeWithZone.new(time.utc, self)
|
464
|
+
else
|
465
|
+
TimeWithZone.new(nil, self, time)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
421
469
|
def time_now
|
422
470
|
Time.now
|
423
471
|
end
|
Binary file
|