<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Date on Opensource internals</title><link>https://articles.9j.nz/tags/date/</link><description>Posts filed under Date on Opensource internals.</description><generator>Hugo</generator><language>en-US</language><managingEditor>Jay Hubbert</managingEditor><lastBuildDate>Mon, 27 Jul 2026 01:19:06 +0000</lastBuildDate><atom:link href="https://articles.9j.nz/tags/date/index.xml" rel="self" type="application/rss+xml"/><item><title>PostgreSQL's date Implementation in C</title><link>https://articles.9j.nz/posts/how-postgres-implements-date-in-c/</link><pubDate>Mon, 27 Jul 2026 01:19:06 +0000</pubDate><dc:creator>Jay Hubbert</dc:creator><guid isPermaLink="true">https://articles.9j.nz/posts/how-postgres-implements-date-in-c/</guid><category>postgres</category><category>internals</category><category>date</category><description>A PostgreSQL date is a 4-byte signed integer counting days since 2000-01-01, reached by subtracting a Julian-day constant. That is why it sorts as an int32 and why infinity is just INT32_MAX.</description><content:encoded>&lt;p&gt;A PostgreSQL &lt;code&gt;date&lt;/code&gt; is not a Unix timestamp, not a &lt;code&gt;struct tm&lt;/code&gt;, and not&#10;&amp;ldquo;days since 1970&amp;rdquo;. It is a signed 32-bit integer counting days since&#10;&lt;strong&gt;2000-01-01&lt;/strong&gt;. That single decision is why a date sorts with a plain&#10;integer comparison, why &lt;code&gt;date - date&lt;/code&gt; is an &lt;code&gt;int4&lt;/code&gt;, and why&#10;&lt;code&gt;'infinity'::date&lt;/code&gt; is literally &lt;code&gt;INT32_MAX&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;This is a walk through the C implementation, based on reading the&#10;PostgreSQL source (version 20devel, commit &lt;code&gt;e75fcc9867f&lt;/code&gt;).&lt;/p&gt;&#10;&lt;h2 id="the-catalog-entry"&gt;The catalog entry&lt;/h2&gt;&#10;&lt;p&gt;Every type starts as a row in &lt;code&gt;src/include/catalog/pg_type.dat&lt;/code&gt;. For&#10;&lt;code&gt;date&lt;/code&gt; (lines 287–290):&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;text&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{ oid =&amp;gt; &amp;#39;1082&amp;#39;, array_type_oid =&amp;gt; &amp;#39;1182&amp;#39;, descr =&amp;gt; &amp;#39;date&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; typname =&amp;gt; &amp;#39;date&amp;#39;, typlen =&amp;gt; &amp;#39;4&amp;#39;, typbyval =&amp;gt; &amp;#39;t&amp;#39;, typcategory =&amp;gt; &amp;#39;D&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; typinput =&amp;gt; &amp;#39;date_in&amp;#39;, typoutput =&amp;gt; &amp;#39;date_out&amp;#39;, typreceive =&amp;gt; &amp;#39;date_recv&amp;#39;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; typsend =&amp;gt; &amp;#39;date_send&amp;#39;, typalign =&amp;gt; &amp;#39;i&amp;#39; },&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Four facts fall out of this:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Field&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Value&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Meaning&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;typlen&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;a 4-byte value, stored inline&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;typbyval&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;t&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;passed by value, not by reference&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;typalign&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;aligned to a 4-byte boundary&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;array_type_oid&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;1182&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;the &lt;code&gt;date[]&lt;/code&gt; array type&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;There is no &lt;code&gt;typstorage&lt;/code&gt;, so it defaults to &lt;code&gt;p&lt;/code&gt; (PLAIN) — no compression, no&#10;TOAST. A date is always exactly 4 bytes on disk, and there is nothing to&#10;decompress.&lt;/p&gt;&#10;&lt;h2 id="the-c-representation"&gt;The C representation&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;DateADT&lt;/code&gt; is a one-line typedef in &lt;code&gt;src/include/utils/date.h&lt;/code&gt;:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="n"&gt;int32&lt;/span&gt; &lt;span class="n"&gt;DateADT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Because the type is by-value, the accessors are trivial. &lt;code&gt;Datum&lt;/code&gt; is the&#10;generic 8-byte value container PostgreSQL uses everywhere&#10;(&lt;code&gt;src/include/postgres.h&lt;/code&gt;), and the conversion is just a cast:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;DateADT&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;DatumGetDateADT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Datum&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateADT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;DatumGetInt32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="n"&gt;Datum&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;DateADTGetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateADT&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Int32GetDatum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;The infinity sentinels are reserved at the extremes of the type&#10;(&lt;code&gt;src/include/utils/date.h&lt;/code&gt;):&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define DATEVAL_NOBEGIN&#9;&#9;((DateADT) PG_INT32_MIN)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define DATEVAL_NOEND&#9;&#9;((DateADT) PG_INT32_MAX)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&lt;code&gt;-2147483648&lt;/code&gt; is &lt;code&gt;-infinity&lt;/code&gt;; &lt;code&gt;2147483647&lt;/code&gt; is &lt;code&gt;infinity&lt;/code&gt;. Everything in&#10;between is a day count.&lt;/p&gt;&#10;&lt;h2 id="days-since-2000-via-julian-day"&gt;Days since 2000, via Julian day&lt;/h2&gt;&#10;&lt;p&gt;The internal value is &lt;code&gt;julian_day - POSTGRES_EPOCH_JDATE&lt;/code&gt;, where&#10;&lt;code&gt;POSTGRES_EPOCH_JDATE&lt;/code&gt; is &lt;code&gt;2451545&lt;/code&gt;, the Julian day of 2000-01-01&#10;(&lt;code&gt;src/include/datatype/timestamp.h&lt;/code&gt;):&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define UNIX_EPOCH_JDATE&#9;&#9;2440588 &lt;/span&gt;&lt;span class="cm"&gt;/* == date2j(1970, 1, 1) */&lt;/span&gt;&lt;span class="cp"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define POSTGRES_EPOCH_JDATE&#9;2451545 &lt;/span&gt;&lt;span class="cm"&gt;/* == date2j(2000, 1, 1) */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;The Julian-day machinery lives in &lt;code&gt;src/backend/utils/adt/datetime.c&lt;/code&gt;, not&#10;&lt;code&gt;date.c&lt;/code&gt;. &lt;code&gt;date2j()&lt;/code&gt; turns a calendar date into a Julian day number:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;date2j&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt;&#9;&#9;&#9;&lt;span class="n"&gt;julian&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="kt"&gt;int&lt;/span&gt;&#9;&#9;&#9;&lt;span class="n"&gt;century&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;4800&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;else&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;4799&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;century&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;julian&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;32167&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;julian&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;century&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;century&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;julian&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;7834&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;julian&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;This is integer-only, so it cannot produce a rounding error, and it works&#10;for negative years (BC). The inverse, &lt;code&gt;j2date()&lt;/code&gt;, is in the same file. The&#10;whole range check is a pair of integer comparisons:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#define IS_VALID_DATE(d) \&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&#9;((DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) &amp;lt;= (d) &amp;amp;&amp;amp; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&#9; (d) &amp;lt; (DATE_END_JULIAN - POSTGRES_EPOCH_JDATE))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;That allows Julian day zero (4714-11-24 BC) up to 5874897-12-31 AD.&lt;/p&gt;&#10;&lt;h2 id="input-and-output"&gt;Input and output&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;date_in()&lt;/code&gt; (&lt;code&gt;src/backend/utils/adt/date.c&lt;/code&gt;) hands the string to the shared&#10;parser, then converts:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;dterr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ParseDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workbuf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workbuf&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ftype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAXDATEFIELDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dterr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="n"&gt;dterr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;DecodeDateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ftype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#9; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;fsec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tzp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;extra&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="p"&gt;...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;date2j&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tm_year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tm_mon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tm_mday&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;POSTGRES_EPOCH_JDATE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* Now check for just-out-of-range dates */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;IS_VALID_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;ereturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;escontext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Datum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&lt;code&gt;DecodeDateTime&lt;/code&gt; returns a &lt;code&gt;dtype&lt;/code&gt;, and &lt;code&gt;date_in&lt;/code&gt; accepts three special&#10;cases besides an ordinary date: &lt;code&gt;DTK_EPOCH&lt;/code&gt; (&lt;code&gt;'epoch'&lt;/code&gt;, i.e. 1970-01-01),&#10;&lt;code&gt;DTK_LATE&lt;/code&gt; (&lt;code&gt;'infinity'&lt;/code&gt;), and &lt;code&gt;DTK_EARLY&lt;/code&gt; (&lt;code&gt;'-infinity'&lt;/code&gt;). Note that a&#10;date never carries a timezone, so &lt;code&gt;tzp&lt;/code&gt; is ignored here.&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;date_out()&lt;/code&gt; is the mirror image:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;j2date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;POSTGRES_EPOCH_JDATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tm_year&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tm_mon&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tm_mday&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;EncodeDateOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;The binary format is the bare 4 bytes. &lt;code&gt;date_recv()&lt;/code&gt; reads them with&#10;&lt;code&gt;pq_getmsgint(buf, sizeof(DateADT))&lt;/code&gt; and range-checks; &lt;code&gt;date_send()&lt;/code&gt; writes&#10;them with &lt;code&gt;pq_sendint32()&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2 id="comparison-sorting-hashing"&gt;Comparison, sorting, hashing&lt;/h2&gt;&#10;&lt;p&gt;Because the internal value is an integer day count, ordering is free.&#10;&lt;code&gt;date_cmp()&lt;/code&gt; is a three-way integer compare, and the btree sort support&#10;hooks it straight to the &lt;code&gt;int32&lt;/code&gt; comparator:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Datum&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;date_sortsupport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PG_FUNCTION_ARGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;SortSupport&lt;/span&gt; &lt;span class="n"&gt;ssup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SortSupport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;PG_GETARG_POINTER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;ssup&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;comparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ssup_datum_int32_cmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="nf"&gt;PG_RETURN_VOID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;Hashing is just &lt;code&gt;hash_uint32(PG_GETARG_DATEADT(0))&lt;/code&gt; in &lt;code&gt;hashdate()&lt;/code&gt;. There&#10;is no normalization step, no locale, no calendar logic in the hot path —&#10;the expensive work is all done once, at input.&lt;/p&gt;&#10;&lt;h2 id="arithmetic"&gt;Arithmetic&lt;/h2&gt;&#10;&lt;p&gt;Adding days is integer addition with an overflow guard (&lt;code&gt;date_pli()&lt;/code&gt;):&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;c&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dateVal&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="cm"&gt;/* Check for integer overflow and out-of-allowed-range */&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;dateVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dateVal&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;IS_VALID_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#9;&#9;&lt;span class="nf"&gt;ereport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;&lt;code&gt;date_mi()&lt;/code&gt; returns the difference as an &lt;code&gt;int4&lt;/code&gt;, and refuses to subtract&#10;infinite dates. The infinity macros make the special cases cheap: adding a&#10;day to &lt;code&gt;infinity&lt;/code&gt; returns &lt;code&gt;infinity&lt;/code&gt;, because &lt;code&gt;date_pli()&lt;/code&gt; short-circuits on&#10;&lt;code&gt;DATE_NOT_FINITE()&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2 id="look-at-it-yourself"&gt;Look at it yourself&lt;/h2&gt;&#10;&lt;p&gt;The catalog row is directly inspectable:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;sql&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typbyval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typalign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typarray&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pg_type&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;date&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;timetz&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;To see the actual bytes, use &lt;code&gt;pageinspect&lt;/code&gt; and &lt;code&gt;tuple_data_split&lt;/code&gt;&#10;(&lt;code&gt;contrib/pageinspect/heapfuncs.c&lt;/code&gt;), which returns one &lt;code&gt;bytea&lt;/code&gt; per&#10;attribute:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;sql&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EXTENSION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pageinspect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t_data&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;heap_page_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_raw_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LATERAL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unnest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple_data_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;d&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;regclass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t_infomask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t_infomask2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t_bits&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t_data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p&gt;That returns the 4 raw bytes of the date. You can also confirm the&#10;epoch by subtraction:&lt;/p&gt;&#10;&lt;div class="code-block"&gt;&#10; &lt;div class="code-block-head"&gt;&#10; &lt;span class="code-lang"&gt;sql&lt;/span&gt;&#10; &lt;button class="code-copy" type="button" data-copy&gt;Copy&lt;/button&gt;&#10; &lt;/div&gt;&#10; &lt;div class="code-block-body"&gt;&#10; &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2024-01-01&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2000-01-01&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 8766&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;infinity&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;-infinity&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- infinity | -infinity&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;h2 id="what-it-all-means"&gt;What it all means&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;A &lt;code&gt;date&lt;/code&gt; is &lt;code&gt;int32&lt;/code&gt; days since 2000-01-01, not a Unix timestamp and not&#10;a &lt;code&gt;struct tm&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;The Julian-day conversion is pure integer arithmetic, so it is exact and&#10;works for BC dates.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;typlen = 4&lt;/code&gt;, &lt;code&gt;typbyval = t&lt;/code&gt;, &lt;code&gt;typalign = i&lt;/code&gt;, PLAIN storage: always 4&#10;bytes, never TOASTed.&lt;/li&gt;&#10;&lt;li&gt;Sorting and hashing are plain &lt;code&gt;int32&lt;/code&gt; operations — the calendar logic is&#10;only paid at parse time.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;infinity&lt;/code&gt;/&lt;code&gt;-infinity&lt;/code&gt; are reserved at &lt;code&gt;INT32_MAX&lt;/code&gt;/&lt;code&gt;INT32_MIN&lt;/code&gt;, and the&#10;arithmetic short-circuits around them.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="further-reading"&gt;Further reading&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;src/include/catalog/pg_type.dat&lt;/code&gt; — the &lt;code&gt;date&lt;/code&gt; catalog entry.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;src/include/utils/date.h&lt;/code&gt; — &lt;code&gt;DateADT&lt;/code&gt;, infinity macros, accessors.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;src/include/datatype/timestamp.h&lt;/code&gt; — &lt;code&gt;POSTGRES_EPOCH_JDATE&lt;/code&gt;, &lt;code&gt;IS_VALID_DATE&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;src/backend/utils/adt/date.c&lt;/code&gt; — &lt;code&gt;date_in&lt;/code&gt;, &lt;code&gt;date_out&lt;/code&gt;, &lt;code&gt;date_recv&lt;/code&gt;, &lt;code&gt;date_send&lt;/code&gt;, arithmetic.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;src/backend/utils/adt/datetime.c&lt;/code&gt; — &lt;code&gt;date2j&lt;/code&gt;, &lt;code&gt;j2date&lt;/code&gt;, &lt;code&gt;EncodeDateOnly&lt;/code&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</content:encoded></item></channel></rss>