Skip to content
Snippets Groups Projects
test_forthwith.py 7.7 KiB
Newer Older
# Copyright (C) 2024, UChicago Argonne, LLC
# Licensed under the 3-clause BSD license.  See accompanying LICENSE.txt file
# in the top-level directory.

import datetime
import pytest
from dateutil.parser import parse as date_parse
from Octeres.forthwith import (
    split_event,
    timedelta_str_to_td,
    timedelta_to_str,
    get_now,
)
from Octeres.forthwith import (
    datetime_to_epoch,
    epoch_to_datetime,
    FORMAT_DATE_FULL,
    get_daily_ranges,
)


def input_datetimes():
    lst = [
        (date_parse("2023-01-01"), "2023-01-01 00:00:00.000000", 1672531200),
        (date_parse("2023-01-01"), "2023-01-01 00:00:00.000000", 1672531200.0),
        (
            date_parse("2023-01-01 00:00:00.000001"),
            "2023-01-01 00:00:00.000001",
            1672531200.000001,
        ),
        (
            date_parse("1970-01-01 00:00:00.000001"),
            "1970-01-01 00:00:00.000001",
            0.000001,
        ),
    ]
    return lst


@pytest.mark.parametrize("dt_obj,dt_str,epoch", input_datetimes())
def test_datetime_to_from_epoch(dt_obj, dt_str, epoch):
    result_epoch = datetime_to_epoch(dt_obj)
    result_dt = epoch_to_datetime(epoch)
    result_dt_str = dt_obj.strftime(FORMAT_DATE_FULL)
    result_dt_obj = datetime.datetime.strptime(dt_str, FORMAT_DATE_FULL)

    assert result_epoch == epoch
    assert result_dt == dt_obj
    assert result_dt_str == dt_str
    assert result_dt_obj == dt_obj
    print(result_epoch)


class Test_split_event:
    def test_split_event_00(self):
        """
        Test a event within a range.
        """
        rs = date_parse("2016-01-01")
        re = date_parse("2016-02-01")
        ts = date_parse("2016-01-01")
        te = date_parse("2016-01-02")
        correct = (ts, te, datetime.timedelta(seconds=0))
        result = split_event(rs, re, ts, te)
        assert result == correct

    def test_split_event_01(self):
        """
        Test a event crossing a range.
        """
        rs = date_parse("2016-01-01")
        re = date_parse("2016-02-01")
        ts = date_parse("2016-01-15")
        te = date_parse("2016-02-05")
        correct = (ts, re, datetime.timedelta(days=4))
        result = split_event(rs, re, ts, te)
        assert result == correct

    def test_split_event_all(self):
        range_start = date_parse("2015-01-03")
        range_end = date_parse("2015-01-06")
        range_full_remaining = range_end - range_start

        cases = []

        # A outer left touching
        a_time_start = date_parse("2015-01-01")
        a_time_end = date_parse("2015-01-03")
        a_correct = (None, None, range_full_remaining)
        cases.append(("a", a_time_start, a_time_end, a_correct))

        # B exact left, right
        b_time_start = date_parse("2015-01-03")
        b_time_end = date_parse("2015-01-06")
        b_correct = (b_time_start, b_time_end, datetime.timedelta(seconds=0))
        cases.append(("b", b_time_start, b_time_end, b_correct))

        # C outer right touching
        c_time_start = date_parse("2015-01-06")
        c_time_end = date_parse("2015-01-08")
        c_correct = (None, None, range_full_remaining)
        cases.append(("c", c_time_start, c_time_end, c_correct))
        d_time_start = date_parse("2015-01-04")
        d_time_end = date_parse("2015-01-05")
        d_correct = (d_time_start, d_time_end, datetime.timedelta(seconds=0))
        cases.append(("d", d_time_start, d_time_end, d_correct))
        e_time_start = date_parse("2015-01-02")
        e_time_end = date_parse("2015-01-07")
        e_correct = (range_start, range_end, datetime.timedelta(days=2))
        cases.append(("e", e_time_start, e_time_end, e_correct))

        # F left into middle
        f_time_start = date_parse("2015-01-01")
        f_time_end = date_parse("2015-01-04")
        f_correct = (range_start, f_time_end, datetime.timedelta(days=2))
        cases.append(("f", f_time_start, f_time_end, f_correct))

        # G right into middle
        g_time_start = date_parse("2015-01-05")
        g_time_end = date_parse("2015-01-08")
        g_correct = (g_time_start, range_end, datetime.timedelta(days=2))
        cases.append(("g", g_time_start, g_time_end, g_correct))

        # H inner left touching
        h_time_start = date_parse("2015-01-03")
        h_time_end = date_parse("2015-01-04")
        h_correct = (h_time_start, h_time_end, datetime.timedelta(seconds=0))
        cases.append(("h", h_time_start, h_time_end, h_correct))

        # I inner right touching
        i_time_start = date_parse("2015-01-05")
        i_time_end = date_parse("2015-01-06")
        i_correct = (i_time_start, i_time_end, datetime.timedelta(seconds=0))
        cases.append(("i", i_time_start, i_time_end, i_correct))

        # J outer left not touching
        j_time_start = date_parse("2015-01-01")
        j_time_end = date_parse("2015-01-02")
        j_correct = (None, None, range_full_remaining)
        cases.append(("j", j_time_start, j_time_end, j_correct))

        # K outer right not touching
        k_time_start = date_parse("2015-01-07")
        k_time_end = date_parse("2015-01-08")
        k_correct = (None, None, range_full_remaining)
        cases.append(("k", k_time_start, k_time_end, k_correct))

        for case_name, ts, te, correct in cases:
            result = split_event(range_start, range_end, ts, te)
            assert result == correct


TIME_FIXTURES = (
    (datetime.timedelta(minutes=2), "00:02:00"),
    (datetime.timedelta(days=1, minutes=2), "1 day, 00:02:00"),
    (datetime.timedelta(days=2, minutes=2), "2 days, 00:02:00"),
    (
        datetime.timedelta(days=1, hours=2, minutes=3, seconds=5, microseconds=700000),
        "1 day, 02:03:05.700000",
    ),
    (datetime.timedelta(days=-1, minutes=2), "-1 day, 00:02:00"),
    (datetime.timedelta(days=-1, minutes=2, microseconds=1), "-1 day, 00:02:00.000001"),
    (datetime.timedelta(days=-1, minutes=-2), "-2 days, 23:58:00"),
    (datetime.timedelta(days=-1, microseconds=-1), "-2 days, 23:59:59.999999"),
    (
        datetime.timedelta(days=-2, seconds=86399, microseconds=999999),
        "-2 days, 23:59:59.999999",
    ),
    @pytest.mark.parametrize("td_a,td_b_str", TIME_FIXTURES)
    def test_timedelta_str_to_td_00(self, td_a, td_b_str):
        td_a_str = timedelta_to_str(td_a)
        td_b = timedelta_str_to_td(td_b_str)
        print()
        print(f"{td_a=} {td_b=}")
        print(f"{str(td_a)=} {str(td_b)=}")
        print(td_a.total_seconds(), td_b.total_seconds())
        print(f"{td_a_str=} {td_b_str=}")
        assert td_a.total_seconds() == td_b.total_seconds()
        assert td_a == td_b
        assert td_a_str == td_b_str


def test_get_now_00():
    now = get_now()
    now2 = get_now()
    assert (now2 - now).total_seconds() < 1

    now = get_now(notz=True)
    now2 = get_now(notz=True)
    assert (now2 - now).total_seconds() < 1
    assert now.tzinfo is None
    assert now2.tzinfo is None

    now = get_now(notz=False)
    now2 = get_now(notz=False)
    assert (now2 - now).total_seconds() < 1
    assert now.tzinfo is not None
    assert now2.tzinfo is not None


def test_get_daily_ranges():
    range_start = datetime.datetime.fromisoformat("2020-01-01")
    range_end = datetime.datetime.fromisoformat("2020-01-07")
    ranges = get_daily_ranges(range_start, range_end - datetime.timedelta(days=1))
    ranges = [(ts.isoformat(), te.isoformat()) for ts, te in ranges]
    assert ranges == [
        ("2020-01-01T00:00:00", "2020-01-02T00:00:00"),
        ("2020-01-02T00:00:00", "2020-01-03T00:00:00"),
        ("2020-01-03T00:00:00", "2020-01-04T00:00:00"),
        ("2020-01-04T00:00:00", "2020-01-05T00:00:00"),
        ("2020-01-05T00:00:00", "2020-01-06T00:00:00"),
        ("2020-01-06T00:00:00", "2020-01-07T00:00:00"),
    ]