From 49560be691d55b1f2357c54b8389a2c65882c9f9 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Mon, 28 Aug 2023 12:51:07 +0900 Subject: [PATCH] [Fix #1094] Make `Rails/TimeZone` aware of `String#to_time` Fixes #1094. This PR make `Rails/TimeZone` aware of `String#to_time`. --- ...make_rails_time_zone_aware_of_string_to_time | 1 + lib/rubocop/cop/rails/time_zone.rb | 17 ++++++++++++----- spec/rubocop/cop/rails/time_zone_spec.rb | 13 +++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 changelog/change_make_rails_time_zone_aware_of_string_to_time diff --git a/changelog/change_make_rails_time_zone_aware_of_string_to_time b/changelog/change_make_rails_time_zone_aware_of_string_to_time new file mode 100644 index 0000000000..7837b5fecf --- /dev/null +++ b/changelog/change_make_rails_time_zone_aware_of_string_to_time @@ -0,0 +1 @@ +* [#1094](https://github.com/rubocop/rubocop-rails/issues/1094): Make `Rails/TimeZone` aware of `String#to_time`. ([@koic][]) diff --git a/lib/rubocop/cop/rails/time_zone.rb b/lib/rubocop/cop/rails/time_zone.rb index 75a58e9440..1ad9768e3d 100644 --- a/lib/rubocop/cop/rails/time_zone.rb +++ b/lib/rubocop/cop/rails/time_zone.rb @@ -21,6 +21,7 @@ module Rails # # bad # Time.now # Time.parse('2015-03-02T19:05:37') + # '2015-03-02T19:05:37'.to_time # # # good # Time.current @@ -44,19 +45,17 @@ class TimeZone < Base extend AutoCorrector MSG = 'Do not use `%s` without zone. Use `%s` instead.' - MSG_ACCEPTABLE = 'Do not use `%s` without zone. Use one of %s instead.' - MSG_LOCALTIME = 'Do not use `Time.localtime` without offset or zone.' + MSG_STRING_TO_TIME = 'Do not use `String#to_time` without zone. Use `Time.zone.parse` instead.' GOOD_METHODS = %i[zone zone_default find_zone find_zone!].freeze - DANGEROUS_METHODS = %i[now local new parse at].freeze - ACCEPTED_METHODS = %i[in_time_zone utc getlocal xmlschema iso8601 jisx0301 rfc3339 httpdate to_i to_f].freeze - TIMEZONE_SPECIFIER = /([A-Za-z]|[+-]\d{2}:?\d{2})\z/.freeze + RESTRICT_ON_SEND = %i[to_time].freeze + def on_const(node) mod, klass = *node # we should only check core classes @@ -66,6 +65,14 @@ def on_const(node) check_time_node(klass, node.parent) if klass == :Time end + def on_send(node) + return if !node.receiver&.str_type? || !node.method?(:to_time) + + add_offense(node.loc.selector, message: MSG_STRING_TO_TIME) do |corrector| + autocorrect(corrector, node) + end + end + private def autocorrect(corrector, node) diff --git a/spec/rubocop/cop/rails/time_zone_spec.rb b/spec/rubocop/cop/rails/time_zone_spec.rb index adb4173024..be0ca5bd5e 100644 --- a/spec/rubocop/cop/rails/time_zone_spec.rb +++ b/spec/rubocop/cop/rails/time_zone_spec.rb @@ -124,6 +124,19 @@ end end + it 'registers an offense for `String#to_time`' do + expect_offense(<<~RUBY) + "2012-03-02 16:05:37".to_time + ^^^^^^^ Do not use `String#to_time` without zone. Use `Time.zone.parse` instead. + RUBY + end + + it 'does not register an offense for `to_time` without receiver' do + expect_no_offenses(<<~RUBY) + to_time + RUBY + end + it 'registers an offense for Time.parse' do expect_offense(<<~RUBY) Time.parse("2012-03-02 16:05:37")