Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/tz/time_zone_database.ex
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ defmodule Tz.TimeZoneDatabase do
div(days * 86_400_000_000 + parts_in_day, 1_000_000)
end

defp iso_days_to_gregorian_seconds({days, {parts_in_day, parts_per_day}}) do
div(days * parts_per_day + parts_in_day, div(parts_per_day, 86400))
end

defp naive_datetime_to_gregorian_seconds(%{calendar: Calendar.ISO, year: year}) when year < 0,
do: 0

Expand Down
45 changes: 45 additions & 0 deletions test/datetime_math_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule DateTimeMathTest do
use ExUnit.Case, async: true

@timezone "America/Fortaleza"
@datetime DateTime.from_naive!(~N[2025-04-15 00:00:01.000000], @timezone, Tz.TimeZoneDatabase)
@added_second DateTime.add(@datetime, +1, :second, Tz.TimeZoneDatabase)
@minus_second DateTime.add(@datetime, -1, :second, Tz.TimeZoneDatabase)

describe "nanosecond" do
test "adds 1 second with nanosecond unit" do
amount = System.convert_time_unit(+1, :second, :nanosecond)
unit = :nanosecond
assert DateTime.add(@datetime, amount, unit, Tz.TimeZoneDatabase) == @added_second
end

test "subtracts 1 second with nanosecond unit" do
amount = System.convert_time_unit(-1, :second, :nanosecond)
unit = :nanosecond
assert DateTime.add(@datetime, amount, unit, Tz.TimeZoneDatabase) == @minus_second
end
end

describe "strictly positive integer with units ranging from decisecond (10^-1s) to Planck time (10^-44s)" do
# To understand how this units work see:
# - https://hexdocs.pm/elixir/1.18.2/System.html#t:time_unit/0
# - https://en.wikipedia.org/wiki/Orders_of_magnitude_(time)
@units_in_parts_per_second Enum.map(1..44, &System.convert_time_unit(1, :second, 10 ** &1))

test "adds 1 second" do
Enum.each(@units_in_parts_per_second, fn parts_per_second ->
amount = +parts_per_second
unit = parts_per_second
assert DateTime.add(@datetime, amount, unit, Tz.TimeZoneDatabase) == @added_second
end)
end

test "subtracts 1 second" do
Enum.each(@units_in_parts_per_second, fn parts_per_second ->
amount = -parts_per_second
unit = parts_per_second
assert DateTime.add(@datetime, amount, unit, Tz.TimeZoneDatabase) == @minus_second
end)
end
end
end
2 changes: 1 addition & 1 deletion test/dynamic_periods_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule DynamicPeriodsTest do
use ExUnit.Case
use ExUnit.Case, async: true

test "dynamic periods" do
time_zone = "Antarctica/Troll"
Expand Down
2 changes: 1 addition & 1 deletion test/time_zone_database_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule TimeZoneDatabaseTest do
use ExUnit.Case
use ExUnit.Case, async: true

alias Support.HoloceneCalendar

Expand Down
3 changes: 2 additions & 1 deletion test/updater_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defmodule UpdaterTest do
use ExUnit.Case
use ExUnit.Case, async: true

@tag :updater
test "updater is only started once" do
assert {:ok, _} = start_supervised(Tz.UpdatePeriodically)
assert {:error, _} = start_supervised(Tz.UpdatePeriodically)
Expand Down