diff --git a/src/Positioning/Positioning.jl b/src/Positioning/Positioning.jl index 1a5f78b..b387f7d 100644 --- a/src/Positioning/Positioning.jl +++ b/src/Positioning/Positioning.jl @@ -255,9 +255,14 @@ pos_noaa = solar_position(obs, dt, NOAA()) - **Refraction**: Any `RefractionAlgorithm` subtype (default: `NoRefraction()`) # Time Zone Handling -- `DateTime` inputs are assumed to be in UTC -- `ZonedDateTime` inputs are automatically converted to UTC -- For local solar time calculations, use appropriate time zones +- **`DateTime` inputs are assumed to be in UTC.** If you pass a local time as a plain + `DateTime`, the result will be incorrect — wrap it in a `ZonedDateTime` with the + appropriate time zone instead. +- **`ZonedDateTime` inputs are automatically converted to UTC** before computing the solar + position. For example, `ZonedDateTime(2023, 6, 21, 14, 0, 0, tz"Europe/Brussels")` + (UTC+2) is converted to `DateTime(2023, 6, 21, 12, 0, 0)` (UTC) before calculation. +- Two `ZonedDateTime` values representing the **same UTC instant** in different time zones + will produce **identical** results. See also: [`solar_position!`](@ref), [`Observer`](@ref), [`PSA`](@ref), [`NOAA`](@ref) """ diff --git a/test/positioning/test-interface.jl b/test/positioning/test-interface.jl index 86073a8..bf77cf1 100644 --- a/test/positioning/test-interface.jl +++ b/test/positioning/test-interface.jl @@ -35,9 +35,20 @@ using Dates: Hour, @dateformat_str result1 = solar_position(obs_ref, dt_plain, alg) @test result1 == result_ref - # ZonedDateTime + # ZonedDateTime (UTC) — same instant as dt_plain result2 = solar_position(obs_ref, dt_zoned, alg) @test result2 == result_ref + + # ZonedDateTime with non-UTC timezone + # 2020-10-17T14:30:00+02:00 (Europe/Brussels) == 2020-10-17T12:30:00 UTC + dt_brussels = ZonedDateTime(2020, 10, 17, 14, 30, 0, tz"Europe/Brussels") + result_tz = solar_position(obs_ref, dt_brussels, alg) + @test result_tz == result_ref + + # 2020-10-17T08:30:00-04:00 (America/New_York EDT) == 2020-10-17T12:30:00 UTC + dt_nyc = ZonedDateTime(2020, 10, 17, 8, 30, 0, tz"America/New_York") + result_nyc = solar_position(obs_ref, dt_nyc, alg) + @test result_nyc == result_ref end @testset "Vectorized Interface" begin @@ -126,6 +137,21 @@ using Dates: Hour, @dateformat_str @test pos1 == pos2 end + + @testset "Return new with non-UTC ZonedDateTime (issue #73)" begin + # Convert UTC DateTimes to Brussels timezone ZonedDateTimes + # These represent the same instants in time, just in different timezones + dts_brussels = [ + TimeZones.astimezone( + ZonedDateTime(dt, tz"UTC"), tz"Europe/Brussels" + ) for dt in dts + ] + + pos_brussels = solar_position(obs, dts_brussels, alg) + pos_utc = solar_position(obs, dts, alg) + + @test pos_brussels == pos_utc + end end @testset "Tables Interface" begin