Interesting.
Both i and inspect are using protocols.
As the others said, you can customise inspect to log the underlying map (including the __struct__ key) by passing the structs: false option. I don’t think there’s a built-in way to log an equivalent to the raw representation section from i.
Here follows TMI about protocol implementations 

Elixir includes a default Inspect implementation to log structs that have not implemented the Inspect protocol:
iex(1)> defmodule Example, do: defstruct [:foo]
{:module, Example, <<...>>, %Example{foo: nil}}
iex(2)> %Example{}
%Example{foo: nil} # <-- default implementation
But DateTime has its own implementation of the Inspect protocol that serialises it as a sigil:
iex(3)> DateTime.utc_now
~U[2025-06-24 14:01:48.773039Z] # <-- DateTime's implementation
i is actually overriding any type-specific Inspect implementations to dump the raw representation using the default Inspect.Any implementation.
Here’s what IEx.Info is doing internally, vs. what happens when you call inspect normally on a DateTime. Note the use of Inspect.Any, which is the default implementation IEx.Info calls explicitly, vs. Inspect.DateTime, which is what you get when you pass a DateTime struct to inspect.
iex(4)> DateTime.utc_now |> Inspect.Any.inspect(%Inspect.Opts{}) |> Inspect.Algebra.format(:infinity) |> IO.iodata_to_binary
"%DateTime{year: 2025, month: 6, day: 24, hour: 14, minute: 7, second: 18, time_zone: \"Etc/UTC\", zone_abbr: \"UTC\", utc_offset: 0, std_offset: 0, microsecond: {379886, 6}, calendar: Calendar.ISO}"
iex(5)> DateTime.utc_now |> Inspect.DateTime.inspect(%Inspect.Opts{}) |> Inspect.Algebra.format(:infinity) |> IO.iodata_to_binary
"~U[2025-06-24 14:07:23.538947Z]"