activesupport 4.2.11.1 → 5.2.4
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 +399 -440
- data/MIT-LICENSE +2 -2
- data/README.rdoc +4 -5
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +7 -5
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +41 -35
- data/lib/active_support/cache/mem_cache_store.rb +97 -88
- data/lib/active_support/cache/memory_store.rb +27 -30
- data/lib/active_support/cache/null_store.rb +7 -8
- data/lib/active_support/cache/redis_cache_store.rb +461 -0
- data/lib/active_support/cache/strategy/local_cache.rb +67 -34
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +287 -196
- data/lib/active_support/callbacks.rb +640 -590
- data/lib/active_support/concern.rb +11 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
- data/lib/active_support/concurrency/share_lock.rb +227 -0
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/core_ext/array/access.rb +29 -1
- data/lib/active_support/core_ext/array/conversions.rb +22 -18
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +41 -22
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -6
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +11 -9
- data/lib/active_support/core_ext/date/conversions.rb +25 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +36 -18
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
- 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 +101 -33
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/compact.rb +14 -9
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/except.rb +11 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +33 -27
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -8
- data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
- data/lib/active_support/core_ext/hash.rb +11 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- 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/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +6 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +8 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +99 -29
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +9 -9
- data/lib/active_support/core_ext/module/reachable.rb +5 -2
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +14 -11
- data/lib/active_support/core_ext/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +78 -81
- data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -2
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +41 -14
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +49 -19
- 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 +69 -21
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +61 -0
- data/lib/active_support/core_ext/range/conversions.rb +27 -7
- data/lib/active_support/core_ext/range/each.rb +19 -17
- data/lib/active_support/core_ext/range/include_range.rb +2 -22
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -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 +6 -0
- data/lib/active_support/core_ext/securerandom.rb +25 -0
- data/lib/active_support/core_ext/string/access.rb +8 -6
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +7 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +6 -5
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +61 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +15 -7
- data/lib/active_support/core_ext/string/output_safety.rb +34 -38
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +4 -5
- 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/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +85 -51
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +20 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +6 -8
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies.rb +152 -161
- data/lib/active_support/deprecation/behaviors.rb +44 -11
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +66 -20
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- data/lib/active_support/duration.rb +307 -35
- data/lib/active_support/encrypted_configuration.rb +49 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +205 -0
- data/lib/active_support/execution_wrapper.rb +128 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +63 -37
- data/lib/active_support/gem_version.rb +6 -4
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +123 -28
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +37 -13
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +61 -12
- data/lib/active_support/inflector/methods.rb +163 -136
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +16 -13
- data/lib/active_support/json/encoding.rb +11 -58
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +25 -25
- data/lib/active_support/lazy_load_hooks.rb +50 -20
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +13 -10
- data/lib/active_support/logger.rb +8 -7
- data/lib/active_support/logger_silence.rb +6 -4
- data/lib/active_support/logger_thread_safe_level.rb +7 -5
- data/lib/active_support/message_encryptor.rb +168 -53
- data/lib/active_support/message_verifier.rb +150 -17
- data/lib/active_support/messages/metadata.rb +71 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte/chars.rb +36 -23
- data/lib/active_support/multibyte/unicode.rb +100 -96
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +11 -9
- data/lib/active_support/notifications/instrumenter.rb +27 -7
- data/lib/active_support/notifications.rb +11 -7
- data/lib/active_support/number_helper/number_converter.rb +13 -11
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +94 -68
- data/lib/active_support/option_merger.rb +3 -1
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +23 -5
- data/lib/active_support/per_thread_registry.rb +9 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +16 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +131 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +21 -16
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +19 -47
- data/lib/active_support/testing/assertions.rb +137 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- 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 +14 -10
- data/lib/active_support/testing/file_fixtures.rb +36 -0
- data/lib/active_support/testing/isolation.rb +34 -25
- data/lib/active_support/testing/method_call_assertions.rb +43 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +44 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +81 -15
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +169 -39
- data/lib/active_support/values/time_zone.rb +196 -61
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -114
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +11 -9
- data/lib/active_support/xml_mini.rb +37 -37
- data/lib/active_support.rb +12 -11
- metadata +54 -24
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,13 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tzinfo"
|
4
|
+
require "concurrent/map"
|
5
|
+
require "active_support/core_ext/object/blank"
|
5
6
|
|
6
7
|
module ActiveSupport
|
7
8
|
# The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
|
8
9
|
# It allows us to do the following:
|
9
10
|
#
|
10
|
-
# * Limit the set of zones provided by TZInfo to a meaningful subset of
|
11
|
+
# * Limit the set of zones provided by TZInfo to a meaningful subset of 134
|
11
12
|
# zones.
|
12
13
|
# * Retrieve and display zones with a friendlier name
|
13
14
|
# (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
|
@@ -23,19 +24,13 @@ module ActiveSupport
|
|
23
24
|
# config.time_zone = 'Eastern Time (US & Canada)'
|
24
25
|
# end
|
25
26
|
#
|
26
|
-
# Time.zone # => #<TimeZone:0x514834...>
|
27
|
+
# Time.zone # => #<ActiveSupport::TimeZone:0x514834...>
|
27
28
|
# Time.zone.name # => "Eastern Time (US & Canada)"
|
28
29
|
# 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
30
|
class TimeZone
|
36
31
|
# Keys are Rails TimeZone names, values are TZInfo identifiers.
|
37
32
|
MAPPING = {
|
38
|
-
"International Date Line West" => "
|
33
|
+
"International Date Line West" => "Etc/GMT+12",
|
39
34
|
"Midway Island" => "Pacific/Midway",
|
40
35
|
"American Samoa" => "Pacific/Pago_Pago",
|
41
36
|
"Hawaii" => "Pacific/Honolulu",
|
@@ -66,6 +61,7 @@ module ActiveSupport
|
|
66
61
|
"Buenos Aires" => "America/Argentina/Buenos_Aires",
|
67
62
|
"Montevideo" => "America/Montevideo",
|
68
63
|
"Georgetown" => "America/Guyana",
|
64
|
+
"Puerto Rico" => "America/Puerto_Rico",
|
69
65
|
"Greenland" => "America/Godthab",
|
70
66
|
"Mid-Atlantic" => "Atlantic/South_Georgia",
|
71
67
|
"Azores" => "Atlantic/Azores",
|
@@ -92,7 +88,8 @@ module ActiveSupport
|
|
92
88
|
"Paris" => "Europe/Paris",
|
93
89
|
"Amsterdam" => "Europe/Amsterdam",
|
94
90
|
"Berlin" => "Europe/Berlin",
|
95
|
-
"Bern" => "Europe/
|
91
|
+
"Bern" => "Europe/Zurich",
|
92
|
+
"Zurich" => "Europe/Zurich",
|
96
93
|
"Rome" => "Europe/Rome",
|
97
94
|
"Stockholm" => "Europe/Stockholm",
|
98
95
|
"Vienna" => "Europe/Vienna",
|
@@ -186,26 +183,27 @@ module ActiveSupport
|
|
186
183
|
"Samoa" => "Pacific/Apia"
|
187
184
|
}
|
188
185
|
|
189
|
-
UTC_OFFSET_WITH_COLON =
|
190
|
-
UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(
|
186
|
+
UTC_OFFSET_WITH_COLON = "%s%02d:%02d"
|
187
|
+
UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.tr(":", "")
|
191
188
|
|
192
|
-
@lazy_zones_map =
|
189
|
+
@lazy_zones_map = Concurrent::Map.new
|
190
|
+
@country_zones = Concurrent::Map.new
|
193
191
|
|
194
192
|
class << self
|
195
193
|
# Assumes self represents an offset from UTC in seconds (as returned from
|
196
194
|
# Time#utc_offset) and turns this into an +HH:MM formatted string.
|
197
195
|
#
|
198
|
-
# TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
|
196
|
+
# ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
|
199
197
|
def seconds_to_utc_offset(seconds, colon = true)
|
200
198
|
format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
|
201
|
-
sign = (seconds < 0 ?
|
199
|
+
sign = (seconds < 0 ? "-" : "+")
|
202
200
|
hours = seconds.abs / 3600
|
203
201
|
minutes = (seconds.abs % 3600) / 60
|
204
202
|
format % [sign, hours, minutes]
|
205
203
|
end
|
206
204
|
|
207
205
|
def find_tzinfo(name)
|
208
|
-
TZInfo::
|
206
|
+
TZInfo::Timezone.new(MAPPING[name] || name)
|
209
207
|
end
|
210
208
|
|
211
209
|
alias_method :create, :new
|
@@ -224,13 +222,6 @@ module ActiveSupport
|
|
224
222
|
@zones ||= zones_map.values.sort
|
225
223
|
end
|
226
224
|
|
227
|
-
def zones_map #:nodoc:
|
228
|
-
@zones_map ||= begin
|
229
|
-
MAPPING.each_key {|place| self[place]} # load all the zones
|
230
|
-
@lazy_zones_map
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
225
|
# Locate a specific time zone object. If the argument is a string, it
|
235
226
|
# is interpreted to mean the name of the timezone to locate. If it is a
|
236
227
|
# numeric value it is either the hour offset, or the second offset, of the
|
@@ -238,25 +229,61 @@ module ActiveSupport
|
|
238
229
|
# Returns +nil+ if no such time zone is known to the system.
|
239
230
|
def [](arg)
|
240
231
|
case arg
|
241
|
-
|
232
|
+
when String
|
242
233
|
begin
|
243
|
-
@lazy_zones_map[arg] ||= create(arg)
|
234
|
+
@lazy_zones_map[arg] ||= create(arg)
|
244
235
|
rescue TZInfo::InvalidTimezoneIdentifier
|
245
236
|
nil
|
246
237
|
end
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
238
|
+
when Numeric, ActiveSupport::Duration
|
239
|
+
arg *= 3600 if arg.abs <= 13
|
240
|
+
all.find { |z| z.utc_offset == arg.to_i }
|
241
|
+
else
|
242
|
+
raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
|
252
243
|
end
|
253
244
|
end
|
254
245
|
|
255
246
|
# A convenience method for returning a collection of TimeZone objects
|
256
247
|
# for time zones in the USA.
|
257
248
|
def us_zones
|
258
|
-
|
249
|
+
country_zones(:us)
|
250
|
+
end
|
251
|
+
|
252
|
+
# A convenience method for returning a collection of TimeZone objects
|
253
|
+
# for time zones in the country specified by its ISO 3166-1 Alpha2 code.
|
254
|
+
def country_zones(country_code)
|
255
|
+
code = country_code.to_s.upcase
|
256
|
+
@country_zones[code] ||= load_country_zones(code)
|
257
|
+
end
|
258
|
+
|
259
|
+
def clear #:nodoc:
|
260
|
+
@lazy_zones_map = Concurrent::Map.new
|
261
|
+
@country_zones = Concurrent::Map.new
|
262
|
+
@zones = nil
|
263
|
+
@zones_map = nil
|
259
264
|
end
|
265
|
+
|
266
|
+
private
|
267
|
+
def load_country_zones(code)
|
268
|
+
country = TZInfo::Country.get(code)
|
269
|
+
country.zone_identifiers.map do |tz_id|
|
270
|
+
if MAPPING.value?(tz_id)
|
271
|
+
MAPPING.inject([]) do |memo, (key, value)|
|
272
|
+
memo << self[key] if value == tz_id
|
273
|
+
memo
|
274
|
+
end
|
275
|
+
else
|
276
|
+
create(tz_id, nil, TZInfo::Timezone.new(tz_id))
|
277
|
+
end
|
278
|
+
end.flatten(1).sort!
|
279
|
+
end
|
280
|
+
|
281
|
+
def zones_map
|
282
|
+
@zones_map ||= MAPPING.each_with_object({}) do |(name, _), zones|
|
283
|
+
timezone = self[name]
|
284
|
+
zones[name] = timezone if timezone
|
285
|
+
end
|
286
|
+
end
|
260
287
|
end
|
261
288
|
|
262
289
|
include Comparable
|
@@ -273,10 +300,6 @@ module ActiveSupport
|
|
273
300
|
@tzinfo = tzinfo || TimeZone.find_tzinfo(name)
|
274
301
|
end
|
275
302
|
|
276
|
-
def init_with(coder) #:nodoc:
|
277
|
-
initialize(coder['name'])
|
278
|
-
end
|
279
|
-
|
280
303
|
# Returns the offset of this time zone from UTC in seconds.
|
281
304
|
def utc_offset
|
282
305
|
if @utc_offset
|
@@ -286,9 +309,13 @@ module ActiveSupport
|
|
286
309
|
end
|
287
310
|
end
|
288
311
|
|
289
|
-
# Returns
|
290
|
-
#
|
291
|
-
|
312
|
+
# Returns a formatted string of the offset from UTC, or an alternative
|
313
|
+
# string if the time zone is already UTC.
|
314
|
+
#
|
315
|
+
# zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
|
316
|
+
# zone.formatted_offset # => "-06:00"
|
317
|
+
# zone.formatted_offset(false) # => "-0600"
|
318
|
+
def formatted_offset(colon = true, alternate_utc_string = nil)
|
292
319
|
utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
|
293
320
|
end
|
294
321
|
|
@@ -332,6 +359,41 @@ module ActiveSupport
|
|
332
359
|
Time.at(secs).utc.in_time_zone(self)
|
333
360
|
end
|
334
361
|
|
362
|
+
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
363
|
+
# of +self+ from an ISO 8601 string.
|
364
|
+
#
|
365
|
+
# Time.zone = 'Hawaii' # => "Hawaii"
|
366
|
+
# Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
367
|
+
#
|
368
|
+
# If the time components are missing then they will be set to zero.
|
369
|
+
#
|
370
|
+
# Time.zone = 'Hawaii' # => "Hawaii"
|
371
|
+
# Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
|
372
|
+
#
|
373
|
+
# If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
|
374
|
+
# which usually returns +nil+ when given an invalid date string.
|
375
|
+
def iso8601(str)
|
376
|
+
parts = Date._iso8601(str)
|
377
|
+
|
378
|
+
raise ArgumentError, "invalid date" if parts.empty?
|
379
|
+
|
380
|
+
time = Time.new(
|
381
|
+
parts.fetch(:year),
|
382
|
+
parts.fetch(:mon),
|
383
|
+
parts.fetch(:mday),
|
384
|
+
parts.fetch(:hour, 0),
|
385
|
+
parts.fetch(:min, 0),
|
386
|
+
parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
|
387
|
+
parts.fetch(:offset, 0)
|
388
|
+
)
|
389
|
+
|
390
|
+
if parts[:offset]
|
391
|
+
TimeWithZone.new(time.utc, self)
|
392
|
+
else
|
393
|
+
TimeWithZone.new(nil, self, time)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
335
397
|
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
336
398
|
# of +self+ from parsed string.
|
337
399
|
#
|
@@ -348,25 +410,64 @@ module ActiveSupport
|
|
348
410
|
# components are supplied, then the day of the month defaults to 1:
|
349
411
|
#
|
350
412
|
# Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
|
351
|
-
|
352
|
-
|
353
|
-
|
413
|
+
#
|
414
|
+
# If the string is invalid then an +ArgumentError+ could be raised.
|
415
|
+
def parse(str, now = now())
|
416
|
+
parts_to_time(Date._parse(str, false), now)
|
417
|
+
end
|
418
|
+
|
419
|
+
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
420
|
+
# of +self+ from an RFC 3339 string.
|
421
|
+
#
|
422
|
+
# Time.zone = 'Hawaii' # => "Hawaii"
|
423
|
+
# Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
424
|
+
#
|
425
|
+
# If the time or zone components are missing then an +ArgumentError+ will
|
426
|
+
# be raised. This is much stricter than either +parse+ or +iso8601+ which
|
427
|
+
# allow for missing components.
|
428
|
+
#
|
429
|
+
# Time.zone = 'Hawaii' # => "Hawaii"
|
430
|
+
# Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
|
431
|
+
def rfc3339(str)
|
432
|
+
parts = Date._rfc3339(str)
|
433
|
+
|
434
|
+
raise ArgumentError, "invalid date" if parts.empty?
|
354
435
|
|
355
436
|
time = Time.new(
|
356
|
-
parts.fetch(:year
|
357
|
-
parts.fetch(:mon
|
358
|
-
parts.fetch(:mday
|
359
|
-
parts.fetch(:hour
|
360
|
-
parts.fetch(:min
|
361
|
-
parts.fetch(:sec
|
362
|
-
parts.fetch(:offset
|
437
|
+
parts.fetch(:year),
|
438
|
+
parts.fetch(:mon),
|
439
|
+
parts.fetch(:mday),
|
440
|
+
parts.fetch(:hour),
|
441
|
+
parts.fetch(:min),
|
442
|
+
parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
|
443
|
+
parts.fetch(:offset)
|
363
444
|
)
|
364
445
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
446
|
+
TimeWithZone.new(time.utc, self)
|
447
|
+
end
|
448
|
+
|
449
|
+
# Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
|
450
|
+
#
|
451
|
+
# Assumes that +str+ is a time in the time zone +self+,
|
452
|
+
# unless +format+ includes an explicit time zone.
|
453
|
+
# (This is the same behavior as +parse+.)
|
454
|
+
# In either case, the returned TimeWithZone has the timezone of +self+.
|
455
|
+
#
|
456
|
+
# Time.zone = 'Hawaii' # => "Hawaii"
|
457
|
+
# 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
|
458
|
+
#
|
459
|
+
# If upper components are missing from the string, they are supplied from
|
460
|
+
# TimeZone#now:
|
461
|
+
#
|
462
|
+
# Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
463
|
+
# Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
|
464
|
+
#
|
465
|
+
# However, if the date component is not provided, but any other upper
|
466
|
+
# components are supplied, then the day of the month defaults to 1:
|
467
|
+
#
|
468
|
+
# Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
|
469
|
+
def strptime(str, format, now = now())
|
470
|
+
parts_to_time(DateTime._strptime(str, format), now)
|
370
471
|
end
|
371
472
|
|
372
473
|
# Returns an ActiveSupport::TimeWithZone instance representing the current
|
@@ -378,7 +479,7 @@ module ActiveSupport
|
|
378
479
|
time_now.utc.in_time_zone(self)
|
379
480
|
end
|
380
481
|
|
381
|
-
#
|
482
|
+
# Returns the current date in this time zone.
|
382
483
|
def today
|
383
484
|
tzinfo.now.to_date
|
384
485
|
end
|
@@ -402,7 +503,7 @@ module ActiveSupport
|
|
402
503
|
|
403
504
|
# Adjust the given time to the simultaneous time in UTC. Returns a
|
404
505
|
# Time.utc() instance.
|
405
|
-
def local_to_utc(time, dst=true)
|
506
|
+
def local_to_utc(time, dst = true)
|
406
507
|
tzinfo.local_to_utc(time, dst)
|
407
508
|
end
|
408
509
|
|
@@ -414,15 +515,49 @@ module ActiveSupport
|
|
414
515
|
|
415
516
|
# Available so that TimeZone instances respond like TZInfo::Timezone
|
416
517
|
# instances.
|
417
|
-
def period_for_local(time, dst=true)
|
418
|
-
tzinfo.period_for_local(time, dst)
|
518
|
+
def period_for_local(time, dst = true)
|
519
|
+
tzinfo.period_for_local(time, dst) { |periods| periods.last }
|
419
520
|
end
|
420
521
|
|
421
522
|
def periods_for_local(time) #:nodoc:
|
422
523
|
tzinfo.periods_for_local(time)
|
423
524
|
end
|
424
525
|
|
526
|
+
def init_with(coder) #:nodoc:
|
527
|
+
initialize(coder["name"])
|
528
|
+
end
|
529
|
+
|
530
|
+
def encode_with(coder) #:nodoc:
|
531
|
+
coder.tag = "!ruby/object:#{self.class}"
|
532
|
+
coder.map = { "name" => tzinfo.name }
|
533
|
+
end
|
534
|
+
|
425
535
|
private
|
536
|
+
def parts_to_time(parts, now)
|
537
|
+
raise ArgumentError, "invalid date" if parts.nil?
|
538
|
+
return if parts.empty?
|
539
|
+
|
540
|
+
if parts[:seconds]
|
541
|
+
time = Time.at(parts[:seconds])
|
542
|
+
else
|
543
|
+
time = Time.new(
|
544
|
+
parts.fetch(:year, now.year),
|
545
|
+
parts.fetch(:mon, now.month),
|
546
|
+
parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
|
547
|
+
parts.fetch(:hour, 0),
|
548
|
+
parts.fetch(:min, 0),
|
549
|
+
parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
|
550
|
+
parts.fetch(:offset, 0)
|
551
|
+
)
|
552
|
+
end
|
553
|
+
|
554
|
+
if parts[:offset] || parts[:seconds]
|
555
|
+
TimeWithZone.new(time.utc, self)
|
556
|
+
else
|
557
|
+
TimeWithZone.new(nil, self, time)
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
426
561
|
def time_now
|
427
562
|
Time.now
|
428
563
|
end
|
Binary file
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
raise "JRuby is required to use the JDOM backend for XmlMini" unless RUBY_PLATFORM.include?("java")
|
4
|
+
|
5
|
+
require "jruby"
|
4
6
|
include Java
|
5
7
|
|
6
|
-
require
|
8
|
+
require "active_support/core_ext/object/blank"
|
7
9
|
|
8
10
|
java_import javax.xml.parsers.DocumentBuilder unless defined? DocumentBuilder
|
9
11
|
java_import javax.xml.parsers.DocumentBuilderFactory unless defined? DocumentBuilderFactory
|
@@ -16,7 +18,7 @@ module ActiveSupport
|
|
16
18
|
module XmlMini_JDOM #:nodoc:
|
17
19
|
extend self
|
18
20
|
|
19
|
-
CONTENT_KEY =
|
21
|
+
CONTENT_KEY = "__content__".freeze
|
20
22
|
|
21
23
|
NODE_TYPE_NAMES = %w{ATTRIBUTE_NODE CDATA_SECTION_NODE COMMENT_NODE DOCUMENT_FRAGMENT_NODE
|
22
24
|
DOCUMENT_NODE DOCUMENT_TYPE_NODE ELEMENT_NODE ENTITY_NODE ENTITY_REFERENCE_NODE NOTATION_NODE
|
@@ -38,7 +40,7 @@ module ActiveSupport
|
|
38
40
|
else
|
39
41
|
@dbf = DocumentBuilderFactory.new_instance
|
40
42
|
# secure processing of java xml
|
41
|
-
#
|
43
|
+
# https://archive.is/9xcQQ
|
42
44
|
@dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
|
43
45
|
@dbf.setFeature("http://xml.org/sax/features/external-general-entities", false)
|
44
46
|
@dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false)
|
@@ -46,136 +48,136 @@ module ActiveSupport
|
|
46
48
|
xml_string_reader = StringReader.new(data)
|
47
49
|
xml_input_source = InputSource.new(xml_string_reader)
|
48
50
|
doc = @dbf.new_document_builder.parse(xml_input_source)
|
49
|
-
merge_element!({CONTENT_KEY =>
|
51
|
+
merge_element!({ CONTENT_KEY => "" }, doc.document_element, XmlMini.depth)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
55
|
private
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
def delete_empty(hash)
|
68
|
-
hash.delete(CONTENT_KEY) if hash[CONTENT_KEY] == ''
|
69
|
-
end
|
57
|
+
# Convert an XML element and merge into the hash
|
58
|
+
#
|
59
|
+
# hash::
|
60
|
+
# Hash to merge the converted element into.
|
61
|
+
# element::
|
62
|
+
# XML element to merge into hash
|
63
|
+
def merge_element!(hash, element, depth)
|
64
|
+
raise "Document too deep!" if depth == 0
|
65
|
+
delete_empty(hash)
|
66
|
+
merge!(hash, element.tag_name, collapse(element, depth))
|
67
|
+
end
|
70
68
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
# The document element to be collapsed.
|
75
|
-
def collapse(element, depth)
|
76
|
-
hash = get_attributes(element)
|
69
|
+
def delete_empty(hash)
|
70
|
+
hash.delete(CONTENT_KEY) if hash[CONTENT_KEY] == ""
|
71
|
+
end
|
77
72
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
73
|
+
# Actually converts an XML document element into a data structure.
|
74
|
+
#
|
75
|
+
# element::
|
76
|
+
# The document element to be collapsed.
|
77
|
+
def collapse(element, depth)
|
78
|
+
hash = get_attributes(element)
|
79
|
+
|
80
|
+
child_nodes = element.child_nodes
|
81
|
+
if child_nodes.length > 0
|
82
|
+
(0...child_nodes.length).each do |i|
|
83
|
+
child = child_nodes.item(i)
|
84
|
+
merge_element!(hash, child, depth - 1) unless child.node_type == Node.TEXT_NODE
|
85
|
+
end
|
86
|
+
merge_texts!(hash, element) unless empty_content?(element)
|
87
|
+
hash
|
88
|
+
else
|
89
|
+
merge_texts!(hash, element)
|
83
90
|
end
|
84
|
-
merge_texts!(hash, element) unless empty_content?(element)
|
85
|
-
hash
|
86
|
-
else
|
87
|
-
merge_texts!(hash, element)
|
88
91
|
end
|
89
|
-
end
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
93
|
+
# Merge all the texts of an element into the hash
|
94
|
+
#
|
95
|
+
# hash::
|
96
|
+
# Hash to add the converted element to.
|
97
|
+
# element::
|
98
|
+
# XML element whose texts are to me merged into the hash
|
99
|
+
def merge_texts!(hash, element)
|
100
|
+
delete_empty(hash)
|
101
|
+
text_children = texts(element)
|
102
|
+
if text_children.join.empty?
|
103
|
+
hash
|
104
|
+
else
|
105
|
+
# must use value to prevent double-escaping
|
106
|
+
merge!(hash, CONTENT_KEY, text_children.join)
|
107
|
+
end
|
105
108
|
end
|
106
|
-
end
|
107
109
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
110
|
+
# Adds a new key/value pair to an existing Hash. If the key to be added
|
111
|
+
# already exists and the existing value associated with key is not
|
112
|
+
# an Array, it will be wrapped in an Array. Then the new value is
|
113
|
+
# appended to that Array.
|
114
|
+
#
|
115
|
+
# hash::
|
116
|
+
# Hash to add key/value pair to.
|
117
|
+
# key::
|
118
|
+
# Key to be added.
|
119
|
+
# value::
|
120
|
+
# Value to be associated with key.
|
121
|
+
def merge!(hash, key, value)
|
122
|
+
if hash.has_key?(key)
|
123
|
+
if hash[key].instance_of?(Array)
|
124
|
+
hash[key] << value
|
125
|
+
else
|
126
|
+
hash[key] = [hash[key], value]
|
127
|
+
end
|
128
|
+
elsif value.instance_of?(Array)
|
129
|
+
hash[key] = [value]
|
123
130
|
else
|
124
|
-
hash[key] =
|
131
|
+
hash[key] = value
|
125
132
|
end
|
126
|
-
|
127
|
-
hash[key] = [value]
|
128
|
-
else
|
129
|
-
hash[key] = value
|
133
|
+
hash
|
130
134
|
end
|
131
|
-
hash
|
132
|
-
end
|
133
135
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
136
|
+
# Converts the attributes array of an XML element into a hash.
|
137
|
+
# Returns an empty Hash if node has no attributes.
|
138
|
+
#
|
139
|
+
# element::
|
140
|
+
# XML element to extract attributes from.
|
141
|
+
def get_attributes(element)
|
142
|
+
attribute_hash = {}
|
143
|
+
attributes = element.attributes
|
144
|
+
(0...attributes.length).each do |i|
|
145
|
+
attribute_hash[CONTENT_KEY] ||= ""
|
146
|
+
attribute_hash[attributes.item(i).name] = attributes.item(i).value
|
147
|
+
end
|
148
|
+
attribute_hash
|
149
|
+
end
|
148
150
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
151
|
+
# Determines if a document element has text content
|
152
|
+
#
|
153
|
+
# element::
|
154
|
+
# XML element to be checked.
|
155
|
+
def texts(element)
|
156
|
+
texts = []
|
157
|
+
child_nodes = element.child_nodes
|
158
|
+
(0...child_nodes.length).each do |i|
|
159
|
+
item = child_nodes.item(i)
|
160
|
+
if item.node_type == Node.TEXT_NODE
|
161
|
+
texts << item.get_data
|
162
|
+
end
|
160
163
|
end
|
164
|
+
texts
|
161
165
|
end
|
162
|
-
texts
|
163
|
-
end
|
164
166
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
167
|
+
# Determines if a document element has text content
|
168
|
+
#
|
169
|
+
# element::
|
170
|
+
# XML element to be checked.
|
171
|
+
def empty_content?(element)
|
172
|
+
text = "".dup
|
173
|
+
child_nodes = element.child_nodes
|
174
|
+
(0...child_nodes.length).each do |i|
|
175
|
+
item = child_nodes.item(i)
|
176
|
+
if item.node_type == Node.TEXT_NODE
|
177
|
+
text << item.get_data.strip
|
178
|
+
end
|
176
179
|
end
|
180
|
+
text.strip.length == 0
|
177
181
|
end
|
178
|
-
text.strip.length == 0
|
179
|
-
end
|
180
182
|
end
|
181
183
|
end
|