Repository: dh-tech/undate-python (language: python)

Issue:
Allow partially known dates
In Undate class, right now it allows dates without a year, but it would be good if it would allow, for example, missing digits (e.g. 1991-1?-10).

- [x] support missing digits when initializing undate instance; calculate earliest/latest possible dates based on known digits
- [x] handle missing digits in string method
- [x] update duration methods for partially known dates
- [x] track date granularity/precision 
add an example comparing/testing undate against partial dates & durations in Shakespeare and Company Project dataset
create a jupyter notebook that loads S&co events dataset and installs undate; should go in our examples directory

for events with duration, test parsing start and end with undate and comparing the duration from undate with that in the public dataset

any discrepancies? if so, can we figure out why?


Discussion / hints:

Fix patch:
diff --git a/examples/notebooks/shxco_partial_date_durations.ipynb b/examples/notebooks/shxco_partial_date_durations.ipynb
new file mode 100644
index 0000000..11d6662
--- /dev/null
+++ b/examples/notebooks/shxco_partial_date_durations.ipynb
@@ -0,0 +1,5667 @@
+{
+  "nbformat": 4,
+  "nbformat_minor": 0,
+  "metadata": {
+    "colab": {
+      "provenance": [],
+      "toc_visible": true
+    },
+    "kernelspec": {
+      "name": "python3",
+      "display_name": "Python 3"
+    },
+    "language_info": {
+      "name": "python"
+    }
+  },
+  "cells": [
+    {
+      "cell_type": "markdown",
+      "source": [
+        "# undate partial date duration check\n",
+        "compare undate interval duration calculation for date rnages between partial dates with Shakespeare and Company Project events dataset"
+      ],
+      "metadata": {
+        "id": "s_holu9LI6q1"
+      }
+    },
+    {
+      "cell_type": "code",
+      "execution_count": 1,
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "TbokQJlu4G7Y",
+        "outputId": "d30849fd-811c-492d-ed37-a66ea4dd9088"
+      },
+      "outputs": [
+        {
+          "output_type": "stream",
+          "name": "stdout",
+          "text": [
+            "Collecting git+https://github.com/dh-tech/undate-python.git@story/3-partially-known-dates\n",
+            "  Cloning https://github.com/dh-tech/undate-python.git (to revision story/3-partially-known-dates) to /tmp/pip-req-build-aoklox4b\n",
+            "  Running command git clone --filter=blob:none --quiet https://github.com/dh-tech/undate-python.git /tmp/pip-req-build-aoklox4b\n",
+            "  Running command git checkout -b story/3-partially-known-dates --track origin/story/3-partially-known-dates\n",
+            "  Switched to a new branch 'story/3-partially-known-dates'\n",
+            "  Branch 'story/3-partially-known-dates' set up to track remote branch 'story/3-partially-known-dates' from 'origin'.\n",
+            "  Resolved https://github.com/dh-tech/undate-python.git to commit 615cb0d9af313128a562107305d1b7c2eddd9535\n",
+            "  Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
+            "  Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
+            "  Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
+            "Requirement already satisfied: python-dateutil in /usr/local/lib/python3.10/dist-packages (from undate==0.2.0.dev0) (2.8.2)\n",
+            "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil->undate==0.2.0.dev0) (1.16.0)\n",
+            "Building wheels for collected packages: undate\n",
+            "  Building wheel for undate (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
+            "  Created wheel for undate: filename=undate-0.2.0.dev0-py3-none-any.whl size=15200 sha256=ca2e25447c84ad830f1e7ac31a43d67701390d594fff44637a565c3de5bb6134\n",
+            "  Stored in directory: /tmp/pip-ephem-wheel-cache-ctzxaxcn/wheels/b0/dd/8f/69e3af2abd0249334bdcc1836876d45b86b0e1183e79b71123\n",
+            "Successfully built undate\n",
+            "Installing collected packages: undate\n",
+            "Successfully installed undate-0.2.0.dev0\n"
+          ]
+        }
+      ],
+      "source": [
+        "# install from feature branch for now, until merged\n",
+        "%pip install git+https://github.com/dh-tech/undate-python.git@story/3-partially-known-dates"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "import pandas as pd\n",
+        "\n",
+        "# load most recent version of S&co events dataset\n",
+        "\n",
+        "# dataspace link on S&co website is currently broken\n",
+        "#events_df = pd.read_csv(\"https://dataspace.princeton.edu/bitstream/88435/dsp019306t2441/2/SCoData_events_v1.2_2022-01.csv\")\n",
+        "# other dataset link resulting in an error; incomplete download?\n",
+        "# events_df = pd.read_csv(\"https://dataspace.princeton.edu/bitstream/88435/dsp019306t2441/1\")\n",
+        "events_df = pd.read_csv(\"https://github.com/rlskoeser/shxco-missingdata-specreading/raw/main/data/source-data/SCoData_events_v1.2_2022-01.csv\")\n",
+        "events_df.head()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 579
+        },
+        "id": "Q7KZRmj_4ySW",
+        "outputId": "ee3cacd7-c347-437a-ee8e-91a4086d6e88"
+      },
+      "execution_count": 2,
+      "outputs": [
+        {
+          "output_type": "stream",
+          "name": "stderr",
+          "text": [
+            "<ipython-input-2-7ea275849855>:9: DtypeWarning: Columns (20) have mixed types. Specify dtype option on import or set low_memory=False.\n",
+            "  events_df = pd.read_csv(\"https://github.com/rlskoeser/shxco-missingdata-specreading/raw/main/data/source-data/SCoData_events_v1.2_2022-01.csv\")\n"
+          ]
+        },
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "     event_type start_date    end_date  \\\n",
+              "0       Generic       1920         NaN   \n",
+              "1  Subscription       1921         NaN   \n",
+              "2        Borrow       1922  1922-08-23   \n",
+              "3       Generic       1922         NaN   \n",
+              "4  Subscription       1922         NaN   \n",
+              "\n",
+              "                                         member_uris        member_names  \\\n",
+              "0  https://shakespeareandco.princeton.edu/members...  Raymonde Linossier   \n",
+              "1  https://shakespeareandco.princeton.edu/members...         Mme Garreta   \n",
+              "2  https://shakespeareandco.princeton.edu/members...            Mr. Rhys   \n",
+              "3  https://shakespeareandco.princeton.edu/members...        Ernest Walsh   \n",
+              "4  https://shakespeareandco.princeton.edu/members...         Mr. Lincoln   \n",
+              "\n",
+              "     member_sort_names  subscription_price_paid  subscription_deposit  \\\n",
+              "0  Linossier, Raymonde                      NaN                   NaN   \n",
+              "1         Garreta, Mme                      NaN                   NaN   \n",
+              "2            Rhys, Mr.                      NaN                   NaN   \n",
+              "3        Walsh, Ernest                      NaN                   NaN   \n",
+              "4         Lincoln, Mr.                      NaN                   7.0   \n",
+              "\n",
+              "  subscription_duration  subscription_duration_days  ...  \\\n",
+              "0                   NaN                         NaN  ...   \n",
+              "1                   NaN                         NaN  ...   \n",
+              "2                   NaN                         NaN  ...   \n",
+              "3                   NaN                         NaN  ...   \n",
+              "4                   NaN                         NaN  ...   \n",
+              "\n",
+              "                                            item_uri       item_title  \\\n",
+              "0  https://shakespeareandco.princeton.edu/books/b...     Pigs Is Pigs   \n",
+              "1                                                NaN              NaN   \n",
+              "2  https://shakespeareandco.princeton.edu/books/c...          Typhoon   \n",
+              "3  https://shakespeareandco.princeton.edu/books/b...  The Pretty Lady   \n",
+              "4                                                NaN              NaN   \n",
+              "\n",
+              "  item_volume          item_authors item_year  item_notes  \\\n",
+              "0         NaN  Butler, Ellis Parker    1906.0         NaN   \n",
+              "1         NaN                   NaN       NaN         NaN   \n",
+              "2         NaN        Conrad, Joseph    1902.0         NaN   \n",
+              "3         NaN       Bennett, Arnold    1918.0         NaN   \n",
+              "4         NaN                   NaN       NaN         NaN   \n",
+              "\n",
+              "            source_type                                    source_citation  \\\n",
+              "0  Lending Library Card  Sylvia Beach, Raymonde Linossier Lending Libra...   \n",
+              "1          Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "2  Lending Library Card  Sylvia Beach, Rhys Lending Library Card, Box 4...   \n",
+              "3  Lending Library Card  Sylvia Beach, Ernest Walsh Lending Library Car...   \n",
+              "4          Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "\n",
+              "                                     source_manifest  \\\n",
+              "0  https://figgy.princeton.edu/concern/scanned_re...   \n",
+              "1                                                NaN   \n",
+              "2  https://figgy.princeton.edu/concern/scanned_re...   \n",
+              "3  https://figgy.princeton.edu/concern/scanned_re...   \n",
+              "4                                                NaN   \n",
+              "\n",
+              "                                        source_image  \n",
+              "0  https://iiif.princeton.edu/loris/figgy_prod/00...  \n",
+              "1                                                NaN  \n",
+              "2  https://iiif.princeton.edu/loris/figgy_prod/67...  \n",
+              "3  https://iiif.princeton.edu/loris/figgy_prod/af...  \n",
+              "4                                                NaN  \n",
+              "\n",
+              "[5 rows x 28 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-e2c09639-6f27-4153-9adc-148410c8c94d\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>event_type</th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>member_uris</th>\n",
+              "      <th>member_names</th>\n",
+              "      <th>member_sort_names</th>\n",
+              "      <th>subscription_price_paid</th>\n",
+              "      <th>subscription_deposit</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>...</th>\n",
+              "      <th>item_uri</th>\n",
+              "      <th>item_title</th>\n",
+              "      <th>item_volume</th>\n",
+              "      <th>item_authors</th>\n",
+              "      <th>item_year</th>\n",
+              "      <th>item_notes</th>\n",
+              "      <th>source_type</th>\n",
+              "      <th>source_citation</th>\n",
+              "      <th>source_manifest</th>\n",
+              "      <th>source_image</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>0</th>\n",
+              "      <td>Generic</td>\n",
+              "      <td>1920</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Raymonde Linossier</td>\n",
+              "      <td>Linossier, Raymonde</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>...</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/books/b...</td>\n",
+              "      <td>Pigs Is Pigs</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Butler, Ellis Parker</td>\n",
+              "      <td>1906.0</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Lending Library Card</td>\n",
+              "      <td>Sylvia Beach, Raymonde Linossier Lending Libra...</td>\n",
+              "      <td>https://figgy.princeton.edu/concern/scanned_re...</td>\n",
+              "      <td>https://iiif.princeton.edu/loris/figgy_prod/00...</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>1</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1921</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Mme Garreta</td>\n",
+              "      <td>Garreta, Mme</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>2</th>\n",
+              "      <td>Borrow</td>\n",
+              "      <td>1922</td>\n",
+              "      <td>1922-08-23</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Mr. Rhys</td>\n",
+              "      <td>Rhys, Mr.</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>...</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/books/c...</td>\n",
+              "      <td>Typhoon</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Conrad, Joseph</td>\n",
+              "      <td>1902.0</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Lending Library Card</td>\n",
+              "      <td>Sylvia Beach, Rhys Lending Library Card, Box 4...</td>\n",
+              "      <td>https://figgy.princeton.edu/concern/scanned_re...</td>\n",
+              "      <td>https://iiif.princeton.edu/loris/figgy_prod/67...</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>3</th>\n",
+              "      <td>Generic</td>\n",
+              "      <td>1922</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Ernest Walsh</td>\n",
+              "      <td>Walsh, Ernest</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>...</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/books/b...</td>\n",
+              "      <td>The Pretty Lady</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Bennett, Arnold</td>\n",
+              "      <td>1918.0</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Lending Library Card</td>\n",
+              "      <td>Sylvia Beach, Ernest Walsh Lending Library Car...</td>\n",
+              "      <td>https://figgy.princeton.edu/concern/scanned_re...</td>\n",
+              "      <td>https://iiif.princeton.edu/loris/figgy_prod/af...</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>4</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1922</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Mr. Lincoln</td>\n",
+              "      <td>Lincoln, Mr.</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>7.0</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>5 rows × 28 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-e2c09639-6f27-4153-9adc-148410c8c94d')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-e6c453fb-930e-4c93-812c-4d583fe0dbac\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-e6c453fb-930e-4c93-812c-4d583fe0dbac')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-e6c453fb-930e-4c93-812c-4d583fe0dbac button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-e2c09639-6f27-4153-9adc-148410c8c94d button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-e2c09639-6f27-4153-9adc-148410c8c94d');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 2
+        }
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "source": [
+        "## method to calculate durations\n",
+        "\n",
+        "define a method to initialize undate interval from start and end date string in ISO format as used in S&co datasets\n",
+        "\n",
+        "\n",
+        "**Note:** that there's an off-by-one discrepancy between how we currently calculate duration in undate and in the Shakespeare and Company Project code: the S&co code counts the first day in the range but not the last (could also be thought of as counting half of start and end dates)."
+      ],
+      "metadata": {
+        "id": "0Y6CsfIAJoqi"
+      }
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "from undate.undate import UndateInterval\n",
+        "from undate.dateformat.iso8601 import ISO8601DateFormat\n",
+        "\n",
+        "def undate_duration(start_date, end_date):\n",
+        "  isoformat = ISO8601DateFormat()\n",
+        "\n",
+        "  unstart = isoformat.parse(start_date)\n",
+        "  unend = isoformat.parse(end_date)\n",
+        "  interval = UndateInterval(earliest=unstart, latest=unend)\n",
+        "\n",
+        "  # subtract one here for simplicity of comparison,\n",
+        "  # to reconcile difference between how duration logic\n",
+        "\n",
+        "  return interval.duration().days - 1"
+      ],
+      "metadata": {
+        "id": "y_MqgrQW64uI"
+      },
+      "execution_count": 3,
+      "outputs": []
+    },
+    {
+      "cell_type": "markdown",
+      "source": [
+        "## subscription events\n",
+        "\n",
+        "compare subscription events with known duration"
+      ],
+      "metadata": {
+        "id": "JBVWMB7lJbYB"
+      }
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# identify subscription eventss with duration information\n",
+        "subs_duration = events_df[events_df.subscription_duration_days.notna()]\n",
+        "subs_duration.head()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 560
+        },
+        "id": "c8iPHU5K58cz",
+        "outputId": "c0cc72ef-ed0b-4a30-d7b5-ea21ef0582c7"
+      },
+      "execution_count": 4,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       event_type start_date end_date  \\\n",
+              "28   Subscription       1927     1928   \n",
+              "70   Subscription       1931     1932   \n",
+              "233  Subscription    1921-07  1921-08   \n",
+              "234  Subscription    1921-09  1922-02   \n",
+              "260  Subscription    1923-06  1923-10   \n",
+              "\n",
+              "                                           member_uris  \\\n",
+              "28   https://shakespeareandco.princeton.edu/members...   \n",
+              "70   https://shakespeareandco.princeton.edu/members...   \n",
+              "233  https://shakespeareandco.princeton.edu/members...   \n",
+              "234  https://shakespeareandco.princeton.edu/members...   \n",
+              "260  https://shakespeareandco.princeton.edu/members...   \n",
+              "\n",
+              "                                         member_names  \\\n",
+              "28                              Arthur Elliott Felkin   \n",
+              "70                Geraldine Deknatel;William Deknatel   \n",
+              "233                                  Mrs. G. S. Madam   \n",
+              "234  Anne Moderwell;Hiram Moderwell / H. K. Moderwell   \n",
+              "260                                      Victor Llona   \n",
+              "\n",
+              "                         member_sort_names  subscription_price_paid  \\\n",
+              "28                  Felkin, Arthur Elliott                      NaN   \n",
+              "70   Deknatel, Geraldine;Deknatel, William                      NaN   \n",
+              "233                      Madam, Mrs. G. S.                      NaN   \n",
+              "234       Moderwell, Anne;Moderwell, Hiram                      NaN   \n",
+              "260                          Llona, Victor                      NaN   \n",
+              "\n",
+              "     subscription_deposit subscription_duration  subscription_duration_days  \\\n",
+              "28                    NaN                1 year                       365.0   \n",
+              "70                    NaN                1 year                       365.0   \n",
+              "233                   NaN               1 month                        31.0   \n",
+              "234                   NaN              5 months                       153.0   \n",
+              "260                   NaN              4 months                       122.0   \n",
+              "\n",
+              "     ...  item_uri item_title item_volume  item_authors item_year  item_notes  \\\n",
+              "28   ...       NaN        NaN         NaN           NaN       NaN         NaN   \n",
+              "70   ...       NaN        NaN         NaN           NaN       NaN         NaN   \n",
+              "233  ...       NaN        NaN         NaN           NaN       NaN         NaN   \n",
+              "234  ...       NaN        NaN         NaN           NaN       NaN         NaN   \n",
+              "260  ...       NaN        NaN         NaN           NaN       NaN         NaN   \n",
+              "\n",
+              "      source_type                                    source_citation  \\\n",
+              "28   Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "70   Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "233  Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "234  Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "260  Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "\n",
+              "    source_manifest source_image  \n",
+              "28              NaN          NaN  \n",
+              "70              NaN          NaN  \n",
+              "233             NaN          NaN  \n",
+              "234             NaN          NaN  \n",
+              "260             NaN          NaN  \n",
+              "\n",
+              "[5 rows x 28 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-bae9ce09-21cf-4b61-ae42-635b2bbb1239\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>event_type</th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>member_uris</th>\n",
+              "      <th>member_names</th>\n",
+              "      <th>member_sort_names</th>\n",
+              "      <th>subscription_price_paid</th>\n",
+              "      <th>subscription_deposit</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>...</th>\n",
+              "      <th>item_uri</th>\n",
+              "      <th>item_title</th>\n",
+              "      <th>item_volume</th>\n",
+              "      <th>item_authors</th>\n",
+              "      <th>item_year</th>\n",
+              "      <th>item_notes</th>\n",
+              "      <th>source_type</th>\n",
+              "      <th>source_citation</th>\n",
+              "      <th>source_manifest</th>\n",
+              "      <th>source_image</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>28</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1927</td>\n",
+              "      <td>1928</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Arthur Elliott Felkin</td>\n",
+              "      <td>Felkin, Arthur Elliott</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>70</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1931</td>\n",
+              "      <td>1932</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Geraldine Deknatel;William Deknatel</td>\n",
+              "      <td>Deknatel, Geraldine;Deknatel, William</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>233</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1921-07</td>\n",
+              "      <td>1921-08</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Mrs. G. S. Madam</td>\n",
+              "      <td>Madam, Mrs. G. S.</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>234</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1921-09</td>\n",
+              "      <td>1922-02</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Anne Moderwell;Hiram Moderwell / H. K. Moderwell</td>\n",
+              "      <td>Moderwell, Anne;Moderwell, Hiram</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>153.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>260</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1923-06</td>\n",
+              "      <td>1923-10</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Victor Llona</td>\n",
+              "      <td>Llona, Victor</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>122.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>5 rows × 28 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-bae9ce09-21cf-4b61-ae42-635b2bbb1239')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-75145a1f-2cba-4094-be8b-9b746e87fa6d\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-75145a1f-2cba-4094-be8b-9b746e87fa6d')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-75145a1f-2cba-4094-be8b-9b746e87fa6d button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-bae9ce09-21cf-4b61-ae42-635b2bbb1239 button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-bae9ce09-21cf-4b61-ae42-635b2bbb1239');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 4
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# what do the subscription duration day values look like?\n",
+        "subs_duration.subscription_duration_days.value_counts()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "9i0aN7iQ6voY",
+        "outputId": "fe1ac93f-5571-4bd3-e4c1-06e90cf33f5c"
+      },
+      "execution_count": 5,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "31.0     2997\n",
+              "30.0     1975\n",
+              "92.0      936\n",
+              "91.0      397\n",
+              "365.0     337\n",
+              "         ... \n",
+              "69.0        1\n",
+              "36.0        1\n",
+              "73.0        1\n",
+              "574.0       1\n",
+              "171.0       1\n",
+              "Name: subscription_duration_days, Length: 133, dtype: int64"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 5
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "subs_duration.subscription_duration_days.describe()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "aGqi4LRp60tV",
+        "outputId": "fbd61c94-41ab-40a7-87c2-cf0548c75d5a"
+      },
+      "execution_count": 6,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "count    9146.000000\n",
+              "mean       72.142685\n",
+              "std        81.559368\n",
+              "min         1.000000\n",
+              "25%        30.000000\n",
+              "50%        31.000000\n",
+              "75%        91.000000\n",
+              "max       574.000000\n",
+              "Name: subscription_duration_days, dtype: float64"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 6
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# do we have unknown start/end date values?\n",
+        "subs_duration[subs_duration.start_date.isna()]"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 143
+        },
+        "id": "pUsAb16MKqvb",
+        "outputId": "27f3b8e7-c5a5-4297-eb7e-e37e81945dda"
+      },
+      "execution_count": 7,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "Empty DataFrame\n",
+              "Columns: [event_type, start_date, end_date, member_uris, member_names, member_sort_names, subscription_price_paid, subscription_deposit, subscription_duration, subscription_duration_days, subscription_volumes, subscription_category, subscription_purchase_date, reimbursement_refund, borrow_status, borrow_duration_days, purchase_price, currency, item_uri, item_title, item_volume, item_authors, item_year, item_notes, source_type, source_citation, source_manifest, source_image]\n",
+              "Index: []\n",
+              "\n",
+              "[0 rows x 28 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-07d03635-bd33-419c-8ec5-24507352ed9d\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>event_type</th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>member_uris</th>\n",
+              "      <th>member_names</th>\n",
+              "      <th>member_sort_names</th>\n",
+              "      <th>subscription_price_paid</th>\n",
+              "      <th>subscription_deposit</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>...</th>\n",
+              "      <th>item_uri</th>\n",
+              "      <th>item_title</th>\n",
+              "      <th>item_volume</th>\n",
+              "      <th>item_authors</th>\n",
+              "      <th>item_year</th>\n",
+              "      <th>item_notes</th>\n",
+              "      <th>source_type</th>\n",
+              "      <th>source_citation</th>\n",
+              "      <th>source_manifest</th>\n",
+              "      <th>source_image</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>0 rows × 28 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-07d03635-bd33-419c-8ec5-24507352ed9d')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-b98a2fc0-0e66-494c-969f-a8b210e4c260\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-b98a2fc0-0e66-494c-969f-a8b210e4c260')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-b98a2fc0-0e66-494c-969f-a8b210e4c260 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-07d03635-bd33-419c-8ec5-24507352ed9d button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-07d03635-bd33-419c-8ec5-24507352ed9d');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 7
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "subs_duration[subs_duration.end_date.isna()]"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 310
+        },
+        "id": "0odaog0eK0CN",
+        "outputId": "1e8814ff-0043-4969-b1d1-7574c3e82008"
+      },
+      "execution_count": 8,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "         event_type  start_date end_date  \\\n",
+              "13168  Subscription  1932-10-06      NaN   \n",
+              "13686  Subscription  1933-03-02      NaN   \n",
+              "\n",
+              "                                             member_uris  \\\n",
+              "13168  https://shakespeareandco.princeton.edu/members...   \n",
+              "13686  https://shakespeareandco.princeton.edu/members...   \n",
+              "\n",
+              "                                         member_names  \\\n",
+              "13168  Jean (Bakewell) Connolly / Mrs. Cyril Connolly   \n",
+              "13686                       Stanislas Pascal Franchot   \n",
+              "\n",
+              "                member_sort_names  subscription_price_paid  \\\n",
+              "13168              Connolly, Jean                      NaN   \n",
+              "13686  Franchot, Stanislas Pascal                      NaN   \n",
+              "\n",
+              "       subscription_deposit subscription_duration  subscription_duration_days  \\\n",
+              "13168                 100.0                   NaN                        31.0   \n",
+              "13686                  50.0                   NaN                        31.0   \n",
+              "\n",
+              "       ...  item_uri item_title item_volume  item_authors item_year  \\\n",
+              "13168  ...       NaN        NaN         NaN           NaN       NaN   \n",
+              "13686  ...       NaN        NaN         NaN           NaN       NaN   \n",
+              "\n",
+              "       item_notes                   source_type  \\\n",
+              "13168         NaN                       Logbook   \n",
+              "13686         NaN  Logbook;Lending Library Card   \n",
+              "\n",
+              "                                         source_citation  \\\n",
+              "13168  Sylvia Beach, Logbooks 1919–1941, Sylvia Beach...   \n",
+              "13686  Sylvia Beach, Logbooks 1919–1941, Sylvia Beach...   \n",
+              "\n",
+              "                                         source_manifest  \\\n",
+              "13168                                                NaN   \n",
+              "13686  ;https://figgy.princeton.edu/concern/scanned_r...   \n",
+              "\n",
+              "                                            source_image  \n",
+              "13168                                                NaN  \n",
+              "13686  ;https://iiif.princeton.edu/loris/figgy_prod/7...  \n",
+              "\n",
+              "[2 rows x 28 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-b7ae4256-83f5-42c2-b69a-2aa2d61412ef\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>event_type</th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>member_uris</th>\n",
+              "      <th>member_names</th>\n",
+              "      <th>member_sort_names</th>\n",
+              "      <th>subscription_price_paid</th>\n",
+              "      <th>subscription_deposit</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>...</th>\n",
+              "      <th>item_uri</th>\n",
+              "      <th>item_title</th>\n",
+              "      <th>item_volume</th>\n",
+              "      <th>item_authors</th>\n",
+              "      <th>item_year</th>\n",
+              "      <th>item_notes</th>\n",
+              "      <th>source_type</th>\n",
+              "      <th>source_citation</th>\n",
+              "      <th>source_manifest</th>\n",
+              "      <th>source_image</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>13168</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1932-10-06</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Jean (Bakewell) Connolly / Mrs. Cyril Connolly</td>\n",
+              "      <td>Connolly, Jean</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>100.0</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Logbook</td>\n",
+              "      <td>Sylvia Beach, Logbooks 1919–1941, Sylvia Beach...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>13686</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1933-03-02</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Stanislas Pascal Franchot</td>\n",
+              "      <td>Franchot, Stanislas Pascal</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>50.0</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Logbook;Lending Library Card</td>\n",
+              "      <td>Sylvia Beach, Logbooks 1919–1941, Sylvia Beach...</td>\n",
+              "      <td>;https://figgy.princeton.edu/concern/scanned_r...</td>\n",
+              "      <td>;https://iiif.princeton.edu/loris/figgy_prod/7...</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>2 rows × 28 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-b7ae4256-83f5-42c2-b69a-2aa2d61412ef')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-87db436a-6370-4428-b977-ca2d9b29bb82\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-87db436a-6370-4428-b977-ca2d9b29bb82')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-87db436a-6370-4428-b977-ca2d9b29bb82 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-b7ae4256-83f5-42c2-b69a-2aa2d61412ef button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-b7ae4256-83f5-42c2-b69a-2aa2d61412ef');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 8
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# omit events with unknown end date since we can't recalculate duration\n",
+        "# (duration in the dataset is based on the subscription duration)\n",
+        "subs_duration = subs_duration[subs_duration.end_date.notna()]"
+      ],
+      "metadata": {
+        "id": "jwvN9-CgLQRx"
+      },
+      "execution_count": 9,
+      "outputs": []
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# add a new field for duration as calculated by undate\n",
+        "subs_duration[\"undate_duration\"] = subs_duration.apply(lambda row: undate_duration(str(row.start_date), str(row.end_date)), axis=1)\n",
+        "subs_duration.head()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 560
+        },
+        "id": "Z-CVWd3z7Jb6",
+        "outputId": "d52d57d4-9803-4bfa-9708-bdf149c7098b"
+      },
+      "execution_count": 10,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       event_type start_date end_date  \\\n",
+              "28   Subscription       1927     1928   \n",
+              "70   Subscription       1931     1932   \n",
+              "233  Subscription    1921-07  1921-08   \n",
+              "234  Subscription    1921-09  1922-02   \n",
+              "260  Subscription    1923-06  1923-10   \n",
+              "\n",
+              "                                           member_uris  \\\n",
+              "28   https://shakespeareandco.princeton.edu/members...   \n",
+              "70   https://shakespeareandco.princeton.edu/members...   \n",
+              "233  https://shakespeareandco.princeton.edu/members...   \n",
+              "234  https://shakespeareandco.princeton.edu/members...   \n",
+              "260  https://shakespeareandco.princeton.edu/members...   \n",
+              "\n",
+              "                                         member_names  \\\n",
+              "28                              Arthur Elliott Felkin   \n",
+              "70                Geraldine Deknatel;William Deknatel   \n",
+              "233                                  Mrs. G. S. Madam   \n",
+              "234  Anne Moderwell;Hiram Moderwell / H. K. Moderwell   \n",
+              "260                                      Victor Llona   \n",
+              "\n",
+              "                         member_sort_names  subscription_price_paid  \\\n",
+              "28                  Felkin, Arthur Elliott                      NaN   \n",
+              "70   Deknatel, Geraldine;Deknatel, William                      NaN   \n",
+              "233                      Madam, Mrs. G. S.                      NaN   \n",
+              "234       Moderwell, Anne;Moderwell, Hiram                      NaN   \n",
+              "260                          Llona, Victor                      NaN   \n",
+              "\n",
+              "     subscription_deposit subscription_duration  subscription_duration_days  \\\n",
+              "28                    NaN                1 year                       365.0   \n",
+              "70                    NaN                1 year                       365.0   \n",
+              "233                   NaN               1 month                        31.0   \n",
+              "234                   NaN              5 months                       153.0   \n",
+              "260                   NaN              4 months                       122.0   \n",
+              "\n",
+              "     ...  item_title item_volume item_authors  item_year item_notes  \\\n",
+              "28   ...         NaN         NaN          NaN        NaN        NaN   \n",
+              "70   ...         NaN         NaN          NaN        NaN        NaN   \n",
+              "233  ...         NaN         NaN          NaN        NaN        NaN   \n",
+              "234  ...         NaN         NaN          NaN        NaN        NaN   \n",
+              "260  ...         NaN         NaN          NaN        NaN        NaN   \n",
+              "\n",
+              "      source_type                                    source_citation  \\\n",
+              "28   Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "70   Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "233  Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "234  Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "260  Address Book  Sylvia Beach, Address Book 1919–1935, box 69, ...   \n",
+              "\n",
+              "    source_manifest source_image undate_duration  \n",
+              "28              NaN          NaN             730  \n",
+              "70              NaN          NaN             730  \n",
+              "233             NaN          NaN              61  \n",
+              "234             NaN          NaN             180  \n",
+              "260             NaN          NaN             152  \n",
+              "\n",
+              "[5 rows x 29 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-f33feb85-a718-4801-ab8f-67c421130d0d\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>event_type</th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>member_uris</th>\n",
+              "      <th>member_names</th>\n",
+              "      <th>member_sort_names</th>\n",
+              "      <th>subscription_price_paid</th>\n",
+              "      <th>subscription_deposit</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>...</th>\n",
+              "      <th>item_title</th>\n",
+              "      <th>item_volume</th>\n",
+              "      <th>item_authors</th>\n",
+              "      <th>item_year</th>\n",
+              "      <th>item_notes</th>\n",
+              "      <th>source_type</th>\n",
+              "      <th>source_citation</th>\n",
+              "      <th>source_manifest</th>\n",
+              "      <th>source_image</th>\n",
+              "      <th>undate_duration</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>28</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1927</td>\n",
+              "      <td>1928</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Arthur Elliott Felkin</td>\n",
+              "      <td>Felkin, Arthur Elliott</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>730</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>70</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1931</td>\n",
+              "      <td>1932</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Geraldine Deknatel;William Deknatel</td>\n",
+              "      <td>Deknatel, Geraldine;Deknatel, William</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>730</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>233</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1921-07</td>\n",
+              "      <td>1921-08</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Mrs. G. S. Madam</td>\n",
+              "      <td>Madam, Mrs. G. S.</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>61</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>234</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1921-09</td>\n",
+              "      <td>1922-02</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Anne Moderwell;Hiram Moderwell / H. K. Moderwell</td>\n",
+              "      <td>Moderwell, Anne;Moderwell, Hiram</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>153.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>180</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>260</th>\n",
+              "      <td>Subscription</td>\n",
+              "      <td>1923-06</td>\n",
+              "      <td>1923-10</td>\n",
+              "      <td>https://shakespeareandco.princeton.edu/members...</td>\n",
+              "      <td>Victor Llona</td>\n",
+              "      <td>Llona, Victor</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>122.0</td>\n",
+              "      <td>...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>Address Book</td>\n",
+              "      <td>Sylvia Beach, Address Book 1919–1935, box 69, ...</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>NaN</td>\n",
+              "      <td>152</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>5 rows × 29 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-f33feb85-a718-4801-ab8f-67c421130d0d')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-24565bc5-ae3e-47a1-bb85-56f1d929981f\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-24565bc5-ae3e-47a1-bb85-56f1d929981f')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-24565bc5-ae3e-47a1-bb85-56f1d929981f button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-f33feb85-a718-4801-ab8f-67c421130d0d button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-f33feb85-a718-4801-ab8f-67c421130d0d');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 10
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# compare undate duration with dataset duration\n",
+        "# limit to fields we care about\n",
+        "subs_duration = subs_duration[['start_date', 'end_date', 'subscription_duration', 'subscription_duration_days', 'undate_duration']]\n",
+        "subs_duration"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 424
+        },
+        "id": "fVf6M2E2LgnH",
+        "outputId": "87e6585a-670d-466e-d206-caabaaa48df9"
+      },
+      "execution_count": 11,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       start_date    end_date subscription_duration  \\\n",
+              "28           1927        1928                1 year   \n",
+              "70           1931        1932                1 year   \n",
+              "233       1921-07     1921-08               1 month   \n",
+              "234       1921-09     1922-02              5 months   \n",
+              "260       1923-06     1923-10              4 months   \n",
+              "...           ...         ...                   ...   \n",
+              "35114  1941-11-24  1941-12-24               1 month   \n",
+              "35115  1941-11-24  1941-12-24               1 month   \n",
+              "35116  1941-12-04  1942-01-04               1 month   \n",
+              "35118  1941-12-08  1942-03-08              3 months   \n",
+              "35119  1941-12-09  1942-01-09               1 month   \n",
+              "\n",
+              "       subscription_duration_days  undate_duration  \n",
+              "28                          365.0              730  \n",
+              "70                          365.0              730  \n",
+              "233                          31.0               61  \n",
+              "234                         153.0              180  \n",
+              "260                         122.0              152  \n",
+              "...                           ...              ...  \n",
+              "35114                        30.0               30  \n",
+              "35115                        30.0               30  \n",
+              "35116                        31.0               31  \n",
+              "35118                        90.0               90  \n",
+              "35119                        31.0               31  \n",
+              "\n",
+              "[9144 rows x 5 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-3d1b6405-7503-489d-88ed-f757e8a972e7\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>28</th>\n",
+              "      <td>1927</td>\n",
+              "      <td>1928</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>70</th>\n",
+              "      <td>1931</td>\n",
+              "      <td>1932</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>233</th>\n",
+              "      <td>1921-07</td>\n",
+              "      <td>1921-08</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>61</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>234</th>\n",
+              "      <td>1921-09</td>\n",
+              "      <td>1922-02</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>153.0</td>\n",
+              "      <td>180</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>260</th>\n",
+              "      <td>1923-06</td>\n",
+              "      <td>1923-10</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>122.0</td>\n",
+              "      <td>152</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>...</th>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35114</th>\n",
+              "      <td>1941-11-24</td>\n",
+              "      <td>1941-12-24</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>30</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35115</th>\n",
+              "      <td>1941-11-24</td>\n",
+              "      <td>1941-12-24</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>30</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35116</th>\n",
+              "      <td>1941-12-04</td>\n",
+              "      <td>1942-01-04</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>31</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35118</th>\n",
+              "      <td>1941-12-08</td>\n",
+              "      <td>1942-03-08</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>90.0</td>\n",
+              "      <td>90</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35119</th>\n",
+              "      <td>1941-12-09</td>\n",
+              "      <td>1942-01-09</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>31</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>9144 rows × 5 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-3d1b6405-7503-489d-88ed-f757e8a972e7')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-acbdd6a1-0004-4082-85bb-a2887ee54241\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-acbdd6a1-0004-4082-85bb-a2887ee54241')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-acbdd6a1-0004-4082-85bb-a2887ee54241 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-3d1b6405-7503-489d-88ed-f757e8a972e7 button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-3d1b6405-7503-489d-88ed-f757e8a972e7');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 11
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# what's the difference between the two?\n",
+        "subs_duration['duration_diff'] = subs_duration.apply(lambda row: row.undate_duration - row.subscription_duration_days, axis=1)\n",
+        "subs_duration"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 424
+        },
+        "id": "drnCqTtsL835",
+        "outputId": "dc042b74-295a-436c-9c70-c6014d986cf7"
+      },
+      "execution_count": 12,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       start_date    end_date subscription_duration  \\\n",
+              "28           1927        1928                1 year   \n",
+              "70           1931        1932                1 year   \n",
+              "233       1921-07     1921-08               1 month   \n",
+              "234       1921-09     1922-02              5 months   \n",
+              "260       1923-06     1923-10              4 months   \n",
+              "...           ...         ...                   ...   \n",
+              "35114  1941-11-24  1941-12-24               1 month   \n",
+              "35115  1941-11-24  1941-12-24               1 month   \n",
+              "35116  1941-12-04  1942-01-04               1 month   \n",
+              "35118  1941-12-08  1942-03-08              3 months   \n",
+              "35119  1941-12-09  1942-01-09               1 month   \n",
+              "\n",
+              "       subscription_duration_days  undate_duration  duration_diff  \n",
+              "28                          365.0              730          365.0  \n",
+              "70                          365.0              730          365.0  \n",
+              "233                          31.0               61           30.0  \n",
+              "234                         153.0              180           27.0  \n",
+              "260                         122.0              152           30.0  \n",
+              "...                           ...              ...            ...  \n",
+              "35114                        30.0               30            0.0  \n",
+              "35115                        30.0               30            0.0  \n",
+              "35116                        31.0               31            0.0  \n",
+              "35118                        90.0               90            0.0  \n",
+              "35119                        31.0               31            0.0  \n",
+              "\n",
+              "[9144 rows x 6 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-219637cf-237c-4c69-bcd9-c53e2409e10b\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "      <th>duration_diff</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>28</th>\n",
+              "      <td>1927</td>\n",
+              "      <td>1928</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "      <td>365.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>70</th>\n",
+              "      <td>1931</td>\n",
+              "      <td>1932</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "      <td>365.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>233</th>\n",
+              "      <td>1921-07</td>\n",
+              "      <td>1921-08</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>61</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>234</th>\n",
+              "      <td>1921-09</td>\n",
+              "      <td>1922-02</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>153.0</td>\n",
+              "      <td>180</td>\n",
+              "      <td>27.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>260</th>\n",
+              "      <td>1923-06</td>\n",
+              "      <td>1923-10</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>122.0</td>\n",
+              "      <td>152</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>...</th>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35114</th>\n",
+              "      <td>1941-11-24</td>\n",
+              "      <td>1941-12-24</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35115</th>\n",
+              "      <td>1941-11-24</td>\n",
+              "      <td>1941-12-24</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35116</th>\n",
+              "      <td>1941-12-04</td>\n",
+              "      <td>1942-01-04</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35118</th>\n",
+              "      <td>1941-12-08</td>\n",
+              "      <td>1942-03-08</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>90.0</td>\n",
+              "      <td>90</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>35119</th>\n",
+              "      <td>1941-12-09</td>\n",
+              "      <td>1942-01-09</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>9144 rows × 6 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-219637cf-237c-4c69-bcd9-c53e2409e10b')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-deed31a2-402e-4398-a83b-0b23c1934849\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-deed31a2-402e-4398-a83b-0b23c1934849')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-deed31a2-402e-4398-a83b-0b23c1934849 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-219637cf-237c-4c69-bcd9-c53e2409e10b button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-219637cf-237c-4c69-bcd9-c53e2409e10b');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 12
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "subs_duration['duration_diff'].value_counts()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "z3i984igMNjm",
+        "outputId": "c8a3580e-a36a-4756-d427-286ba8e5cf91"
+      },
+      "execution_count": 13,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              " 0.0      9065\n",
+              " 30.0       30\n",
+              " 29.0       21\n",
+              " 1.0        10\n",
+              "-1.0         9\n",
+              " 28.0        4\n",
+              " 365.0       2\n",
+              " 27.0        1\n",
+              " 2.0         1\n",
+              "-3.0         1\n",
+              "Name: duration_diff, dtype: int64"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 13
+        }
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "source": [
+        "### investigate discrepancies"
+      ],
+      "metadata": {
+        "id": "Uu9kmAA_gm5o"
+      }
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# investigate the ones with larger differences\n",
+        "subset_subdurations = subs_duration[subs_duration.duration_diff != 0]\n",
+        "subset_subdurations"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 424
+        },
+        "id": "gdenGvR1MkUG",
+        "outputId": "589b6b49-3f9c-42d5-e01f-326401007878"
+      },
+      "execution_count": 15,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       start_date    end_date subscription_duration  \\\n",
+              "28           1927        1928                1 year   \n",
+              "70           1931        1932                1 year   \n",
+              "233       1921-07     1921-08               1 month   \n",
+              "234       1921-09     1922-02              5 months   \n",
+              "260       1923-06     1923-10              4 months   \n",
+              "...           ...         ...                   ...   \n",
+              "33878  1933-12-01  1934-01-01               1 month   \n",
+              "33880  1933-12-02  1934-01-02               1 month   \n",
+              "33902  1934-01-02  1934-07-02              6 months   \n",
+              "33936  1934-06-02  1934-12-02              6 months   \n",
+              "34892  1940-11-30  1940-12-30               1 month   \n",
+              "\n",
+              "       subscription_duration_days  undate_duration  duration_diff  \n",
+              "28                          365.0              730          365.0  \n",
+              "70                          365.0              730          365.0  \n",
+              "233                          31.0               61           30.0  \n",
+              "234                         153.0              180           27.0  \n",
+              "260                         122.0              152           30.0  \n",
+              "...                           ...              ...            ...  \n",
+              "33878                        30.0               31            1.0  \n",
+              "33880                        30.0               31            1.0  \n",
+              "33902                       182.0              181           -1.0  \n",
+              "33936                       184.0              183           -1.0  \n",
+              "34892                        31.0               30           -1.0  \n",
+              "\n",
+              "[79 rows x 6 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-7a1a028b-0e9b-43e5-9995-d53e26f03411\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "      <th>duration_diff</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>28</th>\n",
+              "      <td>1927</td>\n",
+              "      <td>1928</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "      <td>365.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>70</th>\n",
+              "      <td>1931</td>\n",
+              "      <td>1932</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "      <td>365.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>233</th>\n",
+              "      <td>1921-07</td>\n",
+              "      <td>1921-08</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>61</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>234</th>\n",
+              "      <td>1921-09</td>\n",
+              "      <td>1922-02</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>153.0</td>\n",
+              "      <td>180</td>\n",
+              "      <td>27.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>260</th>\n",
+              "      <td>1923-06</td>\n",
+              "      <td>1923-10</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>122.0</td>\n",
+              "      <td>152</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>...</th>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33878</th>\n",
+              "      <td>1933-12-01</td>\n",
+              "      <td>1934-01-01</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33880</th>\n",
+              "      <td>1933-12-02</td>\n",
+              "      <td>1934-01-02</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33902</th>\n",
+              "      <td>1934-01-02</td>\n",
+              "      <td>1934-07-02</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>182.0</td>\n",
+              "      <td>181</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33936</th>\n",
+              "      <td>1934-06-02</td>\n",
+              "      <td>1934-12-02</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>184.0</td>\n",
+              "      <td>183</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>34892</th>\n",
+              "      <td>1940-11-30</td>\n",
+              "      <td>1940-12-30</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>79 rows × 6 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-7a1a028b-0e9b-43e5-9995-d53e26f03411')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-9961c2b8-fcb3-4475-8018-0b612c6c184b\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-9961c2b8-fcb3-4475-8018-0b612c6c184b')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-9961c2b8-fcb3-4475-8018-0b612c6c184b button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-7a1a028b-0e9b-43e5-9995-d53e26f03411 button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-7a1a028b-0e9b-43e5-9995-d53e26f03411');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 15
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# too many to lok at once, can we segment by subscription duration?\n",
+        "subset_subdurations.subscription_duration.value_counts()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "9_w1Cwl2N81d",
+        "outputId": "c0733942-16cd-42bf-c9a3-abbf250e44f5"
+      },
+      "execution_count": 16,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "1 month      38\n",
+              "3 months     12\n",
+              "2 months      7\n",
+              "6 months      6\n",
+              "4 months      5\n",
+              "5 months      3\n",
+              "1 year        2\n",
+              "7 months      2\n",
+              "8 months      2\n",
+              "11 months     1\n",
+              "10 months     1\n",
+              "Name: subscription_duration, dtype: int64"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 16
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# lots of one-month subscriptions, what do the discrepancies look like?\n",
+        "subset_subdurations[subset_subdurations.subscription_duration == '1 month']"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 1000
+        },
+        "id": "snv1qguUOHPB",
+        "outputId": "dce76078-236b-48ee-9607-5d702cf4ee04"
+      },
+      "execution_count": 17,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       start_date    end_date subscription_duration  \\\n",
+              "233       1921-07     1921-08               1 month   \n",
+              "261       1923-08     1923-09               1 month   \n",
+              "271       1924-02     1924-03               1 month   \n",
+              "313       1926-11     1926-12               1 month   \n",
+              "354       1928-02     1928-03               1 month   \n",
+              "356       1928-02     1928-03               1 month   \n",
+              "393       1929-08     1929-09               1 month   \n",
+              "394       1929-08     1929-09               1 month   \n",
+              "430       1930-05     1930-06               1 month   \n",
+              "444       1930-11     1930-12               1 month   \n",
+              "462       1931-05     1931-06               1 month   \n",
+              "464       1931-06     1931-07               1 month   \n",
+              "466       1931-07     1931-08               1 month   \n",
+              "468       1931-08     1931-09               1 month   \n",
+              "472       1931-09     1931-10               1 month   \n",
+              "477       1931-10     1931-11               1 month   \n",
+              "478       1931-10     1931-11               1 month   \n",
+              "483       1931-11     1931-12               1 month   \n",
+              "484       1931-11     1931-12               1 month   \n",
+              "487       1931-12     1932-01               1 month   \n",
+              "492       1932-01     1932-02               1 month   \n",
+              "500       1932-02     1932-03               1 month   \n",
+              "501       1932-02     1932-03               1 month   \n",
+              "504       1932-03     1932-04               1 month   \n",
+              "516       1932-04     1932-05               1 month   \n",
+              "517       1932-05     1932-06               1 month   \n",
+              "7064   1926-09-15  1926-10-15               1 month   \n",
+              "31089  1923-11-22  1923-12-22               1 month   \n",
+              "31511  1924-11-08  1924-12-08               1 month   \n",
+              "31722  1925-05-09  1925-06-09               1 month   \n",
+              "32269  1926-06-10  1926-07-10               1 month   \n",
+              "32444  1926-10-07  1926-11-07               1 month   \n",
+              "33401  1929-05-18  1929-06-18               1 month   \n",
+              "33665  1932-12-15  1933-01-15               1 month   \n",
+              "33709  1933-02-03  1933-03-03               1 month   \n",
+              "33878  1933-12-01  1934-01-01               1 month   \n",
+              "33880  1933-12-02  1934-01-02               1 month   \n",
+              "34892  1940-11-30  1940-12-30               1 month   \n",
+              "\n",
+              "       subscription_duration_days  undate_duration  duration_diff  \n",
+              "233                          31.0               61           30.0  \n",
+              "261                          31.0               60           29.0  \n",
+              "271                          29.0               59           30.0  \n",
+              "313                          30.0               60           30.0  \n",
+              "354                          29.0               59           30.0  \n",
+              "356                          29.0               59           30.0  \n",
+              "393                          31.0               60           29.0  \n",
+              "394                          31.0               60           29.0  \n",
+              "430                          31.0               60           29.0  \n",
+              "444                          30.0               60           30.0  \n",
+              "462                          31.0               60           29.0  \n",
+              "464                          30.0               60           30.0  \n",
+              "466                          31.0               61           30.0  \n",
+              "468                          31.0               60           29.0  \n",
+              "472                          30.0               60           30.0  \n",
+              "477                          31.0               60           29.0  \n",
+              "478                          31.0               60           29.0  \n",
+              "483                          30.0               60           30.0  \n",
+              "484                          30.0               60           30.0  \n",
+              "487                          31.0               61           30.0  \n",
+              "492                          31.0               59           28.0  \n",
+              "500                          29.0               59           30.0  \n",
+              "501                          29.0               59           30.0  \n",
+              "504                          31.0               60           29.0  \n",
+              "516                          30.0               60           30.0  \n",
+              "517                          31.0               60           29.0  \n",
+              "7064                         31.0               30           -1.0  \n",
+              "31089                        31.0               30           -1.0  \n",
+              "31511                        31.0               30           -1.0  \n",
+              "31722                        30.0               31            1.0  \n",
+              "32269                        31.0               30           -1.0  \n",
+              "32444                        30.0               31            1.0  \n",
+              "33401                        30.0               31            1.0  \n",
+              "33665                        30.0               31            1.0  \n",
+              "33709                        31.0               28           -3.0  \n",
+              "33878                        30.0               31            1.0  \n",
+              "33880                        30.0               31            1.0  \n",
+              "34892                        31.0               30           -1.0  "
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-2f7de058-1381-42fc-a718-eeb5b40b6c00\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "      <th>duration_diff</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>233</th>\n",
+              "      <td>1921-07</td>\n",
+              "      <td>1921-08</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>61</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>261</th>\n",
+              "      <td>1923-08</td>\n",
+              "      <td>1923-09</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>271</th>\n",
+              "      <td>1924-02</td>\n",
+              "      <td>1924-03</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>29.0</td>\n",
+              "      <td>59</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>313</th>\n",
+              "      <td>1926-11</td>\n",
+              "      <td>1926-12</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>354</th>\n",
+              "      <td>1928-02</td>\n",
+              "      <td>1928-03</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>29.0</td>\n",
+              "      <td>59</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>356</th>\n",
+              "      <td>1928-02</td>\n",
+              "      <td>1928-03</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>29.0</td>\n",
+              "      <td>59</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>393</th>\n",
+              "      <td>1929-08</td>\n",
+              "      <td>1929-09</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>394</th>\n",
+              "      <td>1929-08</td>\n",
+              "      <td>1929-09</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>430</th>\n",
+              "      <td>1930-05</td>\n",
+              "      <td>1930-06</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>444</th>\n",
+              "      <td>1930-11</td>\n",
+              "      <td>1930-12</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>462</th>\n",
+              "      <td>1931-05</td>\n",
+              "      <td>1931-06</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>464</th>\n",
+              "      <td>1931-06</td>\n",
+              "      <td>1931-07</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>466</th>\n",
+              "      <td>1931-07</td>\n",
+              "      <td>1931-08</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>61</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>468</th>\n",
+              "      <td>1931-08</td>\n",
+              "      <td>1931-09</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>472</th>\n",
+              "      <td>1931-09</td>\n",
+              "      <td>1931-10</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>477</th>\n",
+              "      <td>1931-10</td>\n",
+              "      <td>1931-11</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>478</th>\n",
+              "      <td>1931-10</td>\n",
+              "      <td>1931-11</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>483</th>\n",
+              "      <td>1931-11</td>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>484</th>\n",
+              "      <td>1931-11</td>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>487</th>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>1932-01</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>61</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>492</th>\n",
+              "      <td>1932-01</td>\n",
+              "      <td>1932-02</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>59</td>\n",
+              "      <td>28.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>500</th>\n",
+              "      <td>1932-02</td>\n",
+              "      <td>1932-03</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>29.0</td>\n",
+              "      <td>59</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>501</th>\n",
+              "      <td>1932-02</td>\n",
+              "      <td>1932-03</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>29.0</td>\n",
+              "      <td>59</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>504</th>\n",
+              "      <td>1932-03</td>\n",
+              "      <td>1932-04</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>516</th>\n",
+              "      <td>1932-04</td>\n",
+              "      <td>1932-05</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>517</th>\n",
+              "      <td>1932-05</td>\n",
+              "      <td>1932-06</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>60</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>7064</th>\n",
+              "      <td>1926-09-15</td>\n",
+              "      <td>1926-10-15</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>31089</th>\n",
+              "      <td>1923-11-22</td>\n",
+              "      <td>1923-12-22</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>31511</th>\n",
+              "      <td>1924-11-08</td>\n",
+              "      <td>1924-12-08</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>31722</th>\n",
+              "      <td>1925-05-09</td>\n",
+              "      <td>1925-06-09</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>32269</th>\n",
+              "      <td>1926-06-10</td>\n",
+              "      <td>1926-07-10</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>32444</th>\n",
+              "      <td>1926-10-07</td>\n",
+              "      <td>1926-11-07</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33401</th>\n",
+              "      <td>1929-05-18</td>\n",
+              "      <td>1929-06-18</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33665</th>\n",
+              "      <td>1932-12-15</td>\n",
+              "      <td>1933-01-15</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33709</th>\n",
+              "      <td>1933-02-03</td>\n",
+              "      <td>1933-03-03</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>28</td>\n",
+              "      <td>-3.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33878</th>\n",
+              "      <td>1933-12-01</td>\n",
+              "      <td>1934-01-01</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33880</th>\n",
+              "      <td>1933-12-02</td>\n",
+              "      <td>1934-01-02</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>30.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>34892</th>\n",
+              "      <td>1940-11-30</td>\n",
+              "      <td>1940-12-30</td>\n",
+              "      <td>1 month</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>30</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-2f7de058-1381-42fc-a718-eeb5b40b6c00')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-2a0f387a-f2b6-4961-8df1-74b7f4c05a6a\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-2a0f387a-f2b6-4961-8df1-74b7f4c05a6a')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-2a0f387a-f2b6-4961-8df1-74b7f4c05a6a button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-2f7de058-1381-42fc-a718-eeb5b40b6c00 button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-2f7de058-1381-42fc-a718-eeb5b40b6c00');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 17
+        }
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "source": [
+        "The first set of these are calculated differently because they are partial dates; undate logic calculates based on earliest possible date through last possible date, but we have additional information in these cases that is project-specific and undate can't take into account, i.e. subscription duration is one month starting sometime in a known year or month.\n",
+        "\n",
+        "The handful towards the end that are off by one in either direction (+/-) are a little more concerning... (potential bug in S&co code? or value calculated based on known semantic duration?)"
+      ],
+      "metadata": {
+        "id": "Rm4jqlA4hq9E"
+      }
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# durations other than one month\n",
+        "subset_subdurations[subset_subdurations.subscription_duration != '1 month']"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 1000
+        },
+        "id": "TEL7qdNhOXHL",
+        "outputId": "50e051d5-18ae-4f24-a229-fc02fb610ed8"
+      },
+      "execution_count": 18,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       start_date    end_date subscription_duration  \\\n",
+              "28           1927        1928                1 year   \n",
+              "70           1931        1932                1 year   \n",
+              "234       1921-09     1922-02              5 months   \n",
+              "260       1923-06     1923-10              4 months   \n",
+              "272       1924-02     1924-04              2 months   \n",
+              "293       1926-03     1926-10              7 months   \n",
+              "321       1927-03     1928-02             11 months   \n",
+              "331       1927-07     1927-10              3 months   \n",
+              "337       1927-10     1928-06              8 months   \n",
+              "349       1928-01     1928-04              3 months   \n",
+              "388       1929-06     1930-04             10 months   \n",
+              "408       1930-01     1930-04              3 months   \n",
+              "409       1930-01     1930-04              3 months   \n",
+              "412       1930-01     1930-09              8 months   \n",
+              "415       1930-02     1930-06              4 months   \n",
+              "431       1930-05     1930-07              2 months   \n",
+              "437       1930-09     1930-12              3 months   \n",
+              "454       1930-12     1931-03              3 months   \n",
+              "459       1931-03     1931-05              2 months   \n",
+              "465       1931-07     1931-10              3 months   \n",
+              "471       1931-09     1931-12              3 months   \n",
+              "475       1931-09     1931-12              3 months   \n",
+              "476       1931-10     1932-03              5 months   \n",
+              "480       1931-10     1932-02              4 months   \n",
+              "485       1931-11     1932-06              7 months   \n",
+              "486       1931-12     1932-05              5 months   \n",
+              "489       1931-12     1932-02              2 months   \n",
+              "490       1931-12     1932-04              4 months   \n",
+              "496       1932-01     1932-03              2 months   \n",
+              "502       1932-02     1932-06              4 months   \n",
+              "506       1932-03     1932-05              2 months   \n",
+              "507       1932-03     1932-05              2 months   \n",
+              "709    1919-12-02  1920-06-02              6 months   \n",
+              "7560   1927-01-11  1927-04-11              3 months   \n",
+              "31480  1924-10-17  1925-04-17              6 months   \n",
+              "31917  1925-10-21  1926-01-21              3 months   \n",
+              "32613  1927-03-14  1927-06-14              3 months   \n",
+              "32671  1927-06-14  1927-12-14              6 months   \n",
+              "32869  1927-12-14  1928-06-14              6 months   \n",
+              "33902  1934-01-02  1934-07-02              6 months   \n",
+              "33936  1934-06-02  1934-12-02              6 months   \n",
+              "\n",
+              "       subscription_duration_days  undate_duration  duration_diff  \n",
+              "28                          365.0              730          365.0  \n",
+              "70                          365.0              730          365.0  \n",
+              "234                         153.0              180           27.0  \n",
+              "260                         122.0              152           30.0  \n",
+              "272                          60.0               89           29.0  \n",
+              "293                         214.0              244           30.0  \n",
+              "321                         337.0              365           28.0  \n",
+              "331                          92.0              122           30.0  \n",
+              "337                         244.0              273           29.0  \n",
+              "349                          91.0              120           29.0  \n",
+              "388                         304.0              333           29.0  \n",
+              "408                          90.0              119           29.0  \n",
+              "409                          90.0              119           29.0  \n",
+              "412                         243.0              272           29.0  \n",
+              "415                         120.0              149           29.0  \n",
+              "431                          61.0               91           30.0  \n",
+              "437                          91.0              121           30.0  \n",
+              "454                          90.0              120           30.0  \n",
+              "459                          61.0               91           30.0  \n",
+              "465                          92.0              122           30.0  \n",
+              "471                          91.0              121           30.0  \n",
+              "475                          91.0              121           30.0  \n",
+              "476                         152.0              182           30.0  \n",
+              "480                         123.0              151           28.0  \n",
+              "485                         213.0              242           29.0  \n",
+              "486                         152.0              182           30.0  \n",
+              "489                          62.0               90           28.0  \n",
+              "490                         122.0              151           29.0  \n",
+              "496                          60.0               90           30.0  \n",
+              "502                         121.0              150           29.0  \n",
+              "506                          61.0               91           30.0  \n",
+              "507                          61.0               91           30.0  \n",
+              "709                         182.0              183            1.0  \n",
+              "7560                         91.0               90           -1.0  \n",
+              "31480                       181.0              182            1.0  \n",
+              "31917                        91.0               92            1.0  \n",
+              "32613                        90.0               92            2.0  \n",
+              "32671                       184.0              183           -1.0  \n",
+              "32869                       182.0              183            1.0  \n",
+              "33902                       182.0              181           -1.0  \n",
+              "33936                       184.0              183           -1.0  "
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-fdb857cb-e906-47a0-86d0-f5d80fe5921f\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>subscription_duration</th>\n",
+              "      <th>subscription_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "      <th>duration_diff</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>28</th>\n",
+              "      <td>1927</td>\n",
+              "      <td>1928</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "      <td>365.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>70</th>\n",
+              "      <td>1931</td>\n",
+              "      <td>1932</td>\n",
+              "      <td>1 year</td>\n",
+              "      <td>365.0</td>\n",
+              "      <td>730</td>\n",
+              "      <td>365.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>234</th>\n",
+              "      <td>1921-09</td>\n",
+              "      <td>1922-02</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>153.0</td>\n",
+              "      <td>180</td>\n",
+              "      <td>27.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>260</th>\n",
+              "      <td>1923-06</td>\n",
+              "      <td>1923-10</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>122.0</td>\n",
+              "      <td>152</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>272</th>\n",
+              "      <td>1924-02</td>\n",
+              "      <td>1924-04</td>\n",
+              "      <td>2 months</td>\n",
+              "      <td>60.0</td>\n",
+              "      <td>89</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>293</th>\n",
+              "      <td>1926-03</td>\n",
+              "      <td>1926-10</td>\n",
+              "      <td>7 months</td>\n",
+              "      <td>214.0</td>\n",
+              "      <td>244</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>321</th>\n",
+              "      <td>1927-03</td>\n",
+              "      <td>1928-02</td>\n",
+              "      <td>11 months</td>\n",
+              "      <td>337.0</td>\n",
+              "      <td>365</td>\n",
+              "      <td>28.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>331</th>\n",
+              "      <td>1927-07</td>\n",
+              "      <td>1927-10</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>92.0</td>\n",
+              "      <td>122</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>337</th>\n",
+              "      <td>1927-10</td>\n",
+              "      <td>1928-06</td>\n",
+              "      <td>8 months</td>\n",
+              "      <td>244.0</td>\n",
+              "      <td>273</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>349</th>\n",
+              "      <td>1928-01</td>\n",
+              "      <td>1928-04</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>91.0</td>\n",
+              "      <td>120</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>388</th>\n",
+              "      <td>1929-06</td>\n",
+              "      <td>1930-04</td>\n",
+              "      <td>10 months</td>\n",
+              "      <td>304.0</td>\n",
+              "      <td>333</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>408</th>\n",
+              "      <td>1930-01</td>\n",
+              "      <td>1930-04</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>90.0</td>\n",
+              "      <td>119</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>409</th>\n",
+              "      <td>1930-01</td>\n",
+              "      <td>1930-04</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>90.0</td>\n",
+              "      <td>119</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>412</th>\n",
+              "      <td>1930-01</td>\n",
+              "      <td>1930-09</td>\n",
+              "      <td>8 months</td>\n",
+              "      <td>243.0</td>\n",
+              "      <td>272</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>415</th>\n",
+              "      <td>1930-02</td>\n",
+              "      <td>1930-06</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>120.0</td>\n",
+              "      <td>149</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>431</th>\n",
+              "      <td>1930-05</td>\n",
+              "      <td>1930-07</td>\n",
+              "      <td>2 months</td>\n",
+              "      <td>61.0</td>\n",
+              "      <td>91</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>437</th>\n",
+              "      <td>1930-09</td>\n",
+              "      <td>1930-12</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>91.0</td>\n",
+              "      <td>121</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>454</th>\n",
+              "      <td>1930-12</td>\n",
+              "      <td>1931-03</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>90.0</td>\n",
+              "      <td>120</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>459</th>\n",
+              "      <td>1931-03</td>\n",
+              "      <td>1931-05</td>\n",
+              "      <td>2 months</td>\n",
+              "      <td>61.0</td>\n",
+              "      <td>91</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>465</th>\n",
+              "      <td>1931-07</td>\n",
+              "      <td>1931-10</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>92.0</td>\n",
+              "      <td>122</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>471</th>\n",
+              "      <td>1931-09</td>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>91.0</td>\n",
+              "      <td>121</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>475</th>\n",
+              "      <td>1931-09</td>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>91.0</td>\n",
+              "      <td>121</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>476</th>\n",
+              "      <td>1931-10</td>\n",
+              "      <td>1932-03</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>152.0</td>\n",
+              "      <td>182</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>480</th>\n",
+              "      <td>1931-10</td>\n",
+              "      <td>1932-02</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>123.0</td>\n",
+              "      <td>151</td>\n",
+              "      <td>28.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>485</th>\n",
+              "      <td>1931-11</td>\n",
+              "      <td>1932-06</td>\n",
+              "      <td>7 months</td>\n",
+              "      <td>213.0</td>\n",
+              "      <td>242</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>486</th>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>1932-05</td>\n",
+              "      <td>5 months</td>\n",
+              "      <td>152.0</td>\n",
+              "      <td>182</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>489</th>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>1932-02</td>\n",
+              "      <td>2 months</td>\n",
+              "      <td>62.0</td>\n",
+              "      <td>90</td>\n",
+              "      <td>28.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>490</th>\n",
+              "      <td>1931-12</td>\n",
+              "      <td>1932-04</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>122.0</td>\n",
+              "      <td>151</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>496</th>\n",
+              "      <td>1932-01</td>\n",
+              "      <td>1932-03</td>\n",
+              "      <td>2 months</td>\n",
+              "      <td>60.0</td>\n",
+              "      <td>90</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>502</th>\n",
+              "      <td>1932-02</td>\n",
+              "      <td>1932-06</td>\n",
+              "      <td>4 months</td>\n",
+              "      <td>121.0</td>\n",
+              "      <td>150</td>\n",
+              "      <td>29.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>506</th>\n",
+              "      <td>1932-03</td>\n",
+              "      <td>1932-05</td>\n",
+              "      <td>2 months</td>\n",
+              "      <td>61.0</td>\n",
+              "      <td>91</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>507</th>\n",
+              "      <td>1932-03</td>\n",
+              "      <td>1932-05</td>\n",
+              "      <td>2 months</td>\n",
+              "      <td>61.0</td>\n",
+              "      <td>91</td>\n",
+              "      <td>30.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>709</th>\n",
+              "      <td>1919-12-02</td>\n",
+              "      <td>1920-06-02</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>182.0</td>\n",
+              "      <td>183</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>7560</th>\n",
+              "      <td>1927-01-11</td>\n",
+              "      <td>1927-04-11</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>91.0</td>\n",
+              "      <td>90</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>31480</th>\n",
+              "      <td>1924-10-17</td>\n",
+              "      <td>1925-04-17</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>181.0</td>\n",
+              "      <td>182</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>31917</th>\n",
+              "      <td>1925-10-21</td>\n",
+              "      <td>1926-01-21</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>91.0</td>\n",
+              "      <td>92</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>32613</th>\n",
+              "      <td>1927-03-14</td>\n",
+              "      <td>1927-06-14</td>\n",
+              "      <td>3 months</td>\n",
+              "      <td>90.0</td>\n",
+              "      <td>92</td>\n",
+              "      <td>2.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>32671</th>\n",
+              "      <td>1927-06-14</td>\n",
+              "      <td>1927-12-14</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>184.0</td>\n",
+              "      <td>183</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>32869</th>\n",
+              "      <td>1927-12-14</td>\n",
+              "      <td>1928-06-14</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>182.0</td>\n",
+              "      <td>183</td>\n",
+              "      <td>1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33902</th>\n",
+              "      <td>1934-01-02</td>\n",
+              "      <td>1934-07-02</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>182.0</td>\n",
+              "      <td>181</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>33936</th>\n",
+              "      <td>1934-06-02</td>\n",
+              "      <td>1934-12-02</td>\n",
+              "      <td>6 months</td>\n",
+              "      <td>184.0</td>\n",
+              "      <td>183</td>\n",
+              "      <td>-1.0</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-fdb857cb-e906-47a0-86d0-f5d80fe5921f')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-fe0398ea-6356-4025-a49b-84b52af2abf6\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-fe0398ea-6356-4025-a49b-84b52af2abf6')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-fe0398ea-6356-4025-a49b-84b52af2abf6 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-fdb857cb-e906-47a0-86d0-f5d80fe5921f button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-fdb857cb-e906-47a0-86d0-f5d80fe5921f');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 18
+        }
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "source": [
+        "## borrow events\n",
+        "\n",
+        "compare borrow events with known duration"
+      ],
+      "metadata": {
+        "id": "2tk6N7SXKKCu"
+      }
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "borrow_duration = events_df[events_df.borrow_duration_days.notna()]\n",
+        "# limit to fields we care about for this check\n",
+        "borrow_duration = borrow_duration[['start_date', 'end_date', 'borrow_duration_days']]\n",
+        "borrow_duration.head()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 206
+        },
+        "id": "fA1Nedmz6cyF",
+        "outputId": "5230d5ad-fec4-4353-a0d2-9676d1aa776d"
+      },
+      "execution_count": 19,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "    start_date end_date  borrow_duration_days\n",
+              "602    --01-07  --01-13                   6.0\n",
+              "603    --01-12  --01-20                   8.0\n",
+              "604    --01-16  --02-16                  31.0\n",
+              "605    --01-19  --01-24                   5.0\n",
+              "606    --01-20  --01-28                   8.0"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-ab39eba0-04d9-470e-88d2-9a65be8729a5\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>borrow_duration_days</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>602</th>\n",
+              "      <td>--01-07</td>\n",
+              "      <td>--01-13</td>\n",
+              "      <td>6.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>603</th>\n",
+              "      <td>--01-12</td>\n",
+              "      <td>--01-20</td>\n",
+              "      <td>8.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>604</th>\n",
+              "      <td>--01-16</td>\n",
+              "      <td>--02-16</td>\n",
+              "      <td>31.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>605</th>\n",
+              "      <td>--01-19</td>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>5.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>606</th>\n",
+              "      <td>--01-20</td>\n",
+              "      <td>--01-28</td>\n",
+              "      <td>8.0</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-ab39eba0-04d9-470e-88d2-9a65be8729a5')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-f71443cb-f157-4d75-aa33-0183611ceb91\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-f71443cb-f157-4d75-aa33-0183611ceb91')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-f71443cb-f157-4d75-aa33-0183611ceb91 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-ab39eba0-04d9-470e-88d2-9a65be8729a5 button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-ab39eba0-04d9-470e-88d2-9a65be8729a5');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 19
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "borrow_duration.tail()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 206
+        },
+        "id": "KPOBIRsTUKM9",
+        "outputId": "4a251445-e7c7-4250-82df-ece0bc9a3d56"
+      },
+      "execution_count": 20,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       start_date    end_date  borrow_duration_days\n",
+              "29903  1961-06-30  1961-10-04                  96.0\n",
+              "29904  1961-06-30  1961-10-04                  96.0\n",
+              "29905  1961-06-30  1961-10-04                  96.0\n",
+              "29907  1961-10-04  1962-03-21                 168.0\n",
+              "29908  1961-10-04  1962-03-21                 168.0"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-b5f0545c-b1ab-4afc-adcc-31c44fdf5daa\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>borrow_duration_days</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>29903</th>\n",
+              "      <td>1961-06-30</td>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>96.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29904</th>\n",
+              "      <td>1961-06-30</td>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>96.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29905</th>\n",
+              "      <td>1961-06-30</td>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>96.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29907</th>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>1962-03-21</td>\n",
+              "      <td>168.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29908</th>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>1962-03-21</td>\n",
+              "      <td>168.0</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-b5f0545c-b1ab-4afc-adcc-31c44fdf5daa')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-190f48cb-8bd9-4234-9886-f283753f01cc\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-190f48cb-8bd9-4234-9886-f283753f01cc')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-190f48cb-8bd9-4234-9886-f283753f01cc button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-b5f0545c-b1ab-4afc-adcc-31c44fdf5daa button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-b5f0545c-b1ab-4afc-adcc-31c44fdf5daa');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 20
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# add a new field for duration as calculated by undate\n",
+        "borrow_duration[\"undate_duration\"] = borrow_duration.apply(lambda row: undate_duration(str(row.start_date), str(row.end_date)), axis=1)\n",
+        "borrow_duration.head(10)"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 363
+        },
+        "id": "39nEPZva8jDo",
+        "outputId": "6cff4de2-c188-43ad-dc75-684c4d461029"
+      },
+      "execution_count": 21,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "    start_date end_date  borrow_duration_days  undate_duration\n",
+              "602    --01-07  --01-13                   6.0                6\n",
+              "603    --01-12  --01-20                   8.0                8\n",
+              "604    --01-16  --02-16                  31.0               31\n",
+              "605    --01-19  --01-24                   5.0                5\n",
+              "606    --01-20  --01-28                   8.0                8\n",
+              "607    --01-24  --03-20                  55.0               55\n",
+              "608    --01-24  --03-20                  55.0               55\n",
+              "609    --01-24  --03-20                  55.0               55\n",
+              "610    --01-24  --05-30                 126.0              126\n",
+              "611    --01-24  --05-30                 126.0              126"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-c5fdc2f7-0e15-422d-a18a-0b7d10087b67\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>borrow_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>602</th>\n",
+              "      <td>--01-07</td>\n",
+              "      <td>--01-13</td>\n",
+              "      <td>6.0</td>\n",
+              "      <td>6</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>603</th>\n",
+              "      <td>--01-12</td>\n",
+              "      <td>--01-20</td>\n",
+              "      <td>8.0</td>\n",
+              "      <td>8</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>604</th>\n",
+              "      <td>--01-16</td>\n",
+              "      <td>--02-16</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>31</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>605</th>\n",
+              "      <td>--01-19</td>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>5.0</td>\n",
+              "      <td>5</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>606</th>\n",
+              "      <td>--01-20</td>\n",
+              "      <td>--01-28</td>\n",
+              "      <td>8.0</td>\n",
+              "      <td>8</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>607</th>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>--03-20</td>\n",
+              "      <td>55.0</td>\n",
+              "      <td>55</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>608</th>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>--03-20</td>\n",
+              "      <td>55.0</td>\n",
+              "      <td>55</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>609</th>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>--03-20</td>\n",
+              "      <td>55.0</td>\n",
+              "      <td>55</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>610</th>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>--05-30</td>\n",
+              "      <td>126.0</td>\n",
+              "      <td>126</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>611</th>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>--05-30</td>\n",
+              "      <td>126.0</td>\n",
+              "      <td>126</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-c5fdc2f7-0e15-422d-a18a-0b7d10087b67')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-f45f0543-20ab-4ef2-8244-a03186637e68\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-f45f0543-20ab-4ef2-8244-a03186637e68')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-f45f0543-20ab-4ef2-8244-a03186637e68 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-c5fdc2f7-0e15-422d-a18a-0b7d10087b67 button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-c5fdc2f7-0e15-422d-a18a-0b7d10087b67');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 21
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# what's the difference between the two?\n",
+        "borrow_duration['duration_diff'] = borrow_duration.apply(lambda row: row.undate_duration - row.borrow_duration_days, axis=1)\n",
+        "borrow_duration"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 424
+        },
+        "id": "rL5S47wPWfd-",
+        "outputId": "127af40e-0037-4f99-d590-9cc2466a206b"
+      },
+      "execution_count": 22,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "       start_date    end_date  borrow_duration_days  undate_duration  \\\n",
+              "602       --01-07     --01-13                   6.0                6   \n",
+              "603       --01-12     --01-20                   8.0                8   \n",
+              "604       --01-16     --02-16                  31.0               31   \n",
+              "605       --01-19     --01-24                   5.0                5   \n",
+              "606       --01-20     --01-28                   8.0                8   \n",
+              "...           ...         ...                   ...              ...   \n",
+              "29903  1961-06-30  1961-10-04                  96.0               96   \n",
+              "29904  1961-06-30  1961-10-04                  96.0               96   \n",
+              "29905  1961-06-30  1961-10-04                  96.0               96   \n",
+              "29907  1961-10-04  1962-03-21                 168.0              168   \n",
+              "29908  1961-10-04  1962-03-21                 168.0              168   \n",
+              "\n",
+              "       duration_diff  \n",
+              "602              0.0  \n",
+              "603              0.0  \n",
+              "604              0.0  \n",
+              "605              0.0  \n",
+              "606              0.0  \n",
+              "...              ...  \n",
+              "29903            0.0  \n",
+              "29904            0.0  \n",
+              "29905            0.0  \n",
+              "29907            0.0  \n",
+              "29908            0.0  \n",
+              "\n",
+              "[19728 rows x 5 columns]"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-20d01b45-7e4a-4266-ae09-59fdf136b0fa\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>borrow_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "      <th>duration_diff</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "    <tr>\n",
+              "      <th>602</th>\n",
+              "      <td>--01-07</td>\n",
+              "      <td>--01-13</td>\n",
+              "      <td>6.0</td>\n",
+              "      <td>6</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>603</th>\n",
+              "      <td>--01-12</td>\n",
+              "      <td>--01-20</td>\n",
+              "      <td>8.0</td>\n",
+              "      <td>8</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>604</th>\n",
+              "      <td>--01-16</td>\n",
+              "      <td>--02-16</td>\n",
+              "      <td>31.0</td>\n",
+              "      <td>31</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>605</th>\n",
+              "      <td>--01-19</td>\n",
+              "      <td>--01-24</td>\n",
+              "      <td>5.0</td>\n",
+              "      <td>5</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>606</th>\n",
+              "      <td>--01-20</td>\n",
+              "      <td>--01-28</td>\n",
+              "      <td>8.0</td>\n",
+              "      <td>8</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>...</th>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "      <td>...</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29903</th>\n",
+              "      <td>1961-06-30</td>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>96.0</td>\n",
+              "      <td>96</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29904</th>\n",
+              "      <td>1961-06-30</td>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>96.0</td>\n",
+              "      <td>96</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29905</th>\n",
+              "      <td>1961-06-30</td>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>96.0</td>\n",
+              "      <td>96</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29907</th>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>1962-03-21</td>\n",
+              "      <td>168.0</td>\n",
+              "      <td>168</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "    <tr>\n",
+              "      <th>29908</th>\n",
+              "      <td>1961-10-04</td>\n",
+              "      <td>1962-03-21</td>\n",
+              "      <td>168.0</td>\n",
+              "      <td>168</td>\n",
+              "      <td>0.0</td>\n",
+              "    </tr>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "<p>19728 rows × 5 columns</p>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-20d01b45-7e4a-4266-ae09-59fdf136b0fa')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-8b0a94ac-5af6-4df4-8f48-4a9002e8e2ed\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-8b0a94ac-5af6-4df4-8f48-4a9002e8e2ed')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-8b0a94ac-5af6-4df4-8f48-4a9002e8e2ed button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-20d01b45-7e4a-4266-ae09-59fdf136b0fa button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-20d01b45-7e4a-4266-ae09-59fdf136b0fa');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 22
+        }
+      ]
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "# what do the duration differences look like?\n",
+        "borrow_duration.duration_diff.value_counts()"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "DQumLSXZW7r6",
+        "outputId": "fc5196d6-9d9a-430e-ecb2-c142676c3614"
+      },
+      "execution_count": 23,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "0.0    19728\n",
+              "Name: duration_diff, dtype: int64"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 23
+        }
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "source": [
+        "Woohoo, everything matches! 🎉\n",
+        "\n",
+        "In a previous run, there were two borrow events where the calculation did not match; this was due to an error in undate duration method when the start and end dates have unknown years and dates wrap to the following year (e.g., december to january), which has now been corrected.\n",
+        "\n",
+        "**Note:** One of those events has a range (--06-07/--06-06) that looks like a data error in S&co, but the data matches what is [written on the lending card](https://shakespeareandco.princeton.edu/members/davet-yvonne/cards/cf96d38f-e651-491c-a575-131ea32ce425/#)."
+      ],
+      "metadata": {
+        "id": "r0TUYWzSXIil"
+      }
+    },
+    {
+      "cell_type": "code",
+      "source": [
+        "borrow_duration[borrow_duration.duration_diff != 0]"
+      ],
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/",
+          "height": 49
+        },
+        "id": "-Bq76gtDWljg",
+        "outputId": "f1ee526d-b938-4cbf-e93c-c6c91c077ae7"
+      },
+      "execution_count": 24,
+      "outputs": [
+        {
+          "output_type": "execute_result",
+          "data": {
+            "text/plain": [
+              "Empty DataFrame\n",
+              "Columns: [start_date, end_date, borrow_duration_days, undate_duration, duration_diff]\n",
+              "Index: []"
+            ],
+            "text/html": [
+              "\n",
+              "\n",
+              "  <div id=\"df-6ffd1392-f46c-4c4e-bd66-b09d7bba99f2\">\n",
+              "    <div class=\"colab-df-container\">\n",
+              "      <div>\n",
+              "<style scoped>\n",
+              "    .dataframe tbody tr th:only-of-type {\n",
+              "        vertical-align: middle;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe tbody tr th {\n",
+              "        vertical-align: top;\n",
+              "    }\n",
+              "\n",
+              "    .dataframe thead th {\n",
+              "        text-align: right;\n",
+              "    }\n",
+              "</style>\n",
+              "<table border=\"1\" class=\"dataframe\">\n",
+              "  <thead>\n",
+              "    <tr style=\"text-align: right;\">\n",
+              "      <th></th>\n",
+              "      <th>start_date</th>\n",
+              "      <th>end_date</th>\n",
+              "      <th>borrow_duration_days</th>\n",
+              "      <th>undate_duration</th>\n",
+              "      <th>duration_diff</th>\n",
+              "    </tr>\n",
+              "  </thead>\n",
+              "  <tbody>\n",
+              "  </tbody>\n",
+              "</table>\n",
+              "</div>\n",
+              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-6ffd1392-f46c-4c4e-bd66-b09d7bba99f2')\"\n",
+              "              title=\"Convert this dataframe to an interactive table.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "       width=\"24px\">\n",
+              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
+              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
+              "  </svg>\n",
+              "      </button>\n",
+              "\n",
+              "\n",
+              "\n",
+              "    <div id=\"df-d730d31a-e261-459e-abe7-b0e296a54684\">\n",
+              "      <button class=\"colab-df-quickchart\" onclick=\"quickchart('df-d730d31a-e261-459e-abe7-b0e296a54684')\"\n",
+              "              title=\"Suggest charts.\"\n",
+              "              style=\"display:none;\">\n",
+              "\n",
+              "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
+              "     width=\"24px\">\n",
+              "    <g>\n",
+              "        <path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"/>\n",
+              "    </g>\n",
+              "</svg>\n",
+              "      </button>\n",
+              "    </div>\n",
+              "\n",
+              "<style>\n",
+              "  .colab-df-quickchart {\n",
+              "    background-color: #E8F0FE;\n",
+              "    border: none;\n",
+              "    border-radius: 50%;\n",
+              "    cursor: pointer;\n",
+              "    display: none;\n",
+              "    fill: #1967D2;\n",
+              "    height: 32px;\n",
+              "    padding: 0 0 0 0;\n",
+              "    width: 32px;\n",
+              "  }\n",
+              "\n",
+              "  .colab-df-quickchart:hover {\n",
+              "    background-color: #E2EBFA;\n",
+              "    box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "    fill: #174EA6;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart {\n",
+              "    background-color: #3B4455;\n",
+              "    fill: #D2E3FC;\n",
+              "  }\n",
+              "\n",
+              "  [theme=dark] .colab-df-quickchart:hover {\n",
+              "    background-color: #434B5C;\n",
+              "    box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "    filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "    fill: #FFFFFF;\n",
+              "  }\n",
+              "</style>\n",
+              "\n",
+              "    <script>\n",
+              "      async function quickchart(key) {\n",
+              "        const containerElement = document.querySelector('#' + key);\n",
+              "        const charts = await google.colab.kernel.invokeFunction(\n",
+              "            'suggestCharts', [key], {});\n",
+              "      }\n",
+              "    </script>\n",
+              "\n",
+              "      <script>\n",
+              "\n",
+              "function displayQuickchartButton(domScope) {\n",
+              "  let quickchartButtonEl =\n",
+              "    domScope.querySelector('#df-d730d31a-e261-459e-abe7-b0e296a54684 button.colab-df-quickchart');\n",
+              "  quickchartButtonEl.style.display =\n",
+              "    google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "}\n",
+              "\n",
+              "        displayQuickchartButton(document);\n",
+              "      </script>\n",
+              "      <style>\n",
+              "    .colab-df-container {\n",
+              "      display:flex;\n",
+              "      flex-wrap:wrap;\n",
+              "      gap: 12px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert {\n",
+              "      background-color: #E8F0FE;\n",
+              "      border: none;\n",
+              "      border-radius: 50%;\n",
+              "      cursor: pointer;\n",
+              "      display: none;\n",
+              "      fill: #1967D2;\n",
+              "      height: 32px;\n",
+              "      padding: 0 0 0 0;\n",
+              "      width: 32px;\n",
+              "    }\n",
+              "\n",
+              "    .colab-df-convert:hover {\n",
+              "      background-color: #E2EBFA;\n",
+              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
+              "      fill: #174EA6;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert {\n",
+              "      background-color: #3B4455;\n",
+              "      fill: #D2E3FC;\n",
+              "    }\n",
+              "\n",
+              "    [theme=dark] .colab-df-convert:hover {\n",
+              "      background-color: #434B5C;\n",
+              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
+              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
+              "      fill: #FFFFFF;\n",
+              "    }\n",
+              "  </style>\n",
+              "\n",
+              "      <script>\n",
+              "        const buttonEl =\n",
+              "          document.querySelector('#df-6ffd1392-f46c-4c4e-bd66-b09d7bba99f2 button.colab-df-convert');\n",
+              "        buttonEl.style.display =\n",
+              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
+              "\n",
+              "        async function convertToInteractive(key) {\n",
+              "          const element = document.querySelector('#df-6ffd1392-f46c-4c4e-bd66-b09d7bba99f2');\n",
+              "          const dataTable =\n",
+              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
+              "                                                     [key], {});\n",
+              "          if (!dataTable) return;\n",
+              "\n",
+              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
+              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
+              "            + ' to learn more about interactive tables.';\n",
+              "          element.innerHTML = '';\n",
+              "          dataTable['output_type'] = 'display_data';\n",
+              "          await google.colab.output.renderOutput(dataTable, element);\n",
+              "          const docLink = document.createElement('div');\n",
+              "          docLink.innerHTML = docLinkHtml;\n",
+              "          element.appendChild(docLink);\n",
+              "        }\n",
+              "      </script>\n",
+              "    </div>\n",
+              "  </div>\n"
+            ]
+          },
+          "metadata": {},
+          "execution_count": 24
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index 8d04412..217c8ee 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -58,9 +58,10 @@ test =
   pytest-ordering
   pytest-cov
 docs =
-  sphinx
+  sphinx<7.0.0  
   sphinx_rtd_theme
   m2r2
+# pin sphinx because 7.0 currently not compatible with rtd theme
 
 [options.packages.find]
 where = src
diff --git a/src/undate/dateformat/iso8601.py b/src/undate/dateformat/iso8601.py
index 22aff07..eb7e8eb 100644
--- a/src/undate/dateformat/iso8601.py
+++ b/src/undate/dateformat/iso8601.py
@@ -48,17 +48,16 @@ def to_string(self, undate: Undate) -> str:
         date_parts: List[Union[str, None]] = []
         # for each part of the date that is known, generate the string format
         # then combine
-        for date_portion, known in undate.known_values.items():
-            if known:
+        # TODO: should error if we have year and day but no month
+        for date_portion, iso_format in self.iso_format.items():
+            if undate.is_known(date_portion):
                 # NOTE: datetime strftime for %Y for 3-digit year
                 # results in leading zero in some environments
                 # and not others; force year to always be 4 digits
                 if date_portion == "year":
                     date_parts.append("%04d" % undate.earliest.year)
                 else:
-                    date_parts.append(
-                        undate.earliest.strftime(self.iso_format[date_portion])
-                    )
+                    date_parts.append(undate.earliest.strftime(iso_format))
             elif date_portion == "year":
                 # if not known but this is year, add '-' for --MM-DD unknown year format
                 date_parts.append("-")
diff --git a/src/undate/undate.py b/src/undate/undate.py
index 566f869..e816adb 100644
--- a/src/undate/undate.py
+++ b/src/undate/undate.py
@@ -1,5 +1,7 @@
 import datetime
 from calendar import monthrange
+from enum import Enum, auto
+import re
 
 # Pre 3.10 requires Union for multiple types, e.g. Union[int, None] instead of int | None
 from typing import Optional, Dict, Union
@@ -9,14 +11,29 @@
 from undate.dateformat.base import BaseDateFormat
 
 
-# duration of a single day
+#: duration of a single day
 ONE_DAY = datetime.timedelta(days=1)
 
 
+class DatePrecision(Enum):
+    """date precision, to indicate date precision independent from how much
+    of the date is known."""
+
+    #: year
+    YEAR = auto()
+    #: month
+    MONTH = auto()
+    #: day
+    DAY = auto()
+
+
 class Undate:
     """Simple object for representing uncertain, fuzzy or partially unknown dates"""
 
-    DEFAULT_FORMAT = "ISO8601"
+    DEFAULT_FORMAT: str = "ISO8601"
+
+    #: symbol for unknown digits within a date value
+    MISSING_DIGIT: str = "X"
 
     earliest: Union[datetime.date, None] = None
     latest: Union[datetime.date, None] = None
@@ -24,42 +41,104 @@ class Undate:
     #: Labels are not taken into account when comparing undate objects.
     label: Union[str, None] = None
     formatter: Union[BaseDateFormat, None] = None
+    #: precision of the date (day, month, year, etc.)
+    precision: DatePrecision = None
+
+    #: known non-leap year
+    NON_LEAP_YEAR: int = 2022
 
     def __init__(
         self,
-        year: Optional[int] = None,
-        month: Optional[int] = None,
-        day: Optional[int] = None,
+        year: Optional[Union[int, str]] = None,
+        month: Optional[Union[int, str]] = None,
+        day: Optional[Union[int, str]] = None,
         formatter: Optional[BaseDateFormat] = None,
         label: Optional[str] = None,
     ):
-        # TODO: support initializing for unknown values in each of these
-        # e.g., maybe values could be string or int; if string with
-        # unknown digits, calculate min/max for unknowns
+        # keep track of initial values and which values are known
+        self.initial_values: Dict[str, Union[int, str]] = {
+            "year": year,
+            "month": month,
+            "day": day,
+        }
+        if day:
+            self.precision = DatePrecision.DAY
+        elif month:
+            self.precision = DatePrecision.MONTH
+        elif year:
+            self.precision = DatePrecision.YEAR
+
+        # TODO: refactor partial date min/max calculations
+
+        if year is not None:
+            try:
+                year = int(year)
+                # update initial value since it is used to determine
+                # whether or not year is known
+                self.initial_values["year"] = year
+                min_year = max_year = year
+            except ValueError:
+                # year is a string that can't be converted to int
+                min_year = int(year.replace(self.MISSING_DIGIT, "0"))
+                max_year = int(year.replace(self.MISSING_DIGIT, "9"))
+        else:
+            min_year = datetime.MINYEAR
+            max_year = datetime.MAXYEAR
+
+        # if month is passed in as a string but completely unknown,
+        # treat as none
+        # TODO: we should preserve this information somehow;
+        # difference between just a year and and an unknown month within a year
+        # maybe in terms of granularity / size ?
+        if month == "XX":
+            month = None
+
+        min_month = 1
+        max_month = 12
+        if month is not None:
+            try:
+                # treat as an integer if we can
+                month = int(month)
+                # update initial value
+                self.initial_values["month"] = month
+                min_month = max_month = month
+            except ValueError:
+                # if not, calculate min/max for missing digits
+                min_month, max_month = self._missing_digit_minmax(
+                    month, min_month, max_month
+                )
+
+        # similar to month above — unknown day, but day-level granularity
+        if day == "XX":
+            day = None
+
+        if isinstance(day, int) or isinstance(day, str) and day.isnumeric():
+            day = int(day)
+            # update initial value - fully known day
+            self.initial_values["day"] = day
+            min_day = max_day = day
+        else:
+            # if we have no day or partial day, calculate min / max
+            min_day = 1
+            # if we know year and month (or max month), calculate exactly
+            if year and month:
+                _, max_day = monthrange(year, max_month)
+            elif year is None and month:
+                # If we don't have year and month,
+                # calculate based on a known non-leap year
+                # (better than just setting 31, but still not great)
+                _, max_day = monthrange(self.NON_LEAP_YEAR, max_month)
+            else:
+                max_day: int = 31
+
+            # if day is partially specified, narrow min/max further
+            if day is not None:
+                min_day, max_day = self._missing_digit_minmax(day, min_day, max_day)
 
         # for unknowns, assume smallest possible value for earliest and
         # largest valid for latest
-        self.earliest = datetime.date(year or datetime.MINYEAR, month or 1, day or 1)
-        # if day is unknown but we have year and month, calculate max day
-        if day is None and year and month:
-            _, maxday = monthrange(year, month)
-        elif day is None and year is None and month:
-            # TODO: what to do if we don't have year and month?
-            # This will produce bad data if the year is a leap year and the month is February
-            # 2022 chosen below as it is not a not leap year
-            # Better than just setting 31, but still not great
-            _, maxday = monthrange(2022, month)
-        else:
-            maxday: int = 31
-        self.latest = datetime.date(
-            year or datetime.MAXYEAR, month or 12, day or maxday
-        )
-        # keep track of which values are known
-        self.known_values: Dict[str, bool] = {
-            "year": year is not None,
-            "month": month is not None,
-            "day": day is not None,
-        }
+        self.earliest = datetime.date(min_year, min_month, min_day)
+        self.latest = datetime.date(max_year, max_month, max_day)
 
         if not formatter:
             # TODO subclass definitions not available unless they are imported where Undate() is called
@@ -69,6 +148,24 @@ def __init__(
         self.label = label
 
     def __str__(self) -> str:
+        # if any portion of the date is partially known, construct
+        # pseudo ISO8601 format here, since ISO8601 doesn't support unknown digits
+        # (temporary, should switch to default format that can handle it, e.g. EDTF)
+        if any(self.is_partially_known(part) for part in ["year", "month", "day"]):
+            # initial values could be either string or int
+            year = self.initial_values["year"]
+            month = self.initial_values["month"]
+            day = self.initial_values["day"]
+            # if integer, convert to string with correct number of digits
+            # replace unknown year with - for --MM or --MM-DD format
+            parts = [
+                f"{year:04d}" if isinstance(year, int) else year or "-",
+                f"{month:02d}" if isinstance(month, int) else month,
+                f"{day:02d}" if isinstance(day, int) else day,
+            ]
+            # combine, skipping any values that are None
+            return "-".join([str(p) for p in parts if p != None])
+
         return self.formatter.to_string(self)
 
     def __repr__(self) -> str:
@@ -82,18 +179,95 @@ def __eq__(self, other: "Undate") -> bool:
         return (
             self.earliest == other.earliest
             and self.latest == other.latest
-            and self.known_values == other.known_values
+            # NOTE: assumes that partially known values can only be written
+            # in one format (i.e. X for missing digits).
+            # If we support other formats, will need to normalize to common
+            # internal format for comparison
+            and self.initial_values == other.initial_values
         )
 
     @property
     def known_year(self) -> bool:
-        return self.known_values["year"]
+        return self.is_known("year")
+
+    def is_known(self, part: str) -> bool:
+        """Check if a part of the date (year, month, day) is known.
+        Returns False if unknown or only partially known."""
+        # TODO: should we use constants or enum for values?
+
+        # if we have an integer, then consider the date known
+        # if we have a string, then it is only partially known; return false
+        return isinstance(self.initial_values[part], int)
+
+    def is_partially_known(self, part: str) -> bool:
+        return isinstance(self.initial_values[part], str)
 
     def duration(self) -> datetime.timedelta:
-        # what is the duration of this date?
-        # subtract earliest from latest, and add a day to count the starting day
+        """What is the duration of this date?
+        Calculate based on earliest and latest date within range,
+        taking into account the precision of the date even if not all
+        parts of the date are known."""
+
+        # if precision is a single day, duration is one day
+        # no matter when it is or what else is known
+        if self.precision == DatePrecision.DAY:
+            return ONE_DAY
+
+        # if precision is month and year is unknown,
+        # calculate month duration within a single year (not min/max)
+        if self.precision == DatePrecision.MONTH:
+            latest = self.latest
+            if not self.known_year:
+                # if year is unknown, calculate month duration in
+                # a single year
+                latest = datetime.date(
+                    self.earliest.year, self.latest.month, self.latest.day
+                )
+            delta = latest - self.earliest + ONE_DAY
+            # month duration can't ever be more than 31 days
+            # (could we ever know if it's smaller?)
+
+            # if granularity == month but not known month, duration = 31
+            if delta.days > 31:
+                return datetime.timedelta(days=31)
+            return delta
+
+        # otherwise, calculate based on earliest/latest range
+
+        # subtract earliest from latest and add a day to count start day
         return self.latest - self.earliest + ONE_DAY
 
+    def _missing_digit_minmax(
+        self, value: str, min_val: int, max_val: int
+    ) -> (int, int):
+        # given a possible range, calculate min/max values for a string
+        # with a missing digit
+
+        # assuming two digit only (i.e., month or day)
+        possible_values = [f"{n:02}" for n in range(min_val, max_val + 1)]
+        # ensure input value has two digits
+        value = "%02s" % value
+        # generate regex where missing digit matches anything
+        val_pattern = re.compile(value.replace(self.MISSING_DIGIT, "."))
+        # identify all possible matches, then get min and max
+        matches = [val for val in possible_values if val_pattern.match(val)]
+        min_match = min(matches)
+        max_match = max(matches)
+
+        # split input string into a list so we can update individually
+        min_val = list(value)
+        max_val = list(value)
+        for i, digit in enumerate(value):
+            # replace the corresponding digit with our min and max
+            if digit == self.MISSING_DIGIT:
+                min_val[i] = min_match[i]
+                max_val[i] = max_match[i]
+
+        # combine the lists of digits back together and convert to int
+        min_val = int("".join(min_val))
+        max_val = int("".join(max_val))
+        return (min_val, max_val)
+
 
 class UndateInterval:
     """A date range between two uncertain dates.
@@ -148,13 +322,18 @@ def duration(self) -> datetime.timedelta:
         elif not self.latest.known_year and not self.earliest.known_year:
             # under what circumstances can we assume that if both years
             # are unknown the dates are in the same year or sequential?
-            duration = self.latest.earliest - self.earliest.earliest + ONE_DAY
+            duration = self.latest.earliest - self.earliest.earliest
             # if we get a negative, we've wrapped from end of one year
-            # to the beginning of the next
+            # to the beginning of the next;
+            # recalculate assuming second date is in the subsequent year
             if duration.days < 0:
                 end = self.latest.earliest + relativedelta(years=1)
                 duration = end - self.earliest.earliest
 
+            # add the additional day *after* checking for a negative
+            # or after recalculating with adjusted year
+            duration += ONE_DAY
+
             return duration
 
         else:


Test patch:
diff --git a/tests/test_undate.py b/tests/test_undate.py
index 9217ea4..d02c3d2 100644
--- a/tests/test_undate.py
+++ b/tests/test_undate.py
@@ -12,6 +12,17 @@ def test_str(self):
         assert str(Undate(2022)) == "2022"
         assert str(Undate(month=11, day=7)) == "--11-07"
 
+    def test_partially_known_str(self):
+        assert str(Undate("19XX")) == "19XX"
+        assert str(Undate(2022, "1X")) == "2022-1X"
+        assert str(Undate(2022, 11, "2X")) == "2022-11-2X"
+        assert str(Undate(month="1X", day=7)) == "--1X-07"
+
+        # TODO: should not allow initializing year/day without month;
+        # should we infer unknown month? or raise an exception?
+        # assert str(Undate(2022, day="2X")) == "2022-XX-2X"  # currently returns 2022-2X
+        # assert str(Undate(2022, day=7)) == "2022-XX-07"   @ currently returns 2022-07
+
     def test_repr(self):
         assert repr(Undate(2022, 11, 7)) == "<Undate 2022-11-07>"
         assert (
@@ -19,6 +30,92 @@ def test_repr(self):
             == "<Undate 'A Special Day' (2022-11-07)>"
         )
 
+    def test_init_str(self):
+        assert Undate("2000").earliest.year == 2000
+        # single or double digit string month should be ok
+        assert Undate("2000", "2").earliest.month == 2
+        assert Undate("2000", "02").earliest.month == 2
+
+    def test_init_partially_known_year(self):
+        uncertain1900s = Undate("19XX")
+        assert uncertain1900s.earliest.year == 1900
+        assert uncertain1900s.latest.year == 1999
+
+        uncertain1x = Undate("1X05")
+        assert uncertain1x.earliest.year == 1005
+        assert uncertain1x.latest.year == 1905
+
+        uncertain18x7 = Undate("18X7")
+        assert uncertain18x7.earliest.year == 1807
+        assert uncertain18x7.latest.year == 1897
+
+    def test_init_partially_known_month(self):
+        uncertain_fall = Undate(1900, "1X")
+        assert uncertain_fall.earliest.month == 10
+        assert uncertain_fall.latest.month == 12
+
+        uncertain_notfall = Undate(1900, "0X")
+        assert uncertain_notfall.earliest.month == 1
+        assert uncertain_notfall.latest.month == 9
+
+        # unlikely case, but now possible to calculate
+        assert Undate(1900, "X1").earliest.month == 1
+        assert Undate(1900, "X1").latest.month == 11
+
+        # treat as unknown but allow
+        unknown_month = Undate(1900, "XX")
+        assert unknown_month.earliest.month == 1
+        assert unknown_month.latest.month == 12
+        assert str(unknown_month) == "1900-XX"
+
+    def test_init_partially_known_day(self):
+        uncertain_day = Undate(1900, 1, "XX")  # treat as None
+        assert uncertain_day.earliest.day == 1
+        assert uncertain_day.latest.day == 31
+
+        uncertain_day = Undate(1900, 1, "1X")
+        assert uncertain_day.earliest.day == 10
+        assert uncertain_day.latest.day == 19
+
+        uncertain_day = Undate(1900, 1, "0X")
+        assert uncertain_day.earliest.day == 1
+        assert uncertain_day.latest.day == 9
+        uncertain_day = Undate(1900, 1, "2X")
+        assert uncertain_day.earliest.day == 20
+        assert uncertain_day.latest.day == 29
+        uncertain_day = Undate(1900, 1, "3X")
+        assert uncertain_day.earliest.day == 30
+        assert uncertain_day.latest.day == 31
+
+        uncertain_day = Undate(1900, 1, "X5")
+        assert uncertain_day.earliest.day == 5
+        assert uncertain_day.latest.day == 25
+
+        uncertain_day = Undate(1900, 1, "X1")
+        assert uncertain_day.earliest.day == 1
+        assert uncertain_day.latest.day == 31
+
+        # month with only 30 days
+        uncertain_day = Undate(1900, 6, "X1")
+        assert uncertain_day.earliest.day == 1
+        assert uncertain_day.latest.day == 21  # doesn't go to 31
+        uncertain_day = Undate(1900, 6, "3X")
+        assert uncertain_day.earliest.day == 30
+        assert uncertain_day.latest.day == 30
+
+        # special cases
+        # february! 28 days usually
+        uncertain_day = Undate(1900, 2, "2X")
+        assert uncertain_day.earliest.day == 20
+        assert uncertain_day.latest.day == 28
+        # february in a leap year
+        uncertain_day = Undate(2024, 2, "2X")
+        assert uncertain_day.latest.day == 29
+
+    def test_init_invalid(self):
+        with pytest.raises(ValueError):
+            Undate("19xx")
+
     def test_invalid_date(self):
         # invalid month should raise an error
         with pytest.raises(ValueError):
@@ -56,9 +153,40 @@ def test_duration(self):
         leapyear_duration = Undate(2024).duration()
         assert leapyear_duration.days == 366
 
+    def test_partiallyknown_duration(self):
+        # day in unknown month/year
+        assert Undate(day=5).duration().days == 1
+        assert Undate(year=1900, month=11, day="2X").duration().days == 1
+
+        # month in unknown year
+        assert Undate(month=6).duration().days == 30
+        # partially known month
+        assert Undate(year=1900, month="1X").duration().days == 31
+        # what about february?
+        # could vary with leap years, but assume non-leapyear
+        assert Undate(month=2).duration().days == 28
+
     def test_known_year(self):
         assert Undate(2022).known_year is True
         assert Undate(month=2, day=5).known_year is False
+        # partially known year is not known
+        assert Undate("19XX").known_year is False
+        # fully known string year should be known
+        assert Undate("1900").known_year is True
+
+    def test_is_known_month(self):
+        assert Undate(2022).is_known("month") is False
+        assert Undate(2022, 2).is_known("month") is True
+        assert Undate(2022, "5").is_known("month") is True
+        assert Undate(2022, "1X").is_known("month") is False
+        assert Undate(2022, "XX").is_known("month") is False
+
+    def test_is_known_day(self):
+        assert Undate(1984).is_known("day") is False
+        assert Undate(month=1, day=3).is_known("day") is True
+        assert Undate(month=1, day="5").is_known("day") is True
+        assert Undate(month=1, day="X5").is_known("day") is False
+        assert Undate(month=1, day="XX").is_known("day") is False
 
 
 class TestUndateInterval:
@@ -136,4 +264,12 @@ def test_duration(self):
         month_noyear_duration = UndateInterval(
             Undate(None, 12, 1), Undate(None, 1, 1)
         ).duration()
-        assert month_noyear_duration.days == 31
+        assert month_noyear_duration.days == 32
+        # this seems wrong, but we currently count both start and dates
+
+        # real case from Shakespeare and Company Project data;
+        # second date is a year minus one day in the future
+        month_noyear_duration = UndateInterval(
+            Undate(None, 6, 7), Undate(None, 6, 6)
+        ).duration()
+        assert month_noyear_duration.days == 365