<p dir="auto"><strong>Describe the bug</strong><br>
If we create a datetime at year 0, month 1, day 1 with a timezone such that the utc equivalent<br>
would refer to a UTC time that is in a BC year a and save it to a database,<br>
then we can't deserialize it back to a datetime - as when we write the utc</p>
<p dir="auto"><strong>Expected behavior</strong></p>
<p dir="auto">We shouldn't be able to insert datetime values that can't be deserialized back into a datetime.</p>
<p dir="auto"><strong>To Reproduce</strong></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from uuid import uuid4, UUID
from datetime import datetime, timezone, timedelta

from sqlalchemy import (
    Column,
    DateTime,
)
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class Example(Base):
    __tablename__ = &quot;example&quot;

    example_id = Column(UUID(as_uuid=True), primary_key=True)
    date = Column(DateTime(timezone=True), nullable=True)


bc_datetime = datetime(year=1, month=1, day=1, tzinfo=timezone(timedelta(hours=1)))

db_session.add(
    Example(
        example_id=uuid4(),
        date=bc_datetime.
    )
)
db.commit()

# This works

# but this won't, as date can't be serialized into a datetime:

example = db.query(Example).first()
example.date"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">uuid</span> <span class="pl-k">import</span> <span class="pl-s1">uuid4</span>, <span class="pl-v">UUID</span>
<span class="pl-k">from</span> <span class="pl-s1">datetime</span> <span class="pl-k">import</span> <span class="pl-s1">datetime</span>, <span class="pl-s1">timezone</span>, <span class="pl-s1">timedelta</span>

<span class="pl-k">from</span> <span class="pl-s1">sqlalchemy</span> <span class="pl-k">import</span> (
    <span class="pl-v">Column</span>,
    <span class="pl-v">DateTime</span>,
)
<span class="pl-k">from</span> <span class="pl-s1">sqlalchemy</span>.<span class="pl-s1">ext</span>.<span class="pl-s1">declarative</span> <span class="pl-k">import</span> <span class="pl-s1">declarative_base</span>

<span class="pl-v">Base</span> <span class="pl-c1">=</span> <span class="pl-en">declarative_base</span>()


<span class="pl-k">class</span> <span class="pl-v">Example</span>(<span class="pl-v">Base</span>):
    <span class="pl-s1">__tablename__</span> <span class="pl-c1">=</span> <span class="pl-s">"example"</span>

    <span class="pl-s1">example_id</span> <span class="pl-c1">=</span> <span class="pl-v">Column</span>(<span class="pl-v">UUID</span>(<span class="pl-s1">as_uuid</span><span class="pl-c1">=</span><span class="pl-c1">True</span>), <span class="pl-s1">primary_key</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
    <span class="pl-s1">date</span> <span class="pl-c1">=</span> <span class="pl-v">Column</span>(<span class="pl-v">DateTime</span>(<span class="pl-s1">timezone</span><span class="pl-c1">=</span><span class="pl-c1">True</span>), <span class="pl-s1">nullable</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)


<span class="pl-s1">bc_datetime</span> <span class="pl-c1">=</span> <span class="pl-en">datetime</span>(<span class="pl-s1">year</span><span class="pl-c1">=</span><span class="pl-c1">1</span>, <span class="pl-s1">month</span><span class="pl-c1">=</span><span class="pl-c1">1</span>, <span class="pl-s1">day</span><span class="pl-c1">=</span><span class="pl-c1">1</span>, <span class="pl-s1">tzinfo</span><span class="pl-c1">=</span><span class="pl-en">timezone</span>(<span class="pl-en">timedelta</span>(<span class="pl-s1">hours</span><span class="pl-c1">=</span><span class="pl-c1">1</span>)))

<span class="pl-s1">db_session</span>.<span class="pl-en">add</span>(
    <span class="pl-v">Example</span>(
        <span class="pl-s1">example_id</span><span class="pl-c1">=</span><span class="pl-en">uuid4</span>(),
        <span class="pl-s1">date</span><span class="pl-c1">=</span><span class="pl-s1">bc_datetime</span>.
    )
)
<span class="pl-s1">db</span>.<span class="pl-en">commit</span>()

<span class="pl-c"># This works</span>

<span class="pl-c"># but this won't, as date can't be serialized into a datetime:</span>

<span class="pl-s1">example</span> <span class="pl-c1">=</span> <span class="pl-s1">db</span>.<span class="pl-en">query</span>(<span class="pl-v">Example</span>).<span class="pl-en">first</span>()
<span class="pl-s1">example</span>.<span class="pl-s1">date</span></pre></div>
<p dir="auto"><strong>Versions.</strong></p>
<ul dir="auto">
<li>OS: Ubuntu 20.04.2 LTS</li>
<li>Python: 3.8.5</li>
<li>SQLAlchemy:</li>
<li>Database: PostgreSQL 11.9</li>
<li>DBAPI:</li>
</ul>
<p dir="auto"><strong>Migrated issue, originally created by whereswalden</strong></p>
<p dir="auto">Currently, <a href="http://docs.sqlalchemy.org/en/latest/core/metadata.html#sqlalchemy.schema.MetaData.params.naming_convention" rel="nofollow">MetaData.naming_convention</a> does not support composite indexes or foreign keys, so those must be named explicitly. It'd be nice to be able to provide a template for those to be automatically named as well.</p>
<p dir="auto">It would likely be necessary for users to define a function to provide the name, since the constraint/index could include any number of columns, but a fairly simple example could be provided in the documentation that simply <code class="notranslate">','.join()</code>s the column names.</p>