Skip to content

Commit 941ce75

Browse files
jameslongJosé Valim
authored andcommitted
Fix negative microsecond result from DateTime.from_unix/2 (#6599)
1 parent 759457e commit 941ce75

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-3
lines changed

lib/elixir/lib/calendar/iso.ex

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,11 @@ defmodule Calendar.ISO do
314314
def from_unix(integer, unit) when is_integer(integer) do
315315
total = System.convert_time_unit(integer, unit, :microsecond)
316316
if total in @unix_range_microseconds do
317-
microsecond = rem(total, 1_000_000)
317+
microseconds = Integer.mod(total, @microseconds_per_second)
318+
seconds = @unix_epoch + Integer.floor_div(total, @microseconds_per_second)
318319
precision = precision_for_unit(unit)
319-
{date, time} = :calendar.gregorian_seconds_to_datetime(@unix_epoch + div(total, 1_000_000))
320-
{:ok, date, time, {microsecond, precision}}
320+
{date, time} = :calendar.gregorian_seconds_to_datetime(seconds)
321+
{:ok, date, time, {microseconds, precision}}
321322
else
322323
{:error, :invalid_unix_time}
323324
end

lib/elixir/test/elixir/calendar_test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,13 @@ defmodule DateTimeTest do
237237

238238
assert DateTime.from_unix(253402300799) == {:ok, max_datetime}
239239
assert DateTime.from_unix(253402300800) == {:error, :invalid_unix_time}
240+
241+
minus_datetime = %DateTime{
242+
calendar: Calendar.ISO, day: 31, hour: 23, microsecond: {999999, 6},
243+
minute: 59, month: 12, second: 59, std_offset: 0, time_zone: "Etc/UTC",
244+
utc_offset: 0, year: 1969, zone_abbr: "UTC"
245+
}
246+
assert DateTime.from_unix(-1, :microsecond) == {:ok, minus_datetime}
240247
end
241248

242249
test "from_unix!/2" do

0 commit comments

Comments
 (0)