prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Add the ability to test and sort timestamps to be monotonic in a pandas data frame
  # Brief Description
  
  Following up on #703, this issue seeks to introduce the ability to sort the timestamps in a pandas data frame monotonically
  
  I would like to propose...
  
  # Example API
  ```python
  def _test_for_monotonicity(
          df: pd.DataFrame,
          column_name: str = None,
          direction: str = 'increasing'
  ) -> bool:
      """
      Tests input data frame for monotonicity.
  
      Check if the data is monotonically increasing or decreasing.
      Direction is dependent on user input.
      Defaults to increasing
  
      :param df: data frame to be tested for monotonicity
      :param column_name: needs to be specified if and only if the date time is not in index.
          Defaults to None.
      :param direction: specifies the direction in which monotonicity is being tested for.
          Defaults to 'increasing'
      :return: single boolean flag indicating whether the test has passed or not
      """
  
  def sort_monotonically(
          df: pd.DataFrame,
          column_name: str = None,
          direction: str ='increasing'
  ) -> pd.DataFrame:
      """
      Sorts data frame monotonically.
      It assumes the data frame has an index of type pd.DateTimeIndex when index is datetime.
      If datetime is in a column, then the column is expected to be of type pd.Timestamp
  
      :param df: data frame to sort monotonically
      :param column_name: needs to be specified if and only if the date time is not in index.
          Defaults to None
      :param direction: specifies the direction in which monotonicity is being tested for.
          Defaults to 'increasing'
      :return: data frame with its index sorted
      """
  
  
  # more examples below
  # ...
  ```
  
  [ENH] Adding ability to sort timestamps monotonically
  Closes #707 
  
  # PR Description
  
  Please describe the changes proposed in the pull request:
  
  - Adding a function that allows monotonic sorting of timestamps in data frame 
  
  **This PR resolves #707 **
  
  # PR Checklist
  Please ensure that you have done the following:
  
  1. [x] PR in from a fork off your branch. Do not PR from `<your_username>`:`dev`, but rather from `<your_username>`:`<feature-branch_name>`.
  2. [x] If you're not on the contributors list, add yourself to `AUTHORS.rst`.
  3. [x] Add a line to `CHANGELOG.rst` under the latest version header (i.e. the one that is "on deck") describing the contribution.
      - Do use some discretion here; if there are multiple PRs that are related, keep them in a single line.
  
  ## Quick Check
  
  To do a very quick check that everything is correct, follow these steps below:
  
  - [x] Run the command `make check` from pyjanitor's top-level directory. This will automatically run:
      - black formatting
      - flake8 checking
      - running the test suite
      - docs build
  
  Once done, please check off the check-box above.
  
  If `make check` does not work for you, you can execute the commands listed in the Makefile individually.
  
  ## Code Changes
  
  <!-- If you have not made code changes, please feel free to delete this section. -->
  
  If you are adding code changes, please ensure the following:
  
  - [x] Ensure that you have added tests.
  - [x] Run all tests (`$ pytest .`) locally on your machine.
      - [x] Check to ensure that test coverage covers the lines of code that you have added.
      - [x] Ensure that all tests pass.
  
  ## Documentation Changes
  If you are adding documentation changes, please ensure the following:
  
  - [x] Build the docs locally.
  - [ ] View the docs to check that it renders correctly.
  
  # Relevant Reviewers
  - @ericmjl 
  - @samukweku 
  
  Please tag maintainers to review.
  
  - @ericmjl
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `janitor/timeseries.py`
  Content:
  ```
  1 """
  2 Time series-specific data testing and cleaning functions.
  3 """
  4 
  5 import pandas as pd
  6 import pandas_flavor as pf
  7 from janitor import check
  8 
  9 
  10 @pf.register_dataframe_method
  11 def fill_missing_timestamps(
  12     df: pd.DataFrame,
  13     frequency: str,
  14     first_time_stamp: pd.Timestamp = None,
  15     last_time_stamp: pd.Timestamp = None,
  16 ) -> pd.DataFrame:
  17     """
  18     Fill dataframe with missing timestamps based on a defined frequency.
  19 
  20     If timestamps are missing,
  21     this function will reindex the dataframe.
  22     If timestamps are not missing,
  23     then the function will return the dataframe unmodified.
  24     Example usage:
  25     .. code-block:: python
  26 
  27         df = (
  28             pd.DataFrame(...)
  29             .fill_missing_timestamps(frequency="1H")
  30         )
  31 
  32     :param df: Dataframe which needs to be tested for missing timestamps
  33     :param frequency: frequency i.e. sampling frequency of the data.
  34         Acceptable frequency strings are available
  35         `here <https://pandas.pydata.org/pandas-docs/stable/>`_
  36         Check offset aliases under time series in user guide
  37     :param first_time_stamp: timestamp expected to start from
  38         Defaults to None.
  39         If no input is provided assumes the minimum value in time_series
  40     :param last_time_stamp: timestamp expected to end with.
  41         Defaults to None.
  42         If no input is provided, assumes the maximum value in time_series
  43     :returns: dataframe that has a complete set of contiguous datetimes.
  44     """
  45     # Check all the inputs are the correct data type
  46     check("frequency", frequency, [str])
  47     check("first_time_stamp", first_time_stamp, [pd.Timestamp, type(None)])
  48     check("last_time_stamp", last_time_stamp, [pd.Timestamp, type(None)])
  49 
  50     if first_time_stamp is None:
  51         first_time_stamp = df.index.min()
  52     if last_time_stamp is None:
  53         last_time_stamp = df.index.max()
  54 
  55     # Generate expected timestamps
  56     expected_timestamps = pd.date_range(
  57         start=first_time_stamp, end=last_time_stamp, freq=frequency
  58     )
  59 
  60     return df.reindex(expected_timestamps)
  61 
  62 
  63 def _get_missing_timestamps(
  64     df: pd.DataFrame,
  65     frequency: str,
  66     first_time_stamp: pd.Timestamp = None,
  67     last_time_stamp: pd.Timestamp = None,
  68 ) -> pd.DataFrame:
  69     """
  70     Return the timestamps that are missing in a dataframe.
  71 
  72     This function takes in a dataframe,
  73     and checks its index against a dataframe
  74     that contains the expected timestamps.
  75     Here, we assume that the expected timestamps
  76     are going to be of a larger size
  77     than the timestamps available in the input dataframe ``df``.
  78 
  79     If there are any missing timestamps in the input dataframe,
  80     this function will return those missing timestamps
  81     from the expected dataframe.
  82     """
  83     expected_df = df.fill_missing_timestamps(
  84         frequency, first_time_stamp, last_time_stamp
  85     )
  86 
  87     missing_timestamps = expected_df.index.difference(df.index)
  88 
  89     return expected_df.loc[missing_timestamps]
  90
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/janitor/timeseries.py b/janitor/timeseries.py
  --- a/janitor/timeseries.py
  +++ b/janitor/timeseries.py
  @@ -87,3 +87,58 @@
       missing_timestamps = expected_df.index.difference(df.index)
   
       return expected_df.loc[missing_timestamps]
  +
  +
  +@pf.register_dataframe_method
  +def sort_timestamps_monotonically(
  +    df: pd.DataFrame, direction: str = "increasing", strict: bool = False
  +) -> pd.DataFrame:
  +    """
  +    Sort dataframe such that index is monotonic.
  +
  +    If timestamps are monotonic,
  +    this function will return the dataframe unmodified.
  +    If timestamps are not monotonic,
  +    then the function will sort the dataframe.
  +
  +    Example usage:
  +
  +    .. code-block:: python
  +
  +        df = (
  +            pd.DataFrame(...)
  +            .sort_timestamps_monotonically(direction='increasing')
  +        )
  +
  +    :param df: Dataframe which needs to be tested for monotonicity
  +    :param direction: type of monotonicity desired.
  +        Acceptable arguments are:
  +            1. increasing
  +            2. decreasing
  +    :param strict: flag to enable/disable strict monotonicity.
  +        If set to True,
  +        will remove duplicates in the index,
  +        by retaining first occurrence of value in index.
  +        If set to False,
  +        will not test for duplicates in the index.
  +        Defaults to False.
  +    :returns: Dataframe that has monotonically increasing
  +        (or decreasing) timestamps.
  +    """
  +    # Check all the inputs are the correct data type
  +    check("df", df, [pd.DataFrame])
  +    check("direction", direction, [str])
  +    check("strict", strict, [bool])
  +
  +    # Remove duplicates if requested
  +    if strict:
  +        df = df[~df.index.duplicated(keep="first")]
  +
  +    # Sort timestamps
  +    if direction == "increasing":
  +        df = df.sort_index()
  +    else:
  +        df = df.sort_index(ascending=False)
  +
  +    # Return the dataframe
  +    return df
  
verification_info: {"golden_diff": "diff --git a/janitor/timeseries.py b/janitor/timeseries.py\n--- a/janitor/timeseries.py\n+++ b/janitor/timeseries.py\n@@ -87,3 +87,58 @@\n     missing_timestamps = expected_df.index.difference(df.index)\n \n     return expected_df.loc[missing_timestamps]\n+\n+\n+@pf.register_dataframe_method\n+def sort_timestamps_monotonically(\n+    df: pd.DataFrame, direction: str = \"increasing\", strict: bool = False\n+) -> pd.DataFrame:\n+    \"\"\"\n+    Sort dataframe such that index is monotonic.\n+\n+    If timestamps are monotonic,\n+    this function will return the dataframe unmodified.\n+    If timestamps are not monotonic,\n+    then the function will sort the dataframe.\n+\n+    Example usage:\n+\n+    .. code-block:: python\n+\n+        df = (\n+            pd.DataFrame(...)\n+            .sort_timestamps_monotonically(direction='increasing')\n+        )\n+\n+    :param df: Dataframe which needs to be tested for monotonicity\n+    :param direction: type of monotonicity desired.\n+        Acceptable arguments are:\n+            1. increasing\n+            2. decreasing\n+    :param strict: flag to enable/disable strict monotonicity.\n+        If set to True,\n+        will remove duplicates in the index,\n+        by retaining first occurrence of value in index.\n+        If set to False,\n+        will not test for duplicates in the index.\n+        Defaults to False.\n+    :returns: Dataframe that has monotonically increasing\n+        (or decreasing) timestamps.\n+    \"\"\"\n+    # Check all the inputs are the correct data type\n+    check(\"df\", df, [pd.DataFrame])\n+    check(\"direction\", direction, [str])\n+    check(\"strict\", strict, [bool])\n+\n+    # Remove duplicates if requested\n+    if strict:\n+        df = df[~df.index.duplicated(keep=\"first\")]\n+\n+    # Sort timestamps\n+    if direction == \"increasing\":\n+        df = df.sort_index()\n+    else:\n+        df = df.sort_index(ascending=False)\n+\n+    # Return the dataframe\n+    return df\n", "issue": "Add the ability to test and sort timestamps to be monotonic in a pandas data frame\n# Brief Description\r\n\r\nFollowing up on #703, this issue seeks to introduce the ability to sort the timestamps in a pandas data frame monotonically\r\n\r\nI would like to propose...\r\n\r\n# Example API\r\n```python\r\ndef _test_for_monotonicity(\r\n        df: pd.DataFrame,\r\n        column_name: str = None,\r\n        direction: str = 'increasing'\r\n) -> bool:\r\n    \"\"\"\r\n    Tests input data frame for monotonicity.\r\n\r\n    Check if the data is monotonically increasing or decreasing.\r\n    Direction is dependent on user input.\r\n    Defaults to increasing\r\n\r\n    :param df: data frame to be tested for monotonicity\r\n    :param column_name: needs to be specified if and only if the date time is not in index.\r\n        Defaults to None.\r\n    :param direction: specifies the direction in which monotonicity is being tested for.\r\n        Defaults to 'increasing'\r\n    :return: single boolean flag indicating whether the test has passed or not\r\n    \"\"\"\r\n\r\ndef sort_monotonically(\r\n        df: pd.DataFrame,\r\n        column_name: str = None,\r\n        direction: str ='increasing'\r\n) -> pd.DataFrame:\r\n    \"\"\"\r\n    Sorts data frame monotonically.\r\n    It assumes the data frame has an index of type pd.DateTimeIndex when index is datetime.\r\n    If datetime is in a column, then the column is expected to be of type pd.Timestamp\r\n\r\n    :param df: data frame to sort monotonically\r\n    :param column_name: needs to be specified if and only if the date time is not in index.\r\n        Defaults to None\r\n    :param direction: specifies the direction in which monotonicity is being tested for.\r\n        Defaults to 'increasing'\r\n    :return: data frame with its index sorted\r\n    \"\"\"\r\n\r\n\r\n# more examples below\r\n# ...\r\n```\r\n\n[ENH] Adding ability to sort timestamps monotonically\nCloses #707 \r\n\r\n# PR Description\r\n\r\nPlease describe the changes proposed in the pull request:\r\n\r\n- Adding a function that allows monotonic sorting of timestamps in data frame \r\n\r\n**This PR resolves #707 **\r\n\r\n# PR Checklist\r\nPlease ensure that you have done the following:\r\n\r\n1. [x] PR in from a fork off your branch. Do not PR from `<your_username>`:`dev`, but rather from `<your_username>`:`<feature-branch_name>`.\r\n2. [x] If you're not on the contributors list, add yourself to `AUTHORS.rst`.\r\n3. [x] Add a line to `CHANGELOG.rst` under the latest version header (i.e. the one that is \"on deck\") describing the contribution.\r\n    - Do use some discretion here; if there are multiple PRs that are related, keep them in a single line.\r\n\r\n## Quick Check\r\n\r\nTo do a very quick check that everything is correct, follow these steps below:\r\n\r\n- [x] Run the command `make check` from pyjanitor's top-level directory. This will automatically run:\r\n    - black formatting\r\n    - flake8 checking\r\n    - running the test suite\r\n    - docs build\r\n\r\nOnce done, please check off the check-box above.\r\n\r\nIf `make check` does not work for you, you can execute the commands listed in the Makefile individually.\r\n\r\n## Code Changes\r\n\r\n<!-- If you have not made code changes, please feel free to delete this section. -->\r\n\r\nIf you are adding code changes, please ensure the following:\r\n\r\n- [x] Ensure that you have added tests.\r\n- [x] Run all tests (`$ pytest .`) locally on your machine.\r\n    - [x] Check to ensure that test coverage covers the lines of code that you have added.\r\n    - [x] Ensure that all tests pass.\r\n\r\n## Documentation Changes\r\nIf you are adding documentation changes, please ensure the following:\r\n\r\n- [x] Build the docs locally.\r\n- [ ] View the docs to check that it renders correctly.\r\n\r\n# Relevant Reviewers\r\n- @ericmjl \r\n- @samukweku \r\n\r\nPlease tag maintainers to review.\r\n\r\n- @ericmjl\r\n\n", "before_files": [{"content": "\"\"\"\nTime series-specific data testing and cleaning functions.\n\"\"\"\n\nimport pandas as pd\nimport pandas_flavor as pf\nfrom janitor import check\n\n\n@pf.register_dataframe_method\ndef fill_missing_timestamps(\n    df: pd.DataFrame,\n    frequency: str,\n    first_time_stamp: pd.Timestamp = None,\n    last_time_stamp: pd.Timestamp = None,\n) -> pd.DataFrame:\n    \"\"\"\n    Fill dataframe with missing timestamps based on a defined frequency.\n\n    If timestamps are missing,\n    this function will reindex the dataframe.\n    If timestamps are not missing,\n    then the function will return the dataframe unmodified.\n    Example usage:\n    .. code-block:: python\n\n        df = (\n            pd.DataFrame(...)\n            .fill_missing_timestamps(frequency=\"1H\")\n        )\n\n    :param df: Dataframe which needs to be tested for missing timestamps\n    :param frequency: frequency i.e. sampling frequency of the data.\n        Acceptable frequency strings are available\n        `here <https://pandas.pydata.org/pandas-docs/stable/>`_\n        Check offset aliases under time series in user guide\n    :param first_time_stamp: timestamp expected to start from\n        Defaults to None.\n        If no input is provided assumes the minimum value in time_series\n    :param last_time_stamp: timestamp expected to end with.\n        Defaults to None.\n        If no input is provided, assumes the maximum value in time_series\n    :returns: dataframe that has a complete set of contiguous datetimes.\n    \"\"\"\n    # Check all the inputs are the correct data type\n    check(\"frequency\", frequency, [str])\n    check(\"first_time_stamp\", first_time_stamp, [pd.Timestamp, type(None)])\n    check(\"last_time_stamp\", last_time_stamp, [pd.Timestamp, type(None)])\n\n    if first_time_stamp is None:\n        first_time_stamp = df.index.min()\n    if last_time_stamp is None:\n        last_time_stamp = df.index.max()\n\n    # Generate expected timestamps\n    expected_timestamps = pd.date_range(\n        start=first_time_stamp, end=last_time_stamp, freq=frequency\n    )\n\n    return df.reindex(expected_timestamps)\n\n\ndef _get_missing_timestamps(\n    df: pd.DataFrame,\n    frequency: str,\n    first_time_stamp: pd.Timestamp = None,\n    last_time_stamp: pd.Timestamp = None,\n) -> pd.DataFrame:\n    \"\"\"\n    Return the timestamps that are missing in a dataframe.\n\n    This function takes in a dataframe,\n    and checks its index against a dataframe\n    that contains the expected timestamps.\n    Here, we assume that the expected timestamps\n    are going to be of a larger size\n    than the timestamps available in the input dataframe ``df``.\n\n    If there are any missing timestamps in the input dataframe,\n    this function will return those missing timestamps\n    from the expected dataframe.\n    \"\"\"\n    expected_df = df.fill_missing_timestamps(\n        frequency, first_time_stamp, last_time_stamp\n    )\n\n    missing_timestamps = expected_df.index.difference(df.index)\n\n    return expected_df.loc[missing_timestamps]\n", "path": "janitor/timeseries.py"}], "after_files": [{"content": "\"\"\"\nTime series-specific data testing and cleaning functions.\n\"\"\"\n\nimport pandas as pd\nimport pandas_flavor as pf\nfrom janitor import check\n\n\n@pf.register_dataframe_method\ndef fill_missing_timestamps(\n    df: pd.DataFrame,\n    frequency: str,\n    first_time_stamp: pd.Timestamp = None,\n    last_time_stamp: pd.Timestamp = None,\n) -> pd.DataFrame:\n    \"\"\"\n    Fill dataframe with missing timestamps based on a defined frequency.\n\n    If timestamps are missing,\n    this function will reindex the dataframe.\n    If timestamps are not missing,\n    then the function will return the dataframe unmodified.\n    Example usage:\n    .. code-block:: python\n\n        df = (\n            pd.DataFrame(...)\n            .fill_missing_timestamps(frequency=\"1H\")\n        )\n\n    :param df: Dataframe which needs to be tested for missing timestamps\n    :param frequency: frequency i.e. sampling frequency of the data.\n        Acceptable frequency strings are available\n        `here <https://pandas.pydata.org/pandas-docs/stable/>`_\n        Check offset aliases under time series in user guide\n    :param first_time_stamp: timestamp expected to start from\n        Defaults to None.\n        If no input is provided assumes the minimum value in time_series\n    :param last_time_stamp: timestamp expected to end with.\n        Defaults to None.\n        If no input is provided, assumes the maximum value in time_series\n    :returns: dataframe that has a complete set of contiguous datetimes.\n    \"\"\"\n    # Check all the inputs are the correct data type\n    check(\"frequency\", frequency, [str])\n    check(\"first_time_stamp\", first_time_stamp, [pd.Timestamp, type(None)])\n    check(\"last_time_stamp\", last_time_stamp, [pd.Timestamp, type(None)])\n\n    if first_time_stamp is None:\n        first_time_stamp = df.index.min()\n    if last_time_stamp is None:\n        last_time_stamp = df.index.max()\n\n    # Generate expected timestamps\n    expected_timestamps = pd.date_range(\n        start=first_time_stamp, end=last_time_stamp, freq=frequency\n    )\n\n    return df.reindex(expected_timestamps)\n\n\ndef _get_missing_timestamps(\n    df: pd.DataFrame,\n    frequency: str,\n    first_time_stamp: pd.Timestamp = None,\n    last_time_stamp: pd.Timestamp = None,\n) -> pd.DataFrame:\n    \"\"\"\n    Return the timestamps that are missing in a dataframe.\n\n    This function takes in a dataframe,\n    and checks its index against a dataframe\n    that contains the expected timestamps.\n    Here, we assume that the expected timestamps\n    are going to be of a larger size\n    than the timestamps available in the input dataframe ``df``.\n\n    If there are any missing timestamps in the input dataframe,\n    this function will return those missing timestamps\n    from the expected dataframe.\n    \"\"\"\n    expected_df = df.fill_missing_timestamps(\n        frequency, first_time_stamp, last_time_stamp\n    )\n\n    missing_timestamps = expected_df.index.difference(df.index)\n\n    return expected_df.loc[missing_timestamps]\n\n\n@pf.register_dataframe_method\ndef sort_timestamps_monotonically(\n    df: pd.DataFrame, direction: str = \"increasing\", strict: bool = False\n) -> pd.DataFrame:\n    \"\"\"\n    Sort dataframe such that index is monotonic.\n\n    If timestamps are monotonic,\n    this function will return the dataframe unmodified.\n    If timestamps are not monotonic,\n    then the function will sort the dataframe.\n\n    Example usage:\n\n    .. code-block:: python\n\n        df = (\n            pd.DataFrame(...)\n            .sort_timestamps_monotonically(direction='increasing')\n        )\n\n    :param df: Dataframe which needs to be tested for monotonicity\n    :param direction: type of monotonicity desired.\n        Acceptable arguments are:\n            1. increasing\n            2. decreasing\n    :param strict: flag to enable/disable strict monotonicity.\n        If set to True,\n        will remove duplicates in the index,\n        by retaining first occurrence of value in index.\n        If set to False,\n        will not test for duplicates in the index.\n        Defaults to False.\n    :returns: Dataframe that has monotonically increasing\n        (or decreasing) timestamps.\n    \"\"\"\n    # Check all the inputs are the correct data type\n    check(\"df\", df, [pd.DataFrame])\n    check(\"direction\", direction, [str])\n    check(\"strict\", strict, [bool])\n\n    # Remove duplicates if requested\n    if strict:\n        df = df[~df.index.duplicated(keep=\"first\")]\n\n    # Sort timestamps\n    if direction == \"increasing\":\n        df = df.sort_index()\n    else:\n        df = df.sort_index(ascending=False)\n\n    # Return the dataframe\n    return df\n", "path": "janitor/timeseries.py"}]}