Source code for querexfuzz.dates

"""
Convert date spec from parser into (start, end) datetime tuple.

Testers::

    s = Querexfuzz.parse('@ c @ m @ d @ y @mod m-3:2 @create y-10:9 @ d-91:30 ')
    for s in s['dates']:
        print(s)
        print(qfd.resolve_date_range(s))

"""

from datetime import datetime
from logging import getLogger

from dateutil.relativedelta import relativedelta
import tzlocal
import pandas as pd


TIMEZONE = tzlocal.get_localzone()

logger = getLogger(__name__)


[docs] def resolve_date_range(spec: dict) -> tuple[datetime, datetime]: """Converts a date spec from the parser into a (start, end) datetime tuple.""" now = pd.Timestamp.now(tz=TIMEZONE) unit = spec['unit'] # --- New section for 'c' (calendar year) unit --- if unit == 'c': current_year = now.year # the current partial year counts as 1 # and the full year is added below # ergo subtract one start_offset = int(spec['start']) - 1 end_offset = int(spec['end']) start_year = current_year - start_offset end_year = current_year - end_offset # Ensure start year is before end year if start_year > end_year: start_year, end_year = end_year, start_year start_date = pd.Timestamp(f"{start_year}-01-01", tz=TIMEZONE) # Go to the very end of the last day of the end year end_date = pd.Timestamp(f"{end_year}-12-31T23:59:59.999999", tz=TIMEZONE) # logger.debug("Resolved calendar year range: %s to %s", start_date, end_date) return start_date, end_date # --- Existing logic for relative units (y, m, d, etc.) --- unit_map = { 'y': 'years', 'q': 'months', 'm': 'months', 'w': 'weeks', 'd': 'days', 'h': 'hours' } multiplier = 3 if unit == 'q' else 1 start_val = float(spec['start']) * multiplier end_val = float(spec['end']) * multiplier start_offset = relativedelta(**{unit_map[unit]: start_val}) end_offset = relativedelta(**{unit_map[unit]: end_val}) start_date = now - start_offset end_date = now - end_offset # Ensure the date range is in the correct order if start_date > end_date: start_date, end_date = end_date, start_date # logger.debug("Resolved relative date range: %s to %s", start_date, end_date) return start_date, end_date