activesupport 1.2.4 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +505 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +40 -0
- data/lib/active_support/actionable_error.rb +50 -0
- data/lib/active_support/all.rb +5 -0
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +234 -0
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +53 -0
- data/lib/active_support/broadcast_logger.rb +238 -0
- data/lib/active_support/builder.rb +8 -0
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +244 -0
- data/lib/active_support/cache/mem_cache_store.rb +288 -0
- data/lib/active_support/cache/memory_store.rb +264 -0
- data/lib/active_support/cache/null_store.rb +62 -0
- data/lib/active_support/cache/redis_cache_store.rb +498 -0
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +246 -0
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +1170 -0
- data/lib/active_support/callbacks.rb +960 -0
- data/lib/active_support/class_attribute.rb +33 -0
- data/lib/active_support/code_generator.rb +79 -0
- data/lib/active_support/concern.rb +217 -0
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +225 -0
- data/lib/active_support/concurrency/thread_monitor.rb +55 -0
- data/lib/active_support/configurable.rb +193 -0
- data/lib/active_support/configuration_file.rb +60 -0
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/array/access.rb +100 -0
- data/lib/active_support/core_ext/array/conversions.rb +209 -26
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/core_ext/array/grouping.rb +109 -0
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/core_ext/array.rb +8 -4
- data/lib/active_support/core_ext/benchmark.rb +6 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
- data/lib/active_support/core_ext/big_decimal.rb +3 -0
- data/lib/active_support/core_ext/class/attribute.rb +137 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/class/subclasses.rb +24 -0
- data/lib/active_support/core_ext/class.rb +4 -0
- data/lib/active_support/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/core_ext/date/blank.rb +18 -0
- data/lib/active_support/core_ext/date/calculations.rb +161 -0
- data/lib/active_support/core_ext/date/conversions.rb +95 -28
- data/lib/active_support/core_ext/date/zones.rb +8 -0
- data/lib/active_support/core_ext/date.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +23 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +16 -0
- data/lib/active_support/core_ext/date_time/blank.rb +18 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +108 -0
- data/lib/active_support/core_ext/date_time.rb +7 -0
- data/lib/active_support/core_ext/digest/uuid.rb +76 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +277 -7
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/file/atomic.rb +72 -0
- data/lib/active_support/core_ext/file.rb +3 -0
- data/lib/active_support/core_ext/hash/conversions.rb +262 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +43 -0
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +12 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +19 -55
- data/lib/active_support/core_ext/hash/keys.rb +134 -44
- data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -22
- data/lib/active_support/core_ext/hash/slice.rb +27 -0
- data/lib/active_support/core_ext/hash.rb +9 -8
- data/lib/active_support/core_ext/integer/inflections.rb +29 -13
- data/lib/active_support/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/core_ext/integer/time.rb +22 -0
- data/lib/active_support/core_ext/integer.rb +4 -6
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/core_ext/kernel.rb +4 -78
- data/lib/active_support/core_ext/load_error.rb +6 -35
- data/lib/active_support/core_ext/module/aliasing.rb +31 -0
- data/lib/active_support/core_ext/module/anonymous.rb +30 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +48 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +225 -0
- data/lib/active_support/core_ext/module/deprecation.rb +25 -0
- data/lib/active_support/core_ext/module/introspection.rb +65 -0
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +17 -0
- data/lib/active_support/core_ext/module.rb +13 -0
- data/lib/active_support/core_ext/name_error.rb +59 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +73 -42
- data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
- data/lib/active_support/core_ext/numeric/time.rb +64 -57
- data/lib/active_support/core_ext/numeric.rb +4 -6
- data/lib/active_support/core_ext/object/acts_like.rb +45 -0
- data/lib/active_support/core_ext/object/blank.rb +199 -0
- data/lib/active_support/core_ext/object/conversions.rb +6 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
- data/lib/active_support/core_ext/object/duplicable.rb +69 -0
- data/lib/active_support/core_ext/object/inclusion.rb +37 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
- data/lib/active_support/core_ext/object/json.rb +267 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -0
- data/lib/active_support/core_ext/object/to_query.rb +93 -0
- data/lib/active_support/core_ext/object/try.rb +158 -0
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +101 -0
- data/lib/active_support/core_ext/object.rb +17 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +58 -17
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +5 -4
- data/lib/active_support/core_ext/regexp.rb +14 -0
- data/lib/active_support/core_ext/securerandom.rb +57 -0
- data/lib/active_support/core_ext/string/access.rb +93 -56
- data/lib/active_support/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/core_ext/string/conversions.rb +57 -16
- data/lib/active_support/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/core_ext/string/filters.rb +151 -0
- data/lib/active_support/core_ext/string/indent.rb +45 -0
- data/lib/active_support/core_ext/string/inflections.rb +297 -54
- data/lib/active_support/core_ext/string/inquiry.rb +16 -0
- data/lib/active_support/core_ext/string/multibyte.rb +67 -0
- data/lib/active_support/core_ext/string/output_safety.rb +235 -0
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -18
- data/lib/active_support/core_ext/string/strip.rb +27 -0
- data/lib/active_support/core_ext/string/zones.rb +16 -0
- data/lib/active_support/core_ext/string.rb +14 -10
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/thread/backtrace/location.rb +7 -0
- data/lib/active_support/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/core_ext/time/calculations.rb +358 -153
- data/lib/active_support/core_ext/time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/time/conversions.rb +69 -30
- data/lib/active_support/core_ext/time/zones.rb +97 -0
- data/lib/active_support/core_ext/time.rb +6 -6
- data/lib/active_support/core_ext.rb +5 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +243 -0
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +183 -0
- data/lib/active_support/dependencies/autoload.rb +72 -0
- data/lib/active_support/dependencies/interlock.rb +55 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +84 -222
- data/lib/active_support/deprecation/behaviors.rb +148 -0
- data/lib/active_support/deprecation/constant_accessor.rb +74 -0
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/method_wrappers.rb +68 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
- data/lib/active_support/deprecation/reporting.rb +162 -0
- data/lib/active_support/deprecation.rb +81 -0
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +112 -0
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +64 -0
- data/lib/active_support/duration.rb +524 -0
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/encrypted_configuration.rb +126 -0
- data/lib/active_support/encrypted_file.rb +133 -0
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +318 -0
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +592 -0
- data/lib/active_support/evented_file_update_checker.rb +185 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +110 -0
- data/lib/active_support/execution_wrapper.rb +150 -0
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +166 -0
- data/lib/active_support/fork_tracker.rb +43 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +41 -0
- data/lib/active_support/hash_with_indifferent_access.rb +464 -0
- data/lib/active_support/html_safe_translation.rb +56 -0
- data/lib/active_support/i18n.rb +17 -0
- data/lib/active_support/i18n_railtie.rb +140 -0
- data/lib/active_support/inflections.rb +68 -49
- data/lib/active_support/inflector/inflections.rb +290 -0
- data/lib/active_support/inflector/methods.rb +387 -0
- data/lib/active_support/inflector/transliterate.rb +147 -0
- data/lib/active_support/inflector.rb +7 -164
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +78 -0
- data/lib/active_support/json/encoding.rb +256 -0
- data/lib/active_support/json.rb +4 -0
- data/lib/active_support/key_generator.rb +66 -0
- data/lib/active_support/lazy_load_hooks.rb +107 -0
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +141 -0
- data/lib/active_support/log_subscriber/test_helper.rb +106 -0
- data/lib/active_support/log_subscriber.rb +188 -0
- data/lib/active_support/logger.rb +55 -0
- data/lib/active_support/logger_silence.rb +21 -0
- data/lib/active_support/logger_thread_safe_level.rb +50 -0
- data/lib/active_support/message_encryptor.rb +374 -0
- data/lib/active_support/message_encryptors.rb +193 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +310 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +377 -0
- data/lib/active_support/message_verifiers.rb +189 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +146 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotation_coordinator.rb +102 -0
- data/lib/active_support/messages/rotator.rb +69 -0
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +188 -0
- data/lib/active_support/multibyte/unicode.rb +42 -0
- data/lib/active_support/multibyte.rb +27 -0
- data/lib/active_support/notifications/fanout.rb +467 -0
- data/lib/active_support/notifications/instrumenter.rb +240 -0
- data/lib/active_support/notifications.rb +281 -0
- data/lib/active_support/number_helper/number_converter.rb +190 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
- data/lib/active_support/number_helper/rounding_helper.rb +46 -0
- data/lib/active_support/number_helper.rb +479 -0
- data/lib/active_support/option_merger.rb +38 -0
- data/lib/active_support/ordered_hash.rb +50 -0
- data/lib/active_support/ordered_options.rb +141 -25
- data/lib/active_support/parameter_filter.rb +157 -0
- data/lib/active_support/rails.rb +26 -0
- data/lib/active_support/railtie.rb +180 -0
- data/lib/active_support/reloader.rb +138 -0
- data/lib/active_support/rescuable.rb +176 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +35 -0
- data/lib/active_support/structured_event_subscriber.rb +99 -0
- data/lib/active_support/subscriber.rb +141 -0
- data/lib/active_support/syntax_error_proxy.rb +67 -0
- data/lib/active_support/tagged_logging.rb +157 -0
- data/lib/active_support/test_case.rb +365 -0
- data/lib/active_support/testing/assertions.rb +369 -0
- data/lib/active_support/testing/autorun.rb +10 -0
- data/lib/active_support/testing/constant_lookup.rb +51 -0
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/declarative.rb +28 -0
- data/lib/active_support/testing/deprecation.rb +82 -0
- data/lib/active_support/testing/error_reporter_assertions.rb +124 -0
- data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +121 -0
- data/lib/active_support/testing/method_call_assertions.rb +69 -0
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/server.rb +98 -0
- data/lib/active_support/testing/parallelization/worker.rb +107 -0
- data/lib/active_support/testing/parallelization.rb +79 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +57 -0
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +27 -0
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +273 -0
- data/lib/active_support/time.rb +20 -0
- data/lib/active_support/time_with_zone.rb +613 -0
- data/lib/active_support/values/time_zone.rb +599 -158
- data/lib/active_support/version.rb +7 -6
- data/lib/active_support/xml_mini/jdom.rb +175 -0
- data/lib/active_support/xml_mini/libxml.rb +80 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
- data/lib/active_support/xml_mini/nokogiri.rb +83 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
- data/lib/active_support/xml_mini/rexml.rb +137 -0
- data/lib/active_support/xml_mini.rb +212 -0
- data/lib/active_support.rb +122 -10
- metadata +524 -93
- data/CHANGELOG +0 -283
- data/lib/active_support/binding_of_caller.rb +0 -84
- data/lib/active_support/breakpoint.rb +0 -523
- data/lib/active_support/class_attribute_accessors.rb +0 -57
- data/lib/active_support/class_inheritable_attributes.rb +0 -117
- data/lib/active_support/clean_logger.rb +0 -36
- data/lib/active_support/core_ext/blank.rb +0 -38
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -14
- data/lib/active_support/core_ext/cgi.rb +0 -5
- data/lib/active_support/core_ext/exception.rb +0 -29
- data/lib/active_support/core_ext/integer/even_odd.rb +0 -24
- data/lib/active_support/core_ext/object_and_class.rb +0 -44
- data/lib/active_support/module_attribute_accessors.rb +0 -57
- data/lib/active_support/whiny_nil.rb +0 -38
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/object/try"
|
|
4
|
+
require "active_support/core_ext/date_time/conversions"
|
|
5
|
+
|
|
6
|
+
module DateAndTime
|
|
7
|
+
module Calculations
|
|
8
|
+
DAYS_INTO_WEEK = {
|
|
9
|
+
sunday: 0,
|
|
10
|
+
monday: 1,
|
|
11
|
+
tuesday: 2,
|
|
12
|
+
wednesday: 3,
|
|
13
|
+
thursday: 4,
|
|
14
|
+
friday: 5,
|
|
15
|
+
saturday: 6
|
|
16
|
+
}
|
|
17
|
+
WEEKEND_DAYS = [ 6, 0 ]
|
|
18
|
+
|
|
19
|
+
# Returns a new date/time representing yesterday.
|
|
20
|
+
def yesterday
|
|
21
|
+
advance(days: -1)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns a new date/time representing tomorrow.
|
|
25
|
+
def tomorrow
|
|
26
|
+
advance(days: 1)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Returns true if the date/time is today.
|
|
30
|
+
def today?
|
|
31
|
+
to_date == ::Date.current
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns true if the date/time is tomorrow.
|
|
35
|
+
def tomorrow?
|
|
36
|
+
to_date == ::Date.current.tomorrow
|
|
37
|
+
end
|
|
38
|
+
alias :next_day? :tomorrow?
|
|
39
|
+
|
|
40
|
+
# Returns true if the date/time is yesterday.
|
|
41
|
+
def yesterday?
|
|
42
|
+
to_date == ::Date.current.yesterday
|
|
43
|
+
end
|
|
44
|
+
alias :prev_day? :yesterday?
|
|
45
|
+
|
|
46
|
+
# Returns true if the date/time is in the past.
|
|
47
|
+
def past?
|
|
48
|
+
self < self.class.current
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns true if the date/time is in the future.
|
|
52
|
+
def future?
|
|
53
|
+
self > self.class.current
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns true if the date/time falls on a Saturday or Sunday.
|
|
57
|
+
def on_weekend?
|
|
58
|
+
WEEKEND_DAYS.include?(wday)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns true if the date/time does not fall on a Saturday or Sunday.
|
|
62
|
+
def on_weekday?
|
|
63
|
+
!WEEKEND_DAYS.include?(wday)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Returns true if the date/time falls before <tt>date_or_time</tt>.
|
|
67
|
+
def before?(date_or_time)
|
|
68
|
+
self < date_or_time
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Returns true if the date/time falls after <tt>date_or_time</tt>.
|
|
72
|
+
def after?(date_or_time)
|
|
73
|
+
self > date_or_time
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns a new date/time the specified number of days ago.
|
|
77
|
+
def days_ago(days)
|
|
78
|
+
advance(days: -days)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns a new date/time the specified number of days in the future.
|
|
82
|
+
def days_since(days)
|
|
83
|
+
advance(days: days)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Returns a new date/time the specified number of weeks ago.
|
|
87
|
+
def weeks_ago(weeks)
|
|
88
|
+
advance(weeks: -weeks)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns a new date/time the specified number of weeks in the future.
|
|
92
|
+
def weeks_since(weeks)
|
|
93
|
+
advance(weeks: weeks)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Returns a new date/time the specified number of months ago.
|
|
97
|
+
def months_ago(months)
|
|
98
|
+
advance(months: -months)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Returns a new date/time the specified number of months in the future.
|
|
102
|
+
def months_since(months)
|
|
103
|
+
advance(months: months)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Returns a new date/time the specified number of years ago.
|
|
107
|
+
def years_ago(years)
|
|
108
|
+
advance(years: -years)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Returns a new date/time the specified number of years in the future.
|
|
112
|
+
def years_since(years)
|
|
113
|
+
advance(years: years)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Returns a new date/time at the start of the month.
|
|
117
|
+
#
|
|
118
|
+
# today = Date.today # => Thu, 18 Jun 2015
|
|
119
|
+
# today.beginning_of_month # => Mon, 01 Jun 2015
|
|
120
|
+
#
|
|
121
|
+
# +DateTime+ objects will have a time set to 0:00.
|
|
122
|
+
#
|
|
123
|
+
# now = DateTime.current # => Thu, 18 Jun 2015 15:23:13 +0000
|
|
124
|
+
# now.beginning_of_month # => Mon, 01 Jun 2015 00:00:00 +0000
|
|
125
|
+
def beginning_of_month
|
|
126
|
+
first_hour(change(day: 1))
|
|
127
|
+
end
|
|
128
|
+
alias :at_beginning_of_month :beginning_of_month
|
|
129
|
+
|
|
130
|
+
# Returns a new date/time at the start of the quarter.
|
|
131
|
+
#
|
|
132
|
+
# today = Date.today # => Fri, 10 Jul 2015
|
|
133
|
+
# today.beginning_of_quarter # => Wed, 01 Jul 2015
|
|
134
|
+
#
|
|
135
|
+
# +DateTime+ objects will have a time set to 0:00.
|
|
136
|
+
#
|
|
137
|
+
# now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
|
138
|
+
# now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
|
|
139
|
+
def beginning_of_quarter
|
|
140
|
+
first_quarter_month = month - (2 + month) % 3
|
|
141
|
+
beginning_of_month.change(month: first_quarter_month)
|
|
142
|
+
end
|
|
143
|
+
alias :at_beginning_of_quarter :beginning_of_quarter
|
|
144
|
+
|
|
145
|
+
# Returns a new date/time at the end of the quarter.
|
|
146
|
+
#
|
|
147
|
+
# today = Date.today # => Fri, 10 Jul 2015
|
|
148
|
+
# today.end_of_quarter # => Wed, 30 Sep 2015
|
|
149
|
+
#
|
|
150
|
+
# +DateTime+ objects will have a time set to 23:59:59.
|
|
151
|
+
#
|
|
152
|
+
# now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
|
153
|
+
# now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
|
|
154
|
+
def end_of_quarter
|
|
155
|
+
last_quarter_month = month + (12 - month) % 3
|
|
156
|
+
beginning_of_month.change(month: last_quarter_month).end_of_month
|
|
157
|
+
end
|
|
158
|
+
alias :at_end_of_quarter :end_of_quarter
|
|
159
|
+
|
|
160
|
+
# Returns the quarter for a date/time.
|
|
161
|
+
#
|
|
162
|
+
# Date.new(2010, 1, 31).quarter # => 1
|
|
163
|
+
# Date.new(2010, 4, 12).quarter # => 2
|
|
164
|
+
# Date.new(2010, 9, 15).quarter # => 3
|
|
165
|
+
# Date.new(2010, 12, 25).quarter # => 4
|
|
166
|
+
def quarter
|
|
167
|
+
(month / 3.0).ceil
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Returns a new date/time at the beginning of the year.
|
|
171
|
+
#
|
|
172
|
+
# today = Date.today # => Fri, 10 Jul 2015
|
|
173
|
+
# today.beginning_of_year # => Thu, 01 Jan 2015
|
|
174
|
+
#
|
|
175
|
+
# +DateTime+ objects will have a time set to 0:00.
|
|
176
|
+
#
|
|
177
|
+
# now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
|
|
178
|
+
# now.beginning_of_year # => Thu, 01 Jan 2015 00:00:00 +0000
|
|
179
|
+
def beginning_of_year
|
|
180
|
+
change(month: 1).beginning_of_month
|
|
181
|
+
end
|
|
182
|
+
alias :at_beginning_of_year :beginning_of_year
|
|
183
|
+
|
|
184
|
+
# Returns a new date/time representing the given day in the next week.
|
|
185
|
+
#
|
|
186
|
+
# today = Date.today # => Thu, 07 May 2015
|
|
187
|
+
# today.next_week # => Mon, 11 May 2015
|
|
188
|
+
#
|
|
189
|
+
# The +given_day_in_next_week+ defaults to the beginning of the week
|
|
190
|
+
# which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
|
|
191
|
+
# when set.
|
|
192
|
+
#
|
|
193
|
+
# today = Date.today # => Thu, 07 May 2015
|
|
194
|
+
# today.next_week(:friday) # => Fri, 15 May 2015
|
|
195
|
+
#
|
|
196
|
+
# +DateTime+ objects have their time set to 0:00 unless +same_time+ is true.
|
|
197
|
+
#
|
|
198
|
+
# now = DateTime.current # => Thu, 07 May 2015 13:31:16 +0000
|
|
199
|
+
# now.next_week # => Mon, 11 May 2015 00:00:00 +0000
|
|
200
|
+
def next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false)
|
|
201
|
+
result = first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
|
|
202
|
+
same_time ? copy_time_to(result) : result
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Returns a new date/time representing the next weekday.
|
|
206
|
+
def next_weekday
|
|
207
|
+
if next_day.on_weekend?
|
|
208
|
+
next_week(:monday, same_time: true)
|
|
209
|
+
else
|
|
210
|
+
next_day
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Short-hand for <tt>months_since(3)</tt>.
|
|
215
|
+
def next_quarter
|
|
216
|
+
months_since(3)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Returns a new date/time representing the given day in the previous week.
|
|
220
|
+
# Week is assumed to start on +start_day+, default is
|
|
221
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
222
|
+
# DateTime objects have their time set to 0:00 unless +same_time+ is true.
|
|
223
|
+
def prev_week(start_day = Date.beginning_of_week, same_time: false)
|
|
224
|
+
result = first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
|
|
225
|
+
same_time ? copy_time_to(result) : result
|
|
226
|
+
end
|
|
227
|
+
alias_method :last_week, :prev_week
|
|
228
|
+
|
|
229
|
+
# Returns a new date/time representing the previous weekday.
|
|
230
|
+
def prev_weekday
|
|
231
|
+
if prev_day.on_weekend?
|
|
232
|
+
copy_time_to(beginning_of_week(:friday))
|
|
233
|
+
else
|
|
234
|
+
prev_day
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
alias_method :last_weekday, :prev_weekday
|
|
238
|
+
|
|
239
|
+
# Short-hand for <tt>months_ago(1)</tt>.
|
|
240
|
+
def last_month
|
|
241
|
+
months_ago(1)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Short-hand for <tt>months_ago(3)</tt>.
|
|
245
|
+
def prev_quarter
|
|
246
|
+
months_ago(3)
|
|
247
|
+
end
|
|
248
|
+
alias_method :last_quarter, :prev_quarter
|
|
249
|
+
|
|
250
|
+
# Short-hand for <tt>years_ago(1)</tt>.
|
|
251
|
+
def last_year
|
|
252
|
+
years_ago(1)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# Returns the number of days to the start of the week on the given day.
|
|
256
|
+
# Week is assumed to start on +start_day+, default is
|
|
257
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
258
|
+
def days_to_week_start(start_day = Date.beginning_of_week)
|
|
259
|
+
start_day_number = DAYS_INTO_WEEK.fetch(start_day)
|
|
260
|
+
(wday - start_day_number) % 7
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# Returns a new date/time representing the start of this week on the given day.
|
|
264
|
+
# Week is assumed to start on +start_day+, default is
|
|
265
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
266
|
+
# +DateTime+ objects have their time set to 0:00.
|
|
267
|
+
def beginning_of_week(start_day = Date.beginning_of_week)
|
|
268
|
+
result = days_ago(days_to_week_start(start_day))
|
|
269
|
+
acts_like?(:time) ? result.midnight : result
|
|
270
|
+
end
|
|
271
|
+
alias :at_beginning_of_week :beginning_of_week
|
|
272
|
+
|
|
273
|
+
# Returns Monday of this week assuming that week starts on Monday.
|
|
274
|
+
# +DateTime+ objects have their time set to 0:00.
|
|
275
|
+
def monday
|
|
276
|
+
beginning_of_week(:monday)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Returns a new date/time representing the end of this week on the given day.
|
|
280
|
+
# Week is assumed to start on +start_day+, default is
|
|
281
|
+
# +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
|
|
282
|
+
# DateTime objects have their time set to 23:59:59.
|
|
283
|
+
def end_of_week(start_day = Date.beginning_of_week)
|
|
284
|
+
last_hour(days_since(6 - days_to_week_start(start_day)))
|
|
285
|
+
end
|
|
286
|
+
alias :at_end_of_week :end_of_week
|
|
287
|
+
|
|
288
|
+
# Returns Sunday of this week assuming that week starts on Monday.
|
|
289
|
+
# +DateTime+ objects have their time set to 23:59:59.
|
|
290
|
+
def sunday
|
|
291
|
+
end_of_week(:monday)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Returns a new date/time representing the end of the month.
|
|
295
|
+
# DateTime objects will have a time set to 23:59:59.
|
|
296
|
+
def end_of_month
|
|
297
|
+
last_day = ::Time.days_in_month(month, year)
|
|
298
|
+
last_hour(days_since(last_day - day))
|
|
299
|
+
end
|
|
300
|
+
alias :at_end_of_month :end_of_month
|
|
301
|
+
|
|
302
|
+
# Returns a new date/time representing the end of the year.
|
|
303
|
+
# DateTime objects will have a time set to 23:59:59.
|
|
304
|
+
def end_of_year
|
|
305
|
+
change(month: 12).end_of_month
|
|
306
|
+
end
|
|
307
|
+
alias :at_end_of_year :end_of_year
|
|
308
|
+
|
|
309
|
+
# Returns a Range representing the whole day of the current date/time.
|
|
310
|
+
def all_day
|
|
311
|
+
beginning_of_day..end_of_day
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Returns a Range representing the whole week of the current date/time.
|
|
315
|
+
# Week starts on start_day, default is <tt>Date.beginning_of_week</tt> or <tt>config.beginning_of_week</tt> when set.
|
|
316
|
+
def all_week(start_day = Date.beginning_of_week)
|
|
317
|
+
beginning_of_week(start_day)..end_of_week(start_day)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Returns a Range representing the whole month of the current date/time.
|
|
321
|
+
def all_month
|
|
322
|
+
beginning_of_month..end_of_month
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Returns a Range representing the whole quarter of the current date/time.
|
|
326
|
+
def all_quarter
|
|
327
|
+
beginning_of_quarter..end_of_quarter
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# Returns a Range representing the whole year of the current date/time.
|
|
331
|
+
def all_year
|
|
332
|
+
beginning_of_year..end_of_year
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Returns a new date/time representing the next occurrence of the specified day of week.
|
|
336
|
+
#
|
|
337
|
+
# today = Date.today # => Thu, 14 Dec 2017
|
|
338
|
+
# today.next_occurring(:monday) # => Mon, 18 Dec 2017
|
|
339
|
+
# today.next_occurring(:thursday) # => Thu, 21 Dec 2017
|
|
340
|
+
def next_occurring(day_of_week)
|
|
341
|
+
from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
|
|
342
|
+
from_now += 7 unless from_now > 0
|
|
343
|
+
advance(days: from_now)
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# Returns a new date/time representing the previous occurrence of the specified day of week.
|
|
347
|
+
#
|
|
348
|
+
# today = Date.today # => Thu, 14 Dec 2017
|
|
349
|
+
# today.prev_occurring(:monday) # => Mon, 11 Dec 2017
|
|
350
|
+
# today.prev_occurring(:thursday) # => Thu, 07 Dec 2017
|
|
351
|
+
def prev_occurring(day_of_week)
|
|
352
|
+
ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
|
|
353
|
+
ago += 7 unless ago > 0
|
|
354
|
+
advance(days: -ago)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
private
|
|
358
|
+
def first_hour(date_or_time)
|
|
359
|
+
date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def last_hour(date_or_time)
|
|
363
|
+
date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def days_span(day)
|
|
367
|
+
(DAYS_INTO_WEEK.fetch(day) - DAYS_INTO_WEEK.fetch(Date.beginning_of_week)) % 7
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def copy_time_to(other)
|
|
371
|
+
other.change(hour: hour, min: min, sec: sec, nsec: try(:nsec))
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/module/attribute_accessors"
|
|
4
|
+
require "active_support/core_ext/module/redefine_method"
|
|
5
|
+
|
|
6
|
+
module DateAndTime
|
|
7
|
+
module Compatibility
|
|
8
|
+
# Change the output of <tt>ActiveSupport::TimeZone.utc_to_local</tt>.
|
|
9
|
+
#
|
|
10
|
+
# When +true+, it returns local times with a UTC offset, with +false+ local
|
|
11
|
+
# times are returned as UTC.
|
|
12
|
+
#
|
|
13
|
+
# # Given this zone:
|
|
14
|
+
# zone = ActiveSupport::TimeZone["Eastern Time (US & Canada)"]
|
|
15
|
+
#
|
|
16
|
+
# # With `utc_to_local_returns_utc_offset_times = false`, local time is converted to UTC:
|
|
17
|
+
# zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 UTC
|
|
18
|
+
#
|
|
19
|
+
# # With `utc_to_local_returns_utc_offset_times = true`, local time is returned with UTC offset:
|
|
20
|
+
# zone.utc_to_local(Time.utc(2000, 1)) # => 1999-12-31 19:00:00 -0500
|
|
21
|
+
mattr_accessor :utc_to_local_returns_utc_offset_times, instance_writer: false, default: false
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DateAndTime
|
|
4
|
+
module Zones
|
|
5
|
+
# Returns the simultaneous time in <tt>Time.zone</tt> if a zone is given or
|
|
6
|
+
# if Time.zone_default is set. Otherwise, it returns the current time.
|
|
7
|
+
#
|
|
8
|
+
# Time.zone = 'Hawaii' # => 'Hawaii'
|
|
9
|
+
# Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
|
10
|
+
# Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00
|
|
11
|
+
#
|
|
12
|
+
# This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
|
|
13
|
+
# instead of the operating system's time zone.
|
|
14
|
+
#
|
|
15
|
+
# You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
|
|
16
|
+
# and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
|
|
17
|
+
#
|
|
18
|
+
# Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
|
|
19
|
+
# Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
|
|
20
|
+
def in_time_zone(zone = ::Time.zone)
|
|
21
|
+
time_zone = ::Time.find_zone! zone
|
|
22
|
+
time = acts_like?(:time) ? self : nil
|
|
23
|
+
|
|
24
|
+
if time_zone
|
|
25
|
+
time_with_zone(time, time_zone)
|
|
26
|
+
else
|
|
27
|
+
time || to_time
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
def time_with_zone(time, zone)
|
|
33
|
+
if time
|
|
34
|
+
ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
|
|
35
|
+
else
|
|
36
|
+
ActiveSupport::TimeWithZone.new(nil, zone, to_time(:utc))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "date"
|
|
4
|
+
require "active_support/core_ext/object/acts_like"
|
|
5
|
+
|
|
6
|
+
class DateTime
|
|
7
|
+
# Duck-types as a Date-like class. See Object#acts_like?.
|
|
8
|
+
def acts_like_date?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Duck-types as a Time-like class. See Object#acts_like?.
|
|
13
|
+
def acts_like_time?
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "date"
|
|
4
|
+
|
|
5
|
+
class DateTime
|
|
6
|
+
class << self
|
|
7
|
+
# Returns <tt>Time.zone.now.to_datetime</tt> when <tt>Time.zone</tt> or
|
|
8
|
+
# <tt>config.time_zone</tt> are set, otherwise returns
|
|
9
|
+
# <tt>Time.now.to_datetime</tt>.
|
|
10
|
+
def current
|
|
11
|
+
::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Returns the number of seconds since 00:00:00.
|
|
16
|
+
#
|
|
17
|
+
# DateTime.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0
|
|
18
|
+
# DateTime.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296
|
|
19
|
+
# DateTime.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399
|
|
20
|
+
def seconds_since_midnight
|
|
21
|
+
sec + (min * 60) + (hour * 3600)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Returns the number of seconds until 23:59:59.
|
|
25
|
+
#
|
|
26
|
+
# DateTime.new(2012, 8, 29, 0, 0, 0).seconds_until_end_of_day # => 86399
|
|
27
|
+
# DateTime.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
|
|
28
|
+
# DateTime.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
|
|
29
|
+
def seconds_until_end_of_day
|
|
30
|
+
end_of_day.to_i - to_i
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns the fraction of a second as a +Rational+
|
|
34
|
+
#
|
|
35
|
+
# DateTime.new(2012, 8, 29, 0, 0, 0.5).subsec # => (1/2)
|
|
36
|
+
def subsec
|
|
37
|
+
sec_fraction
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns a new DateTime where one or more of the elements have been changed
|
|
41
|
+
# according to the +options+ parameter. The time options (<tt>:hour</tt>,
|
|
42
|
+
# <tt>:min</tt>, <tt>:sec</tt>) reset cascadingly, so if only the hour is
|
|
43
|
+
# passed, then minute and sec is set to 0. If the hour and minute is passed,
|
|
44
|
+
# then sec is set to 0. The +options+ parameter takes a hash with any of these
|
|
45
|
+
# keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>,
|
|
46
|
+
# <tt>:min</tt>, <tt>:sec</tt>, <tt>:offset</tt>, <tt>:start</tt>.
|
|
47
|
+
#
|
|
48
|
+
# DateTime.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => DateTime.new(2012, 8, 1, 22, 35, 0)
|
|
49
|
+
# DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => DateTime.new(1981, 8, 1, 22, 35, 0)
|
|
50
|
+
# DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
|
|
51
|
+
def change(options)
|
|
52
|
+
if new_nsec = options[:nsec]
|
|
53
|
+
raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
|
|
54
|
+
new_fraction = Rational(new_nsec, 1000000000)
|
|
55
|
+
else
|
|
56
|
+
new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
|
|
57
|
+
new_fraction = Rational(new_usec, 1000000)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
raise ArgumentError, "argument out of range" if new_fraction >= 1
|
|
61
|
+
|
|
62
|
+
::DateTime.civil(
|
|
63
|
+
options.fetch(:year, year),
|
|
64
|
+
options.fetch(:month, month),
|
|
65
|
+
options.fetch(:day, day),
|
|
66
|
+
options.fetch(:hour, hour),
|
|
67
|
+
options.fetch(:min, options[:hour] ? 0 : min),
|
|
68
|
+
options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
|
|
69
|
+
options.fetch(:offset, offset),
|
|
70
|
+
options.fetch(:start, start)
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Uses Date to provide precise Time calculations for years, months, and days.
|
|
75
|
+
# The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
|
|
76
|
+
# <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
|
|
77
|
+
# <tt>:minutes</tt>, <tt>:seconds</tt>.
|
|
78
|
+
#
|
|
79
|
+
# Just like Date#advance, increments are applied in order of time units from
|
|
80
|
+
# largest to smallest. This order can affect the result around the end of a
|
|
81
|
+
# month.
|
|
82
|
+
def advance(options)
|
|
83
|
+
unless options[:weeks].nil?
|
|
84
|
+
options[:weeks], partial_weeks = options[:weeks].divmod(1)
|
|
85
|
+
options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
unless options[:days].nil?
|
|
89
|
+
options[:days], partial_days = options[:days].divmod(1)
|
|
90
|
+
options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
d = to_date.advance(options)
|
|
94
|
+
datetime_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
|
|
95
|
+
seconds_to_advance = \
|
|
96
|
+
options.fetch(:seconds, 0) +
|
|
97
|
+
options.fetch(:minutes, 0) * 60 +
|
|
98
|
+
options.fetch(:hours, 0) * 3600
|
|
99
|
+
|
|
100
|
+
if seconds_to_advance.zero?
|
|
101
|
+
datetime_advanced_by_date
|
|
102
|
+
else
|
|
103
|
+
datetime_advanced_by_date.since(seconds_to_advance)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Returns a new DateTime representing the time a number of seconds ago.
|
|
108
|
+
# Do not use this method in combination with x.months, use months_ago instead!
|
|
109
|
+
def ago(seconds)
|
|
110
|
+
since(-seconds)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Returns a new DateTime representing the time a number of seconds since the
|
|
114
|
+
# instance time. Do not use this method in combination with x.months, use
|
|
115
|
+
# months_since instead!
|
|
116
|
+
def since(seconds)
|
|
117
|
+
self + Rational(seconds, 86400)
|
|
118
|
+
end
|
|
119
|
+
alias :in :since
|
|
120
|
+
|
|
121
|
+
# Returns a new DateTime representing the start of the day (0:00).
|
|
122
|
+
def beginning_of_day
|
|
123
|
+
change(hour: 0)
|
|
124
|
+
end
|
|
125
|
+
alias :midnight :beginning_of_day
|
|
126
|
+
alias :at_midnight :beginning_of_day
|
|
127
|
+
alias :at_beginning_of_day :beginning_of_day
|
|
128
|
+
|
|
129
|
+
# Returns a new DateTime representing the middle of the day (12:00)
|
|
130
|
+
def middle_of_day
|
|
131
|
+
change(hour: 12)
|
|
132
|
+
end
|
|
133
|
+
alias :midday :middle_of_day
|
|
134
|
+
alias :noon :middle_of_day
|
|
135
|
+
alias :at_midday :middle_of_day
|
|
136
|
+
alias :at_noon :middle_of_day
|
|
137
|
+
alias :at_middle_of_day :middle_of_day
|
|
138
|
+
|
|
139
|
+
# Returns a new DateTime representing the end of the day (23:59:59).
|
|
140
|
+
def end_of_day
|
|
141
|
+
change(hour: 23, min: 59, sec: 59, usec: Rational(999999999, 1000))
|
|
142
|
+
end
|
|
143
|
+
alias :at_end_of_day :end_of_day
|
|
144
|
+
|
|
145
|
+
# Returns a new DateTime representing the start of the hour (hh:00:00).
|
|
146
|
+
def beginning_of_hour
|
|
147
|
+
change(min: 0)
|
|
148
|
+
end
|
|
149
|
+
alias :at_beginning_of_hour :beginning_of_hour
|
|
150
|
+
|
|
151
|
+
# Returns a new DateTime representing the end of the hour (hh:59:59).
|
|
152
|
+
def end_of_hour
|
|
153
|
+
change(min: 59, sec: 59, usec: Rational(999999999, 1000))
|
|
154
|
+
end
|
|
155
|
+
alias :at_end_of_hour :end_of_hour
|
|
156
|
+
|
|
157
|
+
# Returns a new DateTime representing the start of the minute (hh:mm:00).
|
|
158
|
+
def beginning_of_minute
|
|
159
|
+
change(sec: 0)
|
|
160
|
+
end
|
|
161
|
+
alias :at_beginning_of_minute :beginning_of_minute
|
|
162
|
+
|
|
163
|
+
# Returns a new DateTime representing the end of the minute (hh:mm:59).
|
|
164
|
+
def end_of_minute
|
|
165
|
+
change(sec: 59, usec: Rational(999999999, 1000))
|
|
166
|
+
end
|
|
167
|
+
alias :at_end_of_minute :end_of_minute
|
|
168
|
+
|
|
169
|
+
# Returns a <tt>Time</tt> instance of the simultaneous time in the system timezone.
|
|
170
|
+
def localtime(utc_offset = nil)
|
|
171
|
+
utc = new_offset(0)
|
|
172
|
+
|
|
173
|
+
Time.utc(
|
|
174
|
+
utc.year, utc.month, utc.day,
|
|
175
|
+
utc.hour, utc.min, utc.sec + utc.sec_fraction
|
|
176
|
+
).getlocal(utc_offset)
|
|
177
|
+
end
|
|
178
|
+
alias_method :getlocal, :localtime
|
|
179
|
+
|
|
180
|
+
# Returns a <tt>Time</tt> instance of the simultaneous time in the UTC timezone.
|
|
181
|
+
#
|
|
182
|
+
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)) # => Mon, 21 Feb 2005 10:11:12 -0600
|
|
183
|
+
# DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
|
|
184
|
+
def utc
|
|
185
|
+
utc = new_offset(0)
|
|
186
|
+
|
|
187
|
+
Time.utc(
|
|
188
|
+
utc.year, utc.month, utc.day,
|
|
189
|
+
utc.hour, utc.min, utc.sec + utc.sec_fraction
|
|
190
|
+
)
|
|
191
|
+
end
|
|
192
|
+
alias_method :getgm, :utc
|
|
193
|
+
alias_method :getutc, :utc
|
|
194
|
+
alias_method :gmtime, :utc
|
|
195
|
+
|
|
196
|
+
# Returns +true+ if <tt>offset == 0</tt>.
|
|
197
|
+
def utc?
|
|
198
|
+
offset == 0
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Returns the offset value in seconds.
|
|
202
|
+
def utc_offset
|
|
203
|
+
(offset * 86400).to_i
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Layers additional behavior on DateTime#<=> so that Time and
|
|
207
|
+
# ActiveSupport::TimeWithZone instances can be compared with a DateTime.
|
|
208
|
+
def <=>(other)
|
|
209
|
+
if other.respond_to? :to_datetime
|
|
210
|
+
super other.to_datetime rescue nil
|
|
211
|
+
else
|
|
212
|
+
super
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/date_and_time/compatibility"
|
|
4
|
+
require "active_support/core_ext/module/redefine_method"
|
|
5
|
+
|
|
6
|
+
class DateTime
|
|
7
|
+
include DateAndTime::Compatibility
|
|
8
|
+
|
|
9
|
+
silence_redefinition_of_method :to_time
|
|
10
|
+
|
|
11
|
+
# Return an instance of +Time+ with the same UTC offset
|
|
12
|
+
# as +self+.
|
|
13
|
+
def to_time
|
|
14
|
+
getlocal(utc_offset)
|
|
15
|
+
end
|
|
16
|
+
end
|