title: Python [pydantic] - Date validation
body: <p>i'd like to valid a json input for dates as pydantic class,
  next , to simply inject the file to Mongo .</p>
  <p>Simple class with date type</p>
  <pre><code>
  class CustomerBase(BaseModel):
      birthdate: date = None
  
  </code></pre>
  <p>Using motor for working with Mongo</p>
  <p>Db configuration :</p>
  <pre><code>from motor.motor_asyncio import AsyncIOMotorClient
  
  DB = DB_CLIENT[CONF.get(&quot;databases&quot;, dict())[&quot;mongo&quot;][&quot;NAME&quot;]]
  
  </code></pre>
  <p>8/03/2021 - Update:</p>
  <p>I did the following debug test,
  first print the class to see how it saved and next try to inject it to Mongo.</p>
  <p>so for input:</p>
  <pre><code>{ &quot;birthdate&quot;: &quot;2021-03-05&quot;}
  
  </code></pre>
  <p>Routing:</p>
  <pre><code>@customers_router.post(&quot;/&quot;, response_model=dict)
  async def add_customer(customer: CustomerBase):
      print(customer.dict())
  
  &gt;&gt; {'birthdate': datetime.date(2021, 3, 5)}
  
      await DB.customer.insert_one(customer.dict())
      return {&quot;test&quot;:1}
  
  &gt;&gt; 
   File &quot;./customers/routes.py&quot;, line 74, in add_customer
      await DB.customer.insert_one(customer.dict())
    File &quot;/usr/local/lib/python3.8/concurrent/futures/thread.py&quot;, line 57, in run
      result = self.fn(*self.args, **self.kwargs)
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/collection.py&quot;, line 698, in insert_one
      self._insert(document,
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/collection.py&quot;, line 613, in _insert
      return self._insert_one(
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/collection.py&quot;, line 602, in _insert_one
      self.__database.client._retryable_write(
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/mongo_client.py&quot;, line 1498, in _retryable_write
      return self._retry_with_session(retryable, func, s, None)
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/mongo_client.py&quot;, line 1384, in _retry_with_session
      return self._retry_internal(retryable, func, session, bulk)
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/mongo_client.py&quot;, line 1416, in _retry_internal
      return func(session, sock_info, retryable)
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/collection.py&quot;, line 590, in _insert_command
      result = sock_info.command(
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/pool.py&quot;, line 699, in command
      self._raise_connection_failure(error)
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/pool.py&quot;, line 683, in command
      return command(self, dbname, spec, slave_ok,
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/network.py&quot;, line 120, in command
      request_id, msg, size, max_doc_size = message._op_msg(
    File &quot;/usr/local/lib/python3.8/site-packages/pymongo/message.py&quot;, line 714, in _op_msg
      return _op_msg_uncompressed(
  bson.errors.InvalidDocument: cannot encode object: datetime.date(2021, 3, 5), of type: &lt;class 'datetime.date'&gt;
  
  </code></pre>
  <p>Issues:
  1.The date in class saved as birthday: datetime.date(2021, 3, 5)
  is that expected?
  2.Surely the problem coming from :
  '''
  DB.customer.insert_one(customer.dict())
  '''
  it does work when i change the date type to str in Class</p>
  <p><strong>Update  09/03/2022:</strong></p>
  <p>following Tom's suggestion:
  the decorator and parse_birthday function added.
  Now i able to document to Mongo but not able to read it.</p>
  <pre><code>
  class CustomerBase(BaseModel):
      birthdate: datetime.date
  
      @validator(&quot;birthdate&quot;, pre=True)
      def parse_birthdate(cls, value):
          return datetime.datetime.strptime(
              value,
              &quot;%d/%m/%Y&quot;
          ).date()
  
      def dict(self, *args, **kwargs) -&gt; 'DictStrAny':
          for_mongo = kwargs.pop('for_mongo', False)
          d = super().dict(*args, **kwargs)
          if for_mongo:
              for k, v in d.items():
                  if isinstance(v, datetime.date):
                      d[k] = datetime.datetime(
                          year=v.year,
                          month=v.month,
                          day=v.day,
                      )
          return d
  
  class CustomerOnDB(CustomerBase):
      id_: str
  </code></pre>
  <p>assign data (working):
  input : {&quot;birthdate&quot;: &quot;01/11/1978&quot;}</p>
  <pre><code>@customers_router.post(&quot;/&quot;, response_model=dict )
  async def add_customer(customer: CustomerBase):
  
      customer_op = await DB.customer.insert_one(customer.dict(for_mongo=True))
      if customer_op.inserted_id:
          #customer_op.inserted_id -&gt; is the str _id
          await _get_customer_or_404(customer_op.inserted_id)
          return { &quot;id_&quot;: str(customer_op.inserted_id) }
  
  </code></pre>
  <p>When trying to read:</p>
  <pre><code>def validate_object_id(id_: str):
      try:
          _id = ObjectId(id_)
      except Exception:
          raise HTTPException(status_code=400)
      return _id
  
  
  @customers_router.get(
      &quot;/{id_}&quot;,
      response_model=CustomerOnDB
  )
  async def get_customer_by_id(id_: ObjectId = Depends(validate_object_id)):
      customer = await DB.customer.find_one({&quot;_id&quot;: id_})
      if customer:
          customer[&quot;id_&quot;] = str(customer[&quot;_id&quot;])
          return customer
      else:
          raise HTTPException(status_code=404, detail=&quot;Customer not found&quot;)
  
  </code></pre>
  <p>Getting:</p>
  <pre><code>
    File &quot;/usr/local/lib/python3.8/site-packages/fastapi/routing.py&quot;, line 126, in serialize_response
      raise ValidationError(errors, field.type_)
  pydantic.error_wrappers.ValidationError: 1 validation error for CustomerOnDB
  response -&gt; 0 -&gt; birthdate
    strptime() argument 1 must be str, not datetime.datetime (type=type_error)
  
  </code></pre>