Skip to content

Commit d10d5ae

Browse files
amatsudanobu
andcommitted
TZ offset minute has to be negated in the Western Hemisphere
When the TZ in the given string contains minus offset, both hour and minute value has to be negated, but the current code negates hour only. Hence, for instance in Newfoundland Time Zone (UTC−03:30), it used to return 1 hour advanced value. Co-authored-by: Nobuyoshi Nakada <[email protected]>
1 parent 7266313 commit d10d5ae

File tree

3 files changed

+13
-1
lines changed

3 files changed

+13
-1
lines changed

activemodel/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Fix a bug where type casting of string to `Time` and `DateTime` doesn't
2+
calculate minus minute value in TZ offset correctly.
3+
4+
*Akira Matsuda*
5+
16
* Port the `type_for_attribute` method to Active Model. Classes that include
27
`ActiveModel::Attributes` will now provide this method. This method behaves
38
the same for Active Model as it does for Active Record.

activemodel/lib/active_model/type/helpers/time_value.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,13 @@ def fast_string_to_time(string)
9494
end
9595

9696
if $8
97-
offset = $8 == "Z" ? 0 : $8.to_i * 3600 + $9.to_i * 60
97+
offset = \
98+
if $8 == "Z"
99+
0
100+
else
101+
offset_h, offset_m = $8.to_i, $9.to_i
102+
offset_h.to_i * 3600 + (offset_h.negative? ? -1 : 1) * offset_m * 60
103+
end
98104
end
99105

100106
new_time($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, usec, offset)

activemodel/test/cases/type/time_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def test_type_cast_time
1818
assert_equal ::Time.utc(2000, 1, 1, 16, 45, 54), type.cast("2015-06-13T19:45:54+03:00")
1919
assert_equal ::Time.utc(1999, 12, 31, 21, 7, 8), type.cast("06:07:08+09:00")
2020
assert_equal ::Time.utc(2000, 1, 1, 16, 45, 54), type.cast(4 => 16, 5 => 45, 6 => 54)
21+
assert_equal ::Time.utc(2000, 1, 1, 3, 30, 0), type.cast("2023-01-01T00:00:00-03:30")
2122
end
2223

2324
def test_user_input_in_time_zone

0 commit comments

Comments
 (0)