omg-activesupport 8.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +86 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +40 -0
  5. data/lib/active_support/actionable_error.rb +50 -0
  6. data/lib/active_support/all.rb +5 -0
  7. data/lib/active_support/array_inquirer.rb +50 -0
  8. data/lib/active_support/backtrace_cleaner.rb +163 -0
  9. data/lib/active_support/benchmark.rb +21 -0
  10. data/lib/active_support/benchmarkable.rb +53 -0
  11. data/lib/active_support/broadcast_logger.rb +251 -0
  12. data/lib/active_support/builder.rb +8 -0
  13. data/lib/active_support/cache/coder.rb +153 -0
  14. data/lib/active_support/cache/entry.rb +134 -0
  15. data/lib/active_support/cache/file_store.rb +244 -0
  16. data/lib/active_support/cache/mem_cache_store.rb +290 -0
  17. data/lib/active_support/cache/memory_store.rb +262 -0
  18. data/lib/active_support/cache/null_store.rb +62 -0
  19. data/lib/active_support/cache/redis_cache_store.rb +492 -0
  20. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  21. data/lib/active_support/cache/strategy/local_cache.rb +201 -0
  22. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  23. data/lib/active_support/cache.rb +1104 -0
  24. data/lib/active_support/callbacks.rb +944 -0
  25. data/lib/active_support/class_attribute.rb +26 -0
  26. data/lib/active_support/code_generator.rb +79 -0
  27. data/lib/active_support/concern.rb +217 -0
  28. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +72 -0
  29. data/lib/active_support/concurrency/null_lock.rb +13 -0
  30. data/lib/active_support/concurrency/share_lock.rb +225 -0
  31. data/lib/active_support/configurable.rb +159 -0
  32. data/lib/active_support/configuration_file.rb +60 -0
  33. data/lib/active_support/core_ext/array/access.rb +100 -0
  34. data/lib/active_support/core_ext/array/conversions.rb +213 -0
  35. data/lib/active_support/core_ext/array/extract.rb +21 -0
  36. data/lib/active_support/core_ext/array/extract_options.rb +31 -0
  37. data/lib/active_support/core_ext/array/grouping.rb +109 -0
  38. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  39. data/lib/active_support/core_ext/array/wrap.rb +48 -0
  40. data/lib/active_support/core_ext/array.rb +9 -0
  41. data/lib/active_support/core_ext/benchmark.rb +13 -0
  42. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  43. data/lib/active_support/core_ext/big_decimal.rb +3 -0
  44. data/lib/active_support/core_ext/class/attribute.rb +122 -0
  45. data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
  46. data/lib/active_support/core_ext/class/subclasses.rb +24 -0
  47. data/lib/active_support/core_ext/class.rb +4 -0
  48. data/lib/active_support/core_ext/date/acts_like.rb +10 -0
  49. data/lib/active_support/core_ext/date/blank.rb +18 -0
  50. data/lib/active_support/core_ext/date/calculations.rb +161 -0
  51. data/lib/active_support/core_ext/date/conversions.rb +98 -0
  52. data/lib/active_support/core_ext/date/zones.rb +8 -0
  53. data/lib/active_support/core_ext/date.rb +7 -0
  54. data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
  55. data/lib/active_support/core_ext/date_and_time/compatibility.rb +58 -0
  56. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  57. data/lib/active_support/core_ext/date_time/acts_like.rb +16 -0
  58. data/lib/active_support/core_ext/date_time/blank.rb +18 -0
  59. data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
  60. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  61. data/lib/active_support/core_ext/date_time/conversions.rb +106 -0
  62. data/lib/active_support/core_ext/date_time.rb +7 -0
  63. data/lib/active_support/core_ext/digest/uuid.rb +76 -0
  64. data/lib/active_support/core_ext/digest.rb +3 -0
  65. data/lib/active_support/core_ext/enumerable.rb +267 -0
  66. data/lib/active_support/core_ext/erb/util.rb +201 -0
  67. data/lib/active_support/core_ext/file/atomic.rb +72 -0
  68. data/lib/active_support/core_ext/file.rb +3 -0
  69. data/lib/active_support/core_ext/hash/conversions.rb +262 -0
  70. data/lib/active_support/core_ext/hash/deep_merge.rb +42 -0
  71. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  72. data/lib/active_support/core_ext/hash/except.rb +12 -0
  73. data/lib/active_support/core_ext/hash/indifferent_access.rb +24 -0
  74. data/lib/active_support/core_ext/hash/keys.rb +143 -0
  75. data/lib/active_support/core_ext/hash/reverse_merge.rb +25 -0
  76. data/lib/active_support/core_ext/hash/slice.rb +27 -0
  77. data/lib/active_support/core_ext/hash.rb +10 -0
  78. data/lib/active_support/core_ext/integer/inflections.rb +31 -0
  79. data/lib/active_support/core_ext/integer/multiple.rb +12 -0
  80. data/lib/active_support/core_ext/integer/time.rb +22 -0
  81. data/lib/active_support/core_ext/integer.rb +5 -0
  82. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  83. data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
  84. data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
  85. data/lib/active_support/core_ext/kernel.rb +5 -0
  86. data/lib/active_support/core_ext/load_error.rb +9 -0
  87. data/lib/active_support/core_ext/module/aliasing.rb +31 -0
  88. data/lib/active_support/core_ext/module/anonymous.rb +30 -0
  89. data/lib/active_support/core_ext/module/attr_internal.rb +49 -0
  90. data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
  91. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
  92. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  93. data/lib/active_support/core_ext/module/delegation.rb +225 -0
  94. data/lib/active_support/core_ext/module/deprecation.rb +25 -0
  95. data/lib/active_support/core_ext/module/introspection.rb +62 -0
  96. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  97. data/lib/active_support/core_ext/module/remove_method.rb +17 -0
  98. data/lib/active_support/core_ext/module.rb +13 -0
  99. data/lib/active_support/core_ext/name_error.rb +59 -0
  100. data/lib/active_support/core_ext/numeric/bytes.rb +75 -0
  101. data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
  102. data/lib/active_support/core_ext/numeric/time.rb +66 -0
  103. data/lib/active_support/core_ext/numeric.rb +5 -0
  104. data/lib/active_support/core_ext/object/acts_like.rb +45 -0
  105. data/lib/active_support/core_ext/object/blank.rb +199 -0
  106. data/lib/active_support/core_ext/object/conversions.rb +6 -0
  107. data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
  108. data/lib/active_support/core_ext/object/duplicable.rb +69 -0
  109. data/lib/active_support/core_ext/object/inclusion.rb +37 -0
  110. data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
  111. data/lib/active_support/core_ext/object/json.rb +260 -0
  112. data/lib/active_support/core_ext/object/to_param.rb +3 -0
  113. data/lib/active_support/core_ext/object/to_query.rb +87 -0
  114. data/lib/active_support/core_ext/object/try.rb +158 -0
  115. data/lib/active_support/core_ext/object/with.rb +46 -0
  116. data/lib/active_support/core_ext/object/with_options.rb +101 -0
  117. data/lib/active_support/core_ext/object.rb +17 -0
  118. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  119. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  120. data/lib/active_support/core_ext/pathname.rb +4 -0
  121. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  122. data/lib/active_support/core_ext/range/conversions.rb +62 -0
  123. data/lib/active_support/core_ext/range/each.rb +24 -0
  124. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  125. data/lib/active_support/core_ext/range.rb +6 -0
  126. data/lib/active_support/core_ext/regexp.rb +14 -0
  127. data/lib/active_support/core_ext/securerandom.rb +41 -0
  128. data/lib/active_support/core_ext/string/access.rb +95 -0
  129. data/lib/active_support/core_ext/string/behavior.rb +8 -0
  130. data/lib/active_support/core_ext/string/conversions.rb +60 -0
  131. data/lib/active_support/core_ext/string/exclude.rb +13 -0
  132. data/lib/active_support/core_ext/string/filters.rb +151 -0
  133. data/lib/active_support/core_ext/string/indent.rb +45 -0
  134. data/lib/active_support/core_ext/string/inflections.rb +300 -0
  135. data/lib/active_support/core_ext/string/inquiry.rb +16 -0
  136. data/lib/active_support/core_ext/string/multibyte.rb +58 -0
  137. data/lib/active_support/core_ext/string/output_safety.rb +228 -0
  138. data/lib/active_support/core_ext/string/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/string/strip.rb +27 -0
  140. data/lib/active_support/core_ext/string/zones.rb +16 -0
  141. data/lib/active_support/core_ext/string.rb +15 -0
  142. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  143. data/lib/active_support/core_ext/symbol.rb +3 -0
  144. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  145. data/lib/active_support/core_ext/time/acts_like.rb +10 -0
  146. data/lib/active_support/core_ext/time/calculations.rb +386 -0
  147. data/lib/active_support/core_ext/time/compatibility.rb +32 -0
  148. data/lib/active_support/core_ext/time/conversions.rb +75 -0
  149. data/lib/active_support/core_ext/time/zones.rb +97 -0
  150. data/lib/active_support/core_ext/time.rb +7 -0
  151. data/lib/active_support/core_ext.rb +5 -0
  152. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  153. data/lib/active_support/current_attributes.rb +233 -0
  154. data/lib/active_support/deep_mergeable.rb +53 -0
  155. data/lib/active_support/delegation.rb +202 -0
  156. data/lib/active_support/dependencies/autoload.rb +72 -0
  157. data/lib/active_support/dependencies/interlock.rb +49 -0
  158. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  159. data/lib/active_support/dependencies.rb +98 -0
  160. data/lib/active_support/deprecation/behaviors.rb +148 -0
  161. data/lib/active_support/deprecation/constant_accessor.rb +74 -0
  162. data/lib/active_support/deprecation/deprecators.rb +104 -0
  163. data/lib/active_support/deprecation/disallowed.rb +54 -0
  164. data/lib/active_support/deprecation/method_wrappers.rb +68 -0
  165. data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
  166. data/lib/active_support/deprecation/reporting.rb +179 -0
  167. data/lib/active_support/deprecation.rb +81 -0
  168. data/lib/active_support/deprecator.rb +7 -0
  169. data/lib/active_support/descendants_tracker.rb +112 -0
  170. data/lib/active_support/digest.rb +22 -0
  171. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  172. data/lib/active_support/duration/iso8601_serializer.rb +64 -0
  173. data/lib/active_support/duration.rb +520 -0
  174. data/lib/active_support/encrypted_configuration.rb +126 -0
  175. data/lib/active_support/encrypted_file.rb +133 -0
  176. data/lib/active_support/environment_inquirer.rb +40 -0
  177. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  178. data/lib/active_support/error_reporter.rb +265 -0
  179. data/lib/active_support/evented_file_update_checker.rb +182 -0
  180. data/lib/active_support/execution_context/test_helper.rb +13 -0
  181. data/lib/active_support/execution_context.rb +53 -0
  182. data/lib/active_support/execution_wrapper.rb +150 -0
  183. data/lib/active_support/executor/test_helper.rb +7 -0
  184. data/lib/active_support/executor.rb +8 -0
  185. data/lib/active_support/file_update_checker.rb +164 -0
  186. data/lib/active_support/fork_tracker.rb +43 -0
  187. data/lib/active_support/gem_version.rb +17 -0
  188. data/lib/active_support/gzip.rb +40 -0
  189. data/lib/active_support/hash_with_indifferent_access.rb +445 -0
  190. data/lib/active_support/html_safe_translation.rb +56 -0
  191. data/lib/active_support/i18n.rb +17 -0
  192. data/lib/active_support/i18n_railtie.rb +138 -0
  193. data/lib/active_support/inflections.rb +72 -0
  194. data/lib/active_support/inflector/inflections.rb +273 -0
  195. data/lib/active_support/inflector/methods.rb +387 -0
  196. data/lib/active_support/inflector/transliterate.rb +149 -0
  197. data/lib/active_support/inflector.rb +9 -0
  198. data/lib/active_support/isolated_execution_state.rb +75 -0
  199. data/lib/active_support/json/decoding.rb +76 -0
  200. data/lib/active_support/json/encoding.rb +120 -0
  201. data/lib/active_support/json.rb +4 -0
  202. data/lib/active_support/key_generator.rb +66 -0
  203. data/lib/active_support/lazy_load_hooks.rb +107 -0
  204. data/lib/active_support/locale/en.rb +33 -0
  205. data/lib/active_support/locale/en.yml +141 -0
  206. data/lib/active_support/log_subscriber/test_helper.rb +106 -0
  207. data/lib/active_support/log_subscriber.rb +192 -0
  208. data/lib/active_support/logger.rb +55 -0
  209. data/lib/active_support/logger_silence.rb +21 -0
  210. data/lib/active_support/logger_thread_safe_level.rb +47 -0
  211. data/lib/active_support/message_encryptor.rb +374 -0
  212. data/lib/active_support/message_encryptors.rb +141 -0
  213. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  214. data/lib/active_support/message_pack/extensions.rb +305 -0
  215. data/lib/active_support/message_pack/serializer.rb +63 -0
  216. data/lib/active_support/message_pack.rb +50 -0
  217. data/lib/active_support/message_verifier.rb +368 -0
  218. data/lib/active_support/message_verifiers.rb +135 -0
  219. data/lib/active_support/messages/codec.rb +65 -0
  220. data/lib/active_support/messages/metadata.rb +146 -0
  221. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  222. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  223. data/lib/active_support/messages/rotator.rb +59 -0
  224. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  225. data/lib/active_support/multibyte/chars.rb +178 -0
  226. data/lib/active_support/multibyte/unicode.rb +42 -0
  227. data/lib/active_support/multibyte.rb +23 -0
  228. data/lib/active_support/notifications/fanout.rb +446 -0
  229. data/lib/active_support/notifications/instrumenter.rb +240 -0
  230. data/lib/active_support/notifications.rb +281 -0
  231. data/lib/active_support/number_helper/number_converter.rb +190 -0
  232. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  233. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  234. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  235. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  236. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  237. data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
  238. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  239. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  240. data/lib/active_support/number_helper.rb +479 -0
  241. data/lib/active_support/option_merger.rb +38 -0
  242. data/lib/active_support/ordered_hash.rb +50 -0
  243. data/lib/active_support/ordered_options.rb +147 -0
  244. data/lib/active_support/parameter_filter.rb +157 -0
  245. data/lib/active_support/proxy_object.rb +20 -0
  246. data/lib/active_support/rails.rb +26 -0
  247. data/lib/active_support/railtie.rb +161 -0
  248. data/lib/active_support/reloader.rb +138 -0
  249. data/lib/active_support/rescuable.rb +176 -0
  250. data/lib/active_support/secure_compare_rotator.rb +58 -0
  251. data/lib/active_support/security_utils.rb +38 -0
  252. data/lib/active_support/string_inquirer.rb +35 -0
  253. data/lib/active_support/subscriber.rb +146 -0
  254. data/lib/active_support/syntax_error_proxy.rb +60 -0
  255. data/lib/active_support/tagged_logging.rb +152 -0
  256. data/lib/active_support/test_case.rb +304 -0
  257. data/lib/active_support/testing/assertions.rb +332 -0
  258. data/lib/active_support/testing/autorun.rb +5 -0
  259. data/lib/active_support/testing/constant_lookup.rb +51 -0
  260. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  261. data/lib/active_support/testing/declarative.rb +28 -0
  262. data/lib/active_support/testing/deprecation.rb +82 -0
  263. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  264. data/lib/active_support/testing/file_fixtures.rb +38 -0
  265. data/lib/active_support/testing/isolation.rb +121 -0
  266. data/lib/active_support/testing/method_call_assertions.rb +69 -0
  267. data/lib/active_support/testing/parallelization/server.rb +85 -0
  268. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  269. data/lib/active_support/testing/parallelization.rb +55 -0
  270. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  271. data/lib/active_support/testing/setup_and_teardown.rb +57 -0
  272. data/lib/active_support/testing/stream.rb +41 -0
  273. data/lib/active_support/testing/strict_warnings.rb +43 -0
  274. data/lib/active_support/testing/tagged_logging.rb +27 -0
  275. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  276. data/lib/active_support/testing/time_helpers.rb +269 -0
  277. data/lib/active_support/time.rb +20 -0
  278. data/lib/active_support/time_with_zone.rb +609 -0
  279. data/lib/active_support/values/time_zone.rb +614 -0
  280. data/lib/active_support/version.rb +10 -0
  281. data/lib/active_support/xml_mini/jdom.rb +175 -0
  282. data/lib/active_support/xml_mini/libxml.rb +80 -0
  283. data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
  284. data/lib/active_support/xml_mini/nokogiri.rb +83 -0
  285. data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
  286. data/lib/active_support/xml_mini/rexml.rb +137 -0
  287. data/lib/active_support/xml_mini.rb +211 -0
  288. data/lib/active_support.rb +144 -0
  289. metadata +526 -0
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Thread::Backtrace::Location # :nodoc:
4
+ if defined?(ErrorHighlight) && Gem::Version.new(ErrorHighlight::VERSION) >= Gem::Version.new("0.4.0")
5
+ def spot(ex)
6
+ ErrorHighlight.spot(ex, backtrace_location: self)
7
+ end
8
+ else
9
+ def spot(ex)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/acts_like"
4
+
5
+ class Time
6
+ # Duck-types as a Time-like class. See Object#acts_like?.
7
+ def acts_like_time?
8
+ true
9
+ end
10
+ end
@@ -0,0 +1,386 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/duration"
4
+ require "active_support/core_ext/time/conversions"
5
+ require "active_support/time_with_zone"
6
+ require "active_support/core_ext/time/zones"
7
+ require "active_support/core_ext/date_and_time/calculations"
8
+ require "active_support/core_ext/date/calculations"
9
+ require "active_support/core_ext/module/remove_method"
10
+
11
+ class Time
12
+ include DateAndTime::Calculations
13
+
14
+ COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
15
+
16
+ class << self
17
+ # Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances
18
+ def ===(other)
19
+ super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
20
+ end
21
+
22
+ # Returns the number of days in the given month.
23
+ # If no year is specified, it will use the current year.
24
+ def days_in_month(month, year = current.year)
25
+ if month == 2 && ::Date.gregorian_leap?(year)
26
+ 29
27
+ else
28
+ COMMON_YEAR_DAYS_IN_MONTH[month]
29
+ end
30
+ end
31
+
32
+ # Returns the number of days in the given year.
33
+ # If no year is specified, it will use the current year.
34
+ def days_in_year(year = current.year)
35
+ days_in_month(2, year) + 337
36
+ end
37
+
38
+ # Returns <tt>Time.zone.now</tt> when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns <tt>Time.now</tt>.
39
+ def current
40
+ ::Time.zone ? ::Time.zone.now : ::Time.now
41
+ end
42
+
43
+ # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
44
+ # instances can be used when called with a single argument
45
+ def at_with_coercion(time_or_number, *args)
46
+ if args.empty?
47
+ if time_or_number.is_a?(ActiveSupport::TimeWithZone)
48
+ at_without_coercion(time_or_number.to_r).getlocal
49
+ elsif time_or_number.is_a?(DateTime)
50
+ at_without_coercion(time_or_number.to_f).getlocal
51
+ else
52
+ at_without_coercion(time_or_number)
53
+ end
54
+ else
55
+ at_without_coercion(time_or_number, *args)
56
+ end
57
+ end
58
+ ruby2_keywords :at_with_coercion
59
+ alias_method :at_without_coercion, :at
60
+ alias_method :at, :at_with_coercion
61
+
62
+ # Creates a +Time+ instance from an RFC 3339 string.
63
+ #
64
+ # Time.rfc3339('1999-12-31T14:00:00-10:00') # => 2000-01-01 00:00:00 -1000
65
+ #
66
+ # If the time or offset components are missing then an +ArgumentError+ will be raised.
67
+ #
68
+ # Time.rfc3339('1999-12-31') # => ArgumentError: invalid date
69
+ def rfc3339(str)
70
+ parts = Date._rfc3339(str)
71
+
72
+ raise ArgumentError, "invalid date" if parts.empty?
73
+
74
+ Time.new(
75
+ parts.fetch(:year),
76
+ parts.fetch(:mon),
77
+ parts.fetch(:mday),
78
+ parts.fetch(:hour),
79
+ parts.fetch(:min),
80
+ parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
81
+ parts.fetch(:offset)
82
+ )
83
+ end
84
+ end
85
+
86
+ # Returns the number of seconds since 00:00:00.
87
+ #
88
+ # Time.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0.0
89
+ # Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0
90
+ # Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0
91
+ def seconds_since_midnight
92
+ to_i - change(hour: 0).to_i + (usec / 1.0e+6)
93
+ end
94
+
95
+ # Returns the number of seconds until 23:59:59.
96
+ #
97
+ # Time.new(2012, 8, 29, 0, 0, 0).seconds_until_end_of_day # => 86399
98
+ # Time.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
99
+ # Time.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
100
+ def seconds_until_end_of_day
101
+ end_of_day.to_i - to_i
102
+ end
103
+
104
+ # Returns the fraction of a second as a +Rational+
105
+ #
106
+ # Time.new(2012, 8, 29, 0, 0, 0.5).sec_fraction # => (1/2)
107
+ def sec_fraction
108
+ subsec
109
+ end
110
+
111
+ # Returns a new Time where one or more of the elements have been changed according
112
+ # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
113
+ # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
114
+ # the hour is passed, then minute, sec, usec, and nsec is set to 0. If the hour
115
+ # and minute is passed, then sec, usec, and nsec is set to 0. The +options+ parameter
116
+ # takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
117
+ # <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
118
+ # <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
119
+ #
120
+ # Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
121
+ # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
122
+ # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
123
+ def change(options)
124
+ new_year = options.fetch(:year, year)
125
+ new_month = options.fetch(:month, month)
126
+ new_day = options.fetch(:day, day)
127
+ new_hour = options.fetch(:hour, hour)
128
+ new_min = options.fetch(:min, options[:hour] ? 0 : min)
129
+ new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
130
+ new_offset = options.fetch(:offset, nil)
131
+
132
+ if new_nsec = options[:nsec]
133
+ raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
134
+ new_usec = Rational(new_nsec, 1000)
135
+ else
136
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
137
+ end
138
+
139
+ raise ArgumentError, "argument out of range" if new_usec >= 1000000
140
+
141
+ new_sec += Rational(new_usec, 1000000)
142
+
143
+ if new_offset
144
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
145
+ elsif utc?
146
+ ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
147
+ elsif zone.respond_to?(:utc_to_local)
148
+ new_time = ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
149
+
150
+ # Some versions of Ruby have a bug where Time.new with a zone object and
151
+ # fractional seconds will end up with a broken utc_offset.
152
+ # This is fixed in Ruby 3.3.1 and 3.2.4
153
+ unless new_time.utc_offset.integer?
154
+ new_time += 0
155
+ end
156
+
157
+ # When there are two occurrences of a nominal time due to DST ending,
158
+ # `Time.new` chooses the first chronological occurrence (the one with a
159
+ # larger UTC offset). However, for `change`, we want to choose the
160
+ # occurrence that matches this time's UTC offset.
161
+ #
162
+ # If the new time's UTC offset is larger than this time's UTC offset, the
163
+ # new time might be a first chronological occurrence. So we add the offset
164
+ # difference to fast-forward the new time, and check if the result has the
165
+ # desired UTC offset (i.e. is the second chronological occurrence).
166
+ offset_difference = new_time.utc_offset - utc_offset
167
+ if offset_difference > 0 && (new_time_2 = new_time + offset_difference).utc_offset == utc_offset
168
+ new_time_2
169
+ else
170
+ new_time
171
+ end
172
+ elsif zone
173
+ ::Time.local(new_sec, new_min, new_hour, new_day, new_month, new_year, nil, nil, isdst, nil)
174
+ else
175
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
176
+ end
177
+ end
178
+
179
+ # Uses Date to provide precise Time calculations for years, months, and days
180
+ # according to the proleptic Gregorian calendar. The +options+ parameter
181
+ # takes a hash with any of these keys: <tt>:years</tt>, <tt>:months</tt>,
182
+ # <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>, <tt>:minutes</tt>,
183
+ # <tt>:seconds</tt>.
184
+ #
185
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(seconds: 1) # => 2015-08-01 14:35:01 -0700
186
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(minutes: 1) # => 2015-08-01 14:36:00 -0700
187
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1) # => 2015-08-01 15:35:00 -0700
188
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1) # => 2015-08-02 14:35:00 -0700
189
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1) # => 2015-08-08 14:35:00 -0700
190
+ #
191
+ # Just like Date#advance, increments are applied in order of time units from
192
+ # largest to smallest. This order can affect the result around the end of a
193
+ # month.
194
+ def advance(options)
195
+ unless options[:weeks].nil?
196
+ options[:weeks], partial_weeks = options[:weeks].divmod(1)
197
+ options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
198
+ end
199
+
200
+ unless options[:days].nil?
201
+ options[:days], partial_days = options[:days].divmod(1)
202
+ options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
203
+ end
204
+
205
+ d = to_date.gregorian.advance(options)
206
+ time_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
207
+ seconds_to_advance = \
208
+ options.fetch(:seconds, 0) +
209
+ options.fetch(:minutes, 0) * 60 +
210
+ options.fetch(:hours, 0) * 3600
211
+
212
+ if seconds_to_advance.zero?
213
+ time_advanced_by_date
214
+ else
215
+ time_advanced_by_date.since(seconds_to_advance)
216
+ end
217
+ end
218
+
219
+ # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
220
+ def ago(seconds)
221
+ since(-seconds)
222
+ end
223
+
224
+ # Returns a new Time representing the time a number of seconds since the instance time
225
+ def since(seconds)
226
+ self + seconds
227
+ rescue TypeError
228
+ result = to_datetime.since(seconds)
229
+ ActiveSupport.deprecator.warn(
230
+ "Passing an instance of #{seconds.class} to #{self.class}#since is deprecated. This behavior will raise " \
231
+ "a `TypeError` in Rails 8.1."
232
+ )
233
+ result
234
+ end
235
+ alias :in :since
236
+
237
+ # Returns a new Time representing the start of the day (0:00)
238
+ def beginning_of_day
239
+ change(hour: 0)
240
+ end
241
+ alias :midnight :beginning_of_day
242
+ alias :at_midnight :beginning_of_day
243
+ alias :at_beginning_of_day :beginning_of_day
244
+
245
+ # Returns a new Time representing the middle of the day (12:00)
246
+ def middle_of_day
247
+ change(hour: 12)
248
+ end
249
+ alias :midday :middle_of_day
250
+ alias :noon :middle_of_day
251
+ alias :at_midday :middle_of_day
252
+ alias :at_noon :middle_of_day
253
+ alias :at_middle_of_day :middle_of_day
254
+
255
+ # Returns a new Time representing the end of the day, 23:59:59.999999
256
+ def end_of_day
257
+ change(
258
+ hour: 23,
259
+ min: 59,
260
+ sec: 59,
261
+ usec: Rational(999999999, 1000)
262
+ )
263
+ end
264
+ alias :at_end_of_day :end_of_day
265
+
266
+ # Returns a new Time representing the start of the hour (x:00)
267
+ def beginning_of_hour
268
+ change(min: 0)
269
+ end
270
+ alias :at_beginning_of_hour :beginning_of_hour
271
+
272
+ # Returns a new Time representing the end of the hour, x:59:59.999999
273
+ def end_of_hour
274
+ change(
275
+ min: 59,
276
+ sec: 59,
277
+ usec: Rational(999999999, 1000)
278
+ )
279
+ end
280
+ alias :at_end_of_hour :end_of_hour
281
+
282
+ # Returns a new Time representing the start of the minute (x:xx:00)
283
+ def beginning_of_minute
284
+ change(sec: 0)
285
+ end
286
+ alias :at_beginning_of_minute :beginning_of_minute
287
+
288
+ # Returns a new Time representing the end of the minute, x:xx:59.999999
289
+ def end_of_minute
290
+ change(
291
+ sec: 59,
292
+ usec: Rational(999999999, 1000)
293
+ )
294
+ end
295
+ alias :at_end_of_minute :end_of_minute
296
+
297
+ def plus_with_duration(other) # :nodoc:
298
+ if ActiveSupport::Duration === other
299
+ other.since(self)
300
+ else
301
+ plus_without_duration(other)
302
+ end
303
+ end
304
+ alias_method :plus_without_duration, :+
305
+ alias_method :+, :plus_with_duration
306
+
307
+ def minus_with_duration(other) # :nodoc:
308
+ if ActiveSupport::Duration === other
309
+ other.until(self)
310
+ else
311
+ minus_without_duration(other)
312
+ end
313
+ end
314
+ alias_method :minus_without_duration, :-
315
+ alias_method :-, :minus_with_duration
316
+
317
+ # Time#- can also be used to determine the number of seconds between two Time instances.
318
+ # We're layering on additional behavior so that ActiveSupport::TimeWithZone instances
319
+ # are coerced into values that Time#- will recognize
320
+ def minus_with_coercion(other)
321
+ other = other.comparable_time if other.respond_to?(:comparable_time)
322
+ other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
323
+ end
324
+ alias_method :minus_without_coercion, :-
325
+ alias_method :-, :minus_with_coercion # rubocop:disable Lint/DuplicateMethods
326
+
327
+ # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
328
+ # can be chronologically compared with a Time
329
+ def compare_with_coercion(other)
330
+ # we're avoiding Time#to_datetime and Time#to_time because they're expensive
331
+ if other.class == Time
332
+ compare_without_coercion(other)
333
+ elsif other.is_a?(Time)
334
+ # also avoid ActiveSupport::TimeWithZone#to_time before Rails 8.0
335
+ if other.respond_to?(:comparable_time)
336
+ compare_without_coercion(other.comparable_time)
337
+ else
338
+ compare_without_coercion(other.to_time)
339
+ end
340
+ else
341
+ to_datetime <=> other
342
+ end
343
+ end
344
+ alias_method :compare_without_coercion, :<=>
345
+ alias_method :<=>, :compare_with_coercion
346
+
347
+ # Layers additional behavior on Time#eql? so that ActiveSupport::TimeWithZone instances
348
+ # can be eql? to an equivalent Time
349
+ def eql_with_coercion(other)
350
+ # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison
351
+ other = other.comparable_time if other.respond_to?(:comparable_time)
352
+ eql_without_coercion(other)
353
+ end
354
+ alias_method :eql_without_coercion, :eql?
355
+ alias_method :eql?, :eql_with_coercion
356
+
357
+ # Returns a new time the specified number of days ago.
358
+ def prev_day(days = 1)
359
+ advance(days: -days)
360
+ end
361
+
362
+ # Returns a new time the specified number of days in the future.
363
+ def next_day(days = 1)
364
+ advance(days: days)
365
+ end
366
+
367
+ # Returns a new time the specified number of months ago.
368
+ def prev_month(months = 1)
369
+ advance(months: -months)
370
+ end
371
+
372
+ # Returns a new time the specified number of months in the future.
373
+ def next_month(months = 1)
374
+ advance(months: months)
375
+ end
376
+
377
+ # Returns a new time the specified number of years ago.
378
+ def prev_year(years = 1)
379
+ advance(years: -years)
380
+ end
381
+
382
+ # Returns a new time the specified number of years in the future.
383
+ def next_year(years = 1)
384
+ advance(years: years)
385
+ end
386
+ end
@@ -0,0 +1,32 @@
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 Time
7
+ include DateAndTime::Compatibility
8
+
9
+ silence_redefinition_of_method :to_time
10
+
11
+ # Either return +self+ or the time in the local system timezone depending
12
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
13
+ def to_time
14
+ preserve_timezone ? self : getlocal
15
+ end
16
+
17
+ def preserve_timezone # :nodoc:
18
+ active_support_local_zone == zone || super
19
+ end
20
+
21
+ private
22
+ @@active_support_local_tz = nil
23
+
24
+ def active_support_local_zone
25
+ @@active_support_local_zone = nil if @@active_support_local_tz != ENV["TZ"]
26
+ @@active_support_local_zone ||=
27
+ begin
28
+ @@active_support_local_tz = ENV["TZ"]
29
+ Time.new.zone
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+ require "active_support/inflector/methods"
5
+ require "active_support/values/time_zone"
6
+
7
+ class Time
8
+ DATE_FORMATS = {
9
+ db: "%Y-%m-%d %H:%M:%S",
10
+ inspect: "%Y-%m-%d %H:%M:%S.%9N %z",
11
+ number: "%Y%m%d%H%M%S",
12
+ nsec: "%Y%m%d%H%M%S%9N",
13
+ usec: "%Y%m%d%H%M%S%6N",
14
+ time: "%H:%M",
15
+ short: "%d %b %H:%M",
16
+ long: "%B %d, %Y %H:%M",
17
+ long_ordinal: lambda { |time|
18
+ day_format = ActiveSupport::Inflector.ordinalize(time.day)
19
+ time.strftime("%B #{day_format}, %Y %H:%M")
20
+ },
21
+ rfc822: lambda { |time|
22
+ offset_format = time.formatted_offset(false)
23
+ time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
24
+ },
25
+ rfc2822: lambda { |time| time.rfc2822 },
26
+ iso8601: lambda { |time| time.iso8601 }
27
+ }
28
+
29
+ # Converts to a formatted string. See DATE_FORMATS for built-in formats.
30
+ #
31
+ # This method is aliased to <tt>to_formatted_s</tt>.
32
+ #
33
+ # time = Time.now # => 2007-01-18 06:10:17 -06:00
34
+ #
35
+ # time.to_fs(:time) # => "06:10"
36
+ # time.to_formatted_s(:time) # => "06:10"
37
+ #
38
+ # time.to_fs(:db) # => "2007-01-18 06:10:17"
39
+ # time.to_fs(:number) # => "20070118061017"
40
+ # time.to_fs(:short) # => "18 Jan 06:10"
41
+ # time.to_fs(:long) # => "January 18, 2007 06:10"
42
+ # time.to_fs(:long_ordinal) # => "January 18th, 2007 06:10"
43
+ # time.to_fs(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
44
+ # time.to_fs(:rfc2822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
45
+ # time.to_fs(:iso8601) # => "2007-01-18T06:10:17-06:00"
46
+ #
47
+ # == Adding your own time formats to +to_fs+
48
+ # You can add your own formats to the Time::DATE_FORMATS hash.
49
+ # Use the format name as the hash key and either a strftime string
50
+ # or Proc instance that takes a time argument as the value.
51
+ #
52
+ # # config/initializers/time_formats.rb
53
+ # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
54
+ # Time::DATE_FORMATS[:short_ordinal] = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
55
+ def to_fs(format = :default)
56
+ if formatter = DATE_FORMATS[format]
57
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
58
+ else
59
+ to_s
60
+ end
61
+ end
62
+ alias_method :to_formatted_s, :to_fs
63
+
64
+ # Returns a formatted string of the offset from UTC, or an alternative
65
+ # string if the time zone is already UTC.
66
+ #
67
+ # Time.local(2000).formatted_offset # => "-06:00"
68
+ # Time.local(2000).formatted_offset(false) # => "-0600"
69
+ def formatted_offset(colon = true, alternate_utc_string = nil)
70
+ utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
71
+ end
72
+
73
+ # Aliased to +xmlschema+ for compatibility with +DateTime+
74
+ alias_method :rfc3339, :xmlschema
75
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/time_with_zone"
4
+ require "active_support/core_ext/time/acts_like"
5
+ require "active_support/core_ext/date_and_time/zones"
6
+
7
+ class Time
8
+ include DateAndTime::Zones
9
+ class << self
10
+ attr_accessor :zone_default
11
+
12
+ # Returns the TimeZone for the current request, if this has been set (via Time.zone=).
13
+ # If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
14
+ def zone
15
+ ::ActiveSupport::IsolatedExecutionState[:time_zone] || zone_default
16
+ end
17
+
18
+ # Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
19
+ #
20
+ # This method accepts any of the following:
21
+ #
22
+ # * A \Rails TimeZone object.
23
+ # * An identifier for a \Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
24
+ # * A +TZInfo::Timezone+ object.
25
+ # * An identifier for a +TZInfo::Timezone+ object (e.g., "America/New_York").
26
+ #
27
+ # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis and reset it when the request is done.
28
+ # <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
29
+ #
30
+ # class ApplicationController < ActionController::Base
31
+ # around_action :set_time_zone
32
+ #
33
+ # def set_time_zone
34
+ # if logged_in?
35
+ # Time.use_zone(current_user.time_zone) { yield }
36
+ # else
37
+ # yield
38
+ # end
39
+ # end
40
+ # end
41
+ def zone=(time_zone)
42
+ ::ActiveSupport::IsolatedExecutionState[:time_zone] = find_zone!(time_zone)
43
+ end
44
+
45
+ # Allows override of <tt>Time.zone</tt> locally inside supplied block;
46
+ # resets <tt>Time.zone</tt> to existing value when done.
47
+ #
48
+ # class ApplicationController < ActionController::Base
49
+ # around_action :set_time_zone
50
+ #
51
+ # private
52
+ # def set_time_zone
53
+ # Time.use_zone(current_user.timezone) { yield }
54
+ # end
55
+ # end
56
+ #
57
+ # NOTE: This won't affect any ActiveSupport::TimeWithZone
58
+ # objects that have already been created, e.g. any model timestamp
59
+ # attributes that have been read before the block will remain in
60
+ # the application's default timezone.
61
+ def use_zone(time_zone)
62
+ new_zone = find_zone!(time_zone)
63
+ begin
64
+ old_zone, ::Time.zone = ::Time.zone, new_zone
65
+ yield
66
+ ensure
67
+ ::Time.zone = old_zone
68
+ end
69
+ end
70
+
71
+ # Returns a TimeZone instance matching the time zone provided.
72
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
73
+ # Raises an +ArgumentError+ for invalid time zones.
74
+ #
75
+ # Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
76
+ # Time.find_zone! "EST" # => #<ActiveSupport::TimeZone @name="EST" ...>
77
+ # Time.find_zone! -5.hours # => #<ActiveSupport::TimeZone @name="Bogota" ...>
78
+ # Time.find_zone! nil # => nil
79
+ # Time.find_zone! false # => false
80
+ # Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
81
+ def find_zone!(time_zone)
82
+ return time_zone unless time_zone
83
+
84
+ ActiveSupport::TimeZone[time_zone] || raise(ArgumentError, "Invalid Timezone: #{time_zone}")
85
+ end
86
+
87
+ # Returns a TimeZone instance matching the time zone provided.
88
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
89
+ # Returns +nil+ for invalid time zones.
90
+ #
91
+ # Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
92
+ # Time.find_zone "NOT-A-TIMEZONE" # => nil
93
+ def find_zone(time_zone)
94
+ find_zone!(time_zone) rescue nil
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/acts_like"
4
+ require "active_support/core_ext/time/calculations"
5
+ require "active_support/core_ext/time/compatibility"
6
+ require "active_support/core_ext/time/conversions"
7
+ require "active_support/core_ext/time/zones"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).sort.each do |path|
4
+ require path
5
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport::CurrentAttributes::TestHelper # :nodoc:
4
+ def before_setup
5
+ ActiveSupport::CurrentAttributes.reset_all
6
+ super
7
+ end
8
+
9
+ def after_teardown
10
+ super
11
+ ActiveSupport::CurrentAttributes.reset_all
12
+ end
13
+ end