Skip to content

Commit

Permalink
Merge pull request #48 from statisticsnorway/ref-tuesday
Browse files Browse the repository at this point in the history
Added function for reference tuesday in the week of 16th
  • Loading branch information
rakelgading authored Apr 26, 2024
2 parents 4856d88 + 0a2e177 commit c0d4d26
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "ssb-arbmark-fagfunksjoner"
version = "0.0.16"
version = "0.0.17"
description = "SSB Arbeidsmarked og lønn Fag-fellesfunksjoner"
authors = ["Jan Sebastian Rothe <[email protected]>"]
license = "MIT"
Expand Down
2 changes: 2 additions & 0 deletions src/arbmark/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from arbmark.functions.merge import indicate_merge
from arbmark.functions.quarter import first_last_date_quarter
from arbmark.functions.reference import ref_day
from arbmark.functions.reference import ref_tuesday
from arbmark.functions.reference import ref_week
from arbmark.functions.workdays import count_days
from arbmark.functions.workdays import count_holidays
Expand Down Expand Up @@ -36,6 +37,7 @@
"first_last_date_quarter",
"ref_day",
"ref_week",
"ref_tuesday",
"count_days",
"count_holidays",
"count_weekend_days",
Expand Down
51 changes: 51 additions & 0 deletions src/arbmark/functions/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,54 @@ def ref_week(

# Return the result as a series of boolean values
return pd.Series(result, dtype="boolean")


def ref_tuesday(
from_dates: PdSeriesTimestamp, to_dates: PdSeriesTimestamp
) -> PdSeriesBool:
"""Determines if the Tuesday in the same week as the 16th falls between given date ranges.
This function finds the Tuesday in the same week as the 16th day of each month
and checks if it is within the range specified by the corresponding 'from_dates'
and 'to_dates'. It requires that both 'from_dates' and 'to_dates' are in the
same year and month.
Args:
from_dates: A Series of dates representing the start of a period.
These dates should be in the 'YYYY-MM-DD' format.
to_dates: A Series of dates representing the end of a period.
These dates should also be in the 'YYYY-MM-DD' format.
Returns:
A Pandas Series of boolean values. Each element in the Series
corresponds to whether the Tuesday in the week of the 16th day of the month
for each period is within the respective date range.
Raises:
ValueError: If 'from_dates' and 'to_dates' are not in the same year, or if
they are not in the same month.
"""
# Check if the year and month are the same in the from_dates and to_dates
if not np.all(from_dates.dt.year == to_dates.dt.year):
raise ValueError("Function can only be applied to dates in the same year!")
if not np.all(from_dates.dt.month == to_dates.dt.month):
raise ValueError(
"Function can only be applied to date pairs in the same month!"
)

# Compute the date of the 16th for each period
reference_16th = pd.to_datetime(
from_dates.dt.year.astype(str) + "-" + from_dates.dt.month.astype(str) + "-16"
)

# Calculate the day of the week for the 16th (0=Monday, ..., 6=Sunday)
weekday_16th = reference_16th.dt.dayofweek

# Calculate the Tuesday in the same week as the 16th
tuesday_ref = reference_16th + pd.to_timedelta(1 - weekday_16th, unit="d")

# Check if the Tuesday reference day is within the range of the from_date and to_date
result = np.logical_and(from_dates <= tuesday_ref, tuesday_ref <= to_dates)

# Return the result as an array of boolean values
return pd.Series(result, dtype="boolean")
39 changes: 39 additions & 0 deletions tests/test_reference.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pandas as pd

from arbmark import ref_day
from arbmark import ref_tuesday
from arbmark import ref_week


Expand Down Expand Up @@ -40,6 +41,24 @@ def test_ref_week_outside_range() -> None:
).all(), "Reference week outside range test failed"


def test_ref_tuesday_within_range() -> None:
from_dates = pd.Series(pd.to_datetime(["2023-12-11", "2023-11-13"]))
to_dates = pd.Series(pd.to_datetime(["2023-12-15", "2023-11-14"]))
expected = pd.Series([True, True])
assert (
ref_tuesday(from_dates, to_dates) == expected
).all(), "Tuesday in the same week as the 16th within range test failed"


def test_ref_tuesday_outside_range() -> None:
from_dates = pd.Series(pd.to_datetime(["2023-11-15", "2023-12-14"]))
to_dates = pd.Series(pd.to_datetime(["2023-11-30", "2023-12-24"]))
expected = pd.Series([False, False])
assert (
ref_tuesday(from_dates, to_dates) == expected
).all(), "Tuesday in the same week as the 16th outside range test failed"


def test_ref_day_different_years() -> None:
from_dates = pd.Series(["2023-01-01", "2023-01-20"])
to_dates = pd.Series(["2024-02-10", "2024-02-18"])
Expand Down Expand Up @@ -78,3 +97,23 @@ def test_ref_week_different_months() -> None:
raise AssertionError("Different month test should have raised ValueError")
except ValueError:
pass


def test_ref_tuesday_different_years() -> None:
from_dates = pd.Series(pd.to_datetime(["2023-01-01", "2023-01-20"]))
to_dates = pd.Series(pd.to_datetime(["2024-02-10", "2024-02-18"]))
try:
ref_tuesday(from_dates, to_dates)
raise AssertionError("Different year test should have raised ValueError")
except ValueError:
pass


def test_ref_tuesday_different_months() -> None:
from_dates = pd.Series(pd.to_datetime(["2023-01-01", "2023-01-20"]))
to_dates = pd.Series(pd.to_datetime(["2023-03-10", "2023-02-18"]))
try:
ref_tuesday(from_dates, to_dates)
raise AssertionError("Different month test should have raised ValueError")
except ValueError:
pass

0 comments on commit c0d4d26

Please sign in to comment.