title: How does PostgreSQL store datetime types internally
body: <p>When reading the PostreSQL (13) documentation, I came across <a href="https://www.postgresql.org/docs/13/datatype-datetime.html" rel="nofollow noreferrer">this</a> page, which lists the storage sizes of different datetime types.</p>
  <p>Inter alia it states:</p>
  <pre><code>Name                         Storage Size       Description                                   Low Value      High Value      Resolution
  ----                         ------------       -----------                                   ---------      ----------      ----------
  timestamp without time zone       8 bytes       both date and time (no time zone)               4713 BC       294276 AD   1 microsecond
  timestamp with time zone          8 bytes       both date and time, with time zone              4713 BC       294276 AD   1 microsecond
  time with time zone              12 bytes       time of day (no date), with time zone     00:00:00+1559   24:00:00-1559   1 microsecond
  </code></pre>
  <p>I can understand <code>timestamp without time zone</code>: There are roughly (4713 + 294276) * 365 * 24 * 60 * 60 * 1000000 microseconds between low and high value. (Not accounting for calender changes and such). This amounts to roughly 2^63 values and those can be stored in 8 bytes.</p>
  <p>However, <code>timestamp with timezone</code> has the same range and resolution and can additonally store the time zone information. If we already use 63 bits for the values there is only one bit left, which cannot be enough to store the timezone, so the internal storage must work somehow different.</p>
  <p>Even stranger, while timestamps use only 8 bytes, <code>time with time zone</code> needs 12 bytes, although it has the same resolution and a much smaller range of allowed values.</p>
  <p>Thus my question: How does the internal storage of these types in PostgreSQL work?</p>