Skip to content

Commit 921449f

Browse files
committed
Radarr Fixes
1 parent cb0edeb commit 921449f

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

src/primary/utils/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"""
44

55
from src.primary.utils.logger import logger, debug_log
6+
from src.primary.utils.date_utils import parse_date, is_future_date, is_valid_date
67

7-
__all__ = ['logger', 'debug_log']
8+
__all__ = ['logger', 'debug_log', 'parse_date', 'is_future_date', 'is_valid_date']

src/primary/utils/date_utils.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Date Utilities for Huntarr
4+
Handles date parsing and validation across all apps
5+
"""
6+
7+
import datetime
8+
from typing import Optional
9+
from src.primary.utils.logger import get_logger
10+
11+
# Get logger for the utility
12+
date_logger = get_logger(__name__)
13+
14+
15+
def parse_date(date_str: Optional[str]) -> Optional[datetime.datetime]:
16+
"""
17+
Parse a date string into a datetime object.
18+
19+
Args:
20+
date_str: Date string in various formats (ISO, etc.)
21+
22+
Returns:
23+
datetime object if parsing successful, None otherwise
24+
"""
25+
if not date_str:
26+
return None
27+
28+
# Handle empty or whitespace-only strings
29+
if not isinstance(date_str, str) or not date_str.strip():
30+
return None
31+
32+
date_str = date_str.strip()
33+
34+
# Common date formats to try
35+
date_formats = [
36+
"%Y-%m-%dT%H:%M:%S.%fZ", # ISO with microseconds and Z
37+
"%Y-%m-%dT%H:%M:%SZ", # ISO with Z
38+
"%Y-%m-%dT%H:%M:%S", # ISO without Z
39+
"%Y-%m-%d", # Simple date
40+
"%Y-%m-%dT%H:%M:%S.%f", # ISO with microseconds no Z
41+
]
42+
43+
for date_format in date_formats:
44+
try:
45+
parsed_date = datetime.datetime.strptime(date_str, date_format)
46+
# If the date has no timezone info and ends with Z, it's UTC
47+
if date_str.endswith('Z') and parsed_date.tzinfo is None:
48+
parsed_date = parsed_date.replace(tzinfo=datetime.timezone.utc)
49+
return parsed_date
50+
except ValueError:
51+
continue
52+
53+
# If all formats fail, log a debug message
54+
date_logger.debug(f"Failed to parse date string: '{date_str}'")
55+
return None
56+
57+
58+
def is_future_date(date_obj: Optional[datetime.datetime]) -> bool:
59+
"""
60+
Check if a datetime object represents a future date.
61+
62+
Args:
63+
date_obj: datetime object to check
64+
65+
Returns:
66+
True if date is in the future, False otherwise
67+
"""
68+
if not date_obj:
69+
return False
70+
71+
# Get current time in UTC for comparison
72+
now = datetime.datetime.now(datetime.timezone.utc)
73+
74+
# If the date object doesn't have timezone info, assume it's UTC
75+
if date_obj.tzinfo is None:
76+
date_obj = date_obj.replace(tzinfo=datetime.timezone.utc)
77+
78+
return date_obj > now
79+
80+
81+
def is_valid_date(date_str: Optional[str]) -> bool:
82+
"""
83+
Check if a date string can be parsed into a valid date.
84+
85+
Args:
86+
date_str: Date string to validate
87+
88+
Returns:
89+
True if date string is valid, False otherwise
90+
"""
91+
return parse_date(date_str) is not None

0 commit comments

Comments
 (0)