Class: RuboCop::Cop::Rails::TimeZone

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
ConfigurableEnforcedStyle
Defined in:
lib/rubocop/cop/rails/time_zone.rb

Overview

Checks for the use of Time methods without zone.

Built on top of Ruby on Rails style guide (rails.rubystyle.guide#time) and the article danilenko.org/2012/7/6/rails_timezones/

Two styles are supported for this cop. When ‘EnforcedStyle` is ’strict’ then only use of ‘Time.zone` is allowed.

When EnforcedStyle is ‘flexible’ then it’s also allowed to use ‘Time#in_time_zone`.

Examples:

# bad
Time.now
Time.parse('2015-03-02T19:05:37')
'2015-03-02T19:05:37'.to_time

# good
Time.current
Time.zone.now
Time.zone.parse('2015-03-02T19:05:37')
Time.zone.parse('2015-03-02T19:05:37Z') # Respect ISO 8601 format with timezone specifier.
Time.parse('2015-03-02T19:05:37Z') # Also respects ISO 8601
'2015-03-02T19:05:37Z'.to_time # Also respects ISO 8601

EnforcedStyle: flexible (default)

# `flexible` allows usage of `in_time_zone` instead of `zone`.

# good
Time.at(timestamp).in_time_zone

EnforcedStyle: strict

# `strict` means that `Time` should be used with `zone`.

# bad
Time.at(timestamp).in_time_zone

Constant Summary collapse

MSG =
'Do not use `%<current>s` without zone. Use `%<prefer>s` instead.'
MSG_ACCEPTABLE =
'Do not use `%<current>s` without zone. Use one of %<prefer>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

Instance Method Summary collapse

Instance Method Details

#on_const(node) ⇒ Object



61
62
63
64
65
66
67
68
# File 'lib/rubocop/cop/rails/time_zone.rb', line 61

def on_const(node)
  mod, klass = *node
  # we should only check core classes
  # (`Time` or `::Time`)
  return unless (mod.nil? || mod.cbase_type?) && method_send?(node)

  check_time_node(klass, node.parent) if klass == :Time
end

#on_send(node) ⇒ Object Also known as: on_csend



70
71
72
73
74
75
76
77
# File 'lib/rubocop/cop/rails/time_zone.rb', line 70

def on_send(node)
  return if !node.receiver&.str_type? || !node.method?(:to_time)
  return if attach_timezone_specifier?(node.receiver)

  add_offense(node.loc.selector, message: MSG_STRING_TO_TIME) do |corrector|
    corrector.replace(node, "Time.zone.parse(#{node.receiver.source})") unless node.csend_type?
  end
end