Repository: theOehrly/Fast-F1

Issue:
[BUG] Empty dateOfBirth from Ergast causes missing TeamId in quali results
### Describe the issue:

[Ergast quali results for 2024 Saudi Arabia](https://ergast.com/api/f1/2024/2/qualifying.json) do not have a `dateOfBirth` for Bearman.

```
{"number":"38","position":"11","Driver":{"driverId":"bearman","permanentNumber":"38","url":"http://en.wikipedia.org/wiki/Oliver_Bearman","givenName":"Oliver","familyName":"Bearman","dateOfBirth":"","nationality":"British"},"Constructor":{"constructorId":"ferrari","url":"http://en.wikipedia.org/wiki/Scuderia_Ferrari","name":"Ferrari","nationality":"Italian"},"Q1":"1:28.984","Q2":"1:28.642"}
```

When loading the quali results, this causes the `TeamId` column in the pandas df to be empty.

```
core           INFO 	Loading data for Saudi Arabian Grand Prix - Qualifying [v3.3.0]
req            INFO 	Using cached data for session_info
req            INFO 	Using cached data for driver_info
logger      WARNING 	Failed to load result data from Ergast!
core        WARNING 	No result data for this session available on Ergast! (This is expected for recent sessions)
req            INFO 	Using cached data for session_status_data
req            INFO 	Using cached data for track_status_data
req            INFO 	Using cached data for _extended_timing_data
req            INFO 	Using cached data for timing_app_data
core           INFO 	Processing timing data...
req            INFO 	Using cached data for car_data
req            INFO 	Using cached data for position_data
req            INFO 	Using cached data for weather_data
req            INFO 	Using cached data for race_control_messages
core           INFO 	Finished loading data for 20 drivers: ['1', '16', '11', '14', '81', '4', '63', '44', '22', '18', '38', '23', '20', '3', '27', '77', '31', '10', '2', '24']
   DriverNumber BroadcastName Abbreviation DriverId         TeamName TeamColor TeamId  FirstName    LastName          FullName                                                                                                                                               HeadshotUrl CountryCode  Position ClassifiedPosition  GridPosition                     Q1                     Q2                     Q3 Time Status  Points
1             1  M VERSTAPPEN          VER           Red Bull Racing    3671c6               Max  Verstappen    Max Verstappen    https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/M/MAXVER01_Max_Verstappen/maxver01.png.transform/1col/image.png         NED       1.0                              NaN 0 days 00:01:28.171000 0 days 00:01:28.033000 0 days 00:01:27.472000  NaT            NaN
16           16     C LECLERC          LEC                   Ferrari    e8002d           Charles     Leclerc   Charles Leclerc   https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/C/CHALEC01_Charles_Leclerc/chalec01.png.transform/1col/image.png         MON       2.0                              NaN 0 days 00:01:28.318000 0 days 00:01:28.112000 0 days 00:01:27.791000  NaT            NaN
11           11       S PEREZ          PER           Red Bull Racing    3671c6            Sergio       Perez      Sergio Perez      https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/S/SERPER01_Sergio_Perez/serper01.png.transform/1col/image.png         MEX       3.0                              NaN 0 days 00:01:28.638000 0 days 00:01:28.467000 0 days 00:01:27.807000  NaT            NaN
14           14      F ALONSO          ALO              Aston Martin    229971          Fernando      Alonso   Fernando Alonso   https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/F/FERALO01_Fernando_Alonso/feralo01.png.transform/1col/image.png         ESP       4.0                              NaN 0 days 00:01:28.706000 0 days 00:01:28.122000 0 days 00:01:27.846000  NaT            NaN
81           81     O PIASTRI          PIA                   McLaren    ff8000             Oscar     Piastri     Oscar Piastri     https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/O/OSCPIA01_Oscar_Piastri/oscpia01.png.transform/1col/image.png         AUS       5.0                              NaN 0 days 00:01:28.755000 0 days 00:01:28.343000 0 days 00:01:28.089000  NaT            NaN
4             4      L NORRIS          NOR                   McLaren    ff8000             Lando      Norris      Lando Norris      https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/L/LANNOR01_Lando_Norris/lannor01.png.transform/1col/image.png         GBR       6.0                              NaN 0 days 00:01:28.805000 0 days 00:01:28.479000 0 days 00:01:28.132000  NaT            NaN
63           63     G RUSSELL          RUS                  Mercedes    27f4d2            George     Russell    George Russell    https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/G/GEORUS01_George_Russell/georus01.png.transform/1col/image.png         GBR       7.0                              NaN 0 days 00:01:28.749000 0 days 00:01:28.448000 0 days 00:01:28.316000  NaT            NaN
44           44    L HAMILTON          HAM                  Mercedes    27f4d2             Lewis    Hamilton    Lewis Hamilton    https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/L/LEWHAM01_Lewis_Hamilton/lewham01.png.transform/1col/image.png         GBR       8.0                              NaN 0 days 00:01:28.994000 0 days 00:01:28.606000 0 days 00:01:28.460000  NaT            NaN
22           22     Y TSUNODA          TSU                        RB    6692ff              Yuki     Tsunoda      Yuki Tsunoda      https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/Y/YUKTSU01_Yuki_Tsunoda/yuktsu01.png.transform/1col/image.png         JPN       9.0                              NaN 0 days 00:01:28.988000 0 days 00:01:28.564000 0 days 00:01:28.547000  NaT            NaN
18           18      L STROLL          STR              Aston Martin    229971             Lance      Stroll      Lance Stroll      https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/L/LANSTR01_Lance_Stroll/lanstr01.png.transform/1col/image.png         CAN      10.0                              NaN 0 days 00:01:28.250000 0 days 00:01:28.578000 0 days 00:01:28.572000  NaT            NaN
38           38     O BEARMAN          BEA                   Ferrari    e8002d            Oliver     Bearman    Oliver Bearman                                                                                                                                                      None         GBR      11.0                              NaN 0 days 00:01:28.984000 0 days 00:01:28.642000                    NaT  NaT            NaN
23           23       A ALBON          ALB                  Williams    64c4ff         Alexander       Albon   Alexander Albon   https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/A/ALEALB01_Alexander_Albon/alealb01.png.transform/1col/image.png         THA      12.0                              NaN 0 days 00:01:29.107000 0 days 00:01:28.980000                    NaT  NaT            NaN
20           20   K MAGNUSSEN          MAG              Haas F1 Team    b6babd             Kevin   Magnussen   Kevin Magnussen   https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/K/KEVMAG01_Kevin_Magnussen/kevmag01.png.transform/1col/image.png         DEN      13.0                              NaN 0 days 00:01:29.069000 0 days 00:01:29.020000                    NaT  NaT            NaN
3             3   D RICCIARDO          RIC                        RB    6692ff            Daniel   Ricciardo  Daniel Ricciardo  https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/D/DANRIC01_Daniel_Ricciardo/danric01.png.transform/1col/image.png         AUS      14.0                              NaN 0 days 00:01:29.065000 0 days 00:01:29.025000                    NaT  NaT            NaN
27           27  N HULKENBERG          HUL              Haas F1 Team    b6babd              Nico  Hulkenberg   Nico Hulkenberg   https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/N/NICHUL01_Nico_Hulkenberg/nichul01.png.transform/1col/image.png         GER      15.0                              NaN 0 days 00:01:29.055000                    NaT                    NaT  NaT            NaN
77           77      V BOTTAS          BOT               Kick Sauber    52e252          Valtteri      Bottas   Valtteri Bottas   https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/V/VALBOT01_Valtteri_Bottas/valbot01.png.transform/1col/image.png         FIN      16.0                              NaN 0 days 00:01:29.179000                    NaT                    NaT  NaT            NaN
31           31        E OCON          OCO                    Alpine    ff87bc           Esteban        Ocon      Esteban Ocon      https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/E/ESTOCO01_Esteban_Ocon/estoco01.png.transform/1col/image.png         FRA      17.0                              NaN 0 days 00:01:29.475000                    NaT                    NaT  NaT            NaN
10           10       P GASLY          GAS                    Alpine    ff87bc            Pierre       Gasly      Pierre Gasly      https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/P/PIEGAS01_Pierre_Gasly/piegas01.png.transform/1col/image.png         FRA      18.0                              NaN 0 days 00:01:29.479000                    NaT                    NaT  NaT            NaN
2             2    L SARGEANT          SAR                  Williams    64c4ff             Logan    Sargeant    Logan Sargeant    https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/L/LOGSAR01_Logan_Sargeant/logsar01.png.transform/1col/image.png         USA      19.0                              NaN 0 days 00:01:29.526000                    NaT                    NaT  NaT            NaN
24           24        G ZHOU          ZHO               Kick Sauber    52e252            Guanyu        Zhou       Guanyu Zhou       https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/G/GUAZHO01_Guanyu_Zhou/guazho01.png.transform/1col/image.png         CHN      20.0                              NaN                    NaT                    NaT                    NaT  NaT            NaN
```

### Reproduce the code example:

```python
import fastf1

event = fastf1.get_event(2024, 2)
q = event.get_qualifying()
q.load()
print(q.results)
```


### Error message:

```shell
Output with FASTF1_DEBUG=1:

  File "/venv/lib/python3.11/site-packages/fastf1/core.py", line 1415, in load
    self._load_drivers_results(livedata=livedata)
  File "/venv/lib/python3.11/site-packages/fastf1/core.py", line 2149, in _load_drivers_results
    driver_info_ergast = self._drivers_results_from_ergast(
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/core.py", line 2266, in _drivers_results_from_ergast
    response = _get_data()
               ^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/logger.py", line 157, in __wrapped
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/core.py", line 2252, in _get_data
    return self._ergast.get_qualifying_results(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 1127, in get_qualifying_results
    return self._build_default_result(endpoint='qualifying',
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 591, in _build_default_result
    return self._build_result(
           ^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 557, in _build_result
    return ErgastMultiResponse(
           ^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 350, in __init__
    self._content = [ErgastResultFrame(response=elem,
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 350, in <listcomp>
    self._content = [ErgastResultFrame(response=elem,
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 139, in __init__
    data = self._prepare_response(response, category, auto_cast)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 146, in _prepare_response
    _, data[i] = cls._flatten_element(data[i], category, cast)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 166, in _flatten_element
    _, subflat = cls._flatten_element(
                 ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/interface.py", line 159, in _flatten_element
    category['method'](nested, category, flat, cast=cast)
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/structure.py", line 150, in _flatten_by_rename
    value = mapping['type'](value)
            ^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.11/site-packages/fastf1/ergast/structure.py", line 23, in date_from_ergast
    return datetime.datetime.strptime(d_str, "%Y-%m-%d")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.pyenv/versions/3.11.2/lib/python3.11/_strptime.py", line 568, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/.pyenv/versions/3.11.2/lib/python3.11/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '' does not match format '%Y-%m-%d'
```



Discussion:
The DriverId field is also empty for all drivers



Patch:
diff --git a/fastf1/ergast/structure.py b/fastf1/ergast/structure.py
index 5a6ed3224..61170aaec 100644
--- a/fastf1/ergast/structure.py
+++ b/fastf1/ergast/structure.py
@@ -17,10 +17,15 @@
 # matches [hh:][mm:]ss[.micros][Z | +-hh:mm] timestring
 
 
-def date_from_ergast(d_str) -> datetime.datetime:
+def date_from_ergast(d_str) -> Optional[datetime.datetime]:
     """Create a ``datetime.datetime`` object from a date stamp formatted
     like 'YYYY-MM-DD'."""
-    return datetime.datetime.strptime(d_str, "%Y-%m-%d")
+    try:
+        return datetime.datetime.strptime(d_str, "%Y-%m-%d")
+    except ValueError:
+        logger.debug(f"Failed to parse date stamp '{d_str}' in Ergast"
+                     f"response.")
+        return None
 
 
 def time_from_ergast(t_str) -> Optional[datetime.time]:


Test patch:
diff --git a/fastf1/tests/test_ergast.py b/fastf1/tests/test_ergast.py
index 94e277ac3..1b2f2514a 100644
--- a/fastf1/tests/test_ergast.py
+++ b/fastf1/tests/test_ergast.py
@@ -27,6 +27,19 @@ def test_date_from_ergast():
     assert date_from_ergast('2022-10-25') == datetime.datetime(2022, 10, 25)
 
 
+@pytest.mark.parametrize(
+    "date_string",
+    (
+        "",
+        "huh?"
+    )
+)
+def test_date_from_ergast_errors(date_string, caplog):
+    caplog.set_level(logging.DEBUG)
+    assert date_from_ergast(date_string) is None
+    assert "Failed to parse" in caplog.text
+
+
 @pytest.mark.parametrize(
     "time_string, expected",
     (