/
date_time.rb
88 lines (76 loc) · 2.39 KB
/
date_time.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# frozen_string_literal: true
module RuboCop
module Cop
module Style
# This cop checks for consistent usage of the `DateTime` class over the
# `Time` class. This cop is disabled by default since these classes,
# although highly overlapping, have particularities that make them not
# replaceable in certain situations when dealing with multiple timezones
# and/or DST.
#
# @example
#
# # bad - uses `DateTime` for current time
# DateTime.now
#
# # good - uses `Time` for current time
# Time.now
#
# # bad - uses `DateTime` for modern date
# DateTime.iso8601('2016-06-29')
#
# # good - uses `Time` for modern date
# Time.iso8601('2016-06-29')
#
# # good - uses `DateTime` with start argument for historical date
# DateTime.iso8601('1751-04-23', Date::ENGLAND)
#
# @example AllowCoercion: false (default)
#
# # bad - coerces to `DateTime`
# something.to_datetime
#
# # good - coerces to `Time`
# something.to_time
#
# @example AllowCoercion: true
#
# # good
# something.to_datetime
#
# # good
# something.to_time
class DateTime < Base
extend AutoCorrector
CLASS_MSG = 'Prefer Time over DateTime.'
COERCION_MSG = 'Do not use #to_datetime.'
def_node_matcher :date_time?, <<~PATTERN
(send (const {nil? (cbase)} :DateTime) ...)
PATTERN
def_node_matcher :historic_date?, <<~PATTERN
(send _ _ _ (const (const {nil? (cbase)} :Date) _))
PATTERN
def_node_matcher :to_datetime?, <<~PATTERN
(send _ :to_datetime)
PATTERN
def on_send(node)
return unless date_time?(node) ||
(to_datetime?(node) && disallow_coercion?)
return if historic_date?(node)
message = to_datetime?(node) ? COERCION_MSG : CLASS_MSG
add_offense(node, message: message) do |corrector|
autocorrect(corrector, node)
end
end
private
def disallow_coercion?
!cop_config['AllowCoercion']
end
def autocorrect(corrector, node)
return if to_datetime?(node)
corrector.replace(node.receiver.loc.name, 'Time')
end
end
end
end
end