toggleable short date format

This commit is contained in:
Chuck
2025-07-22 11:28:13 -05:00
parent c3ded3999f
commit df3d010c65
12 changed files with 103 additions and 30 deletions

View File

@@ -832,6 +832,30 @@ Example: NHL Configuration"nhl_scoreboard": {
} }
``` ```
## Date Format Configuration
You can customize the date format for upcoming games across all sports displays. The `use_short_date_format` setting in `config/config.json` under the `display` section controls this behavior.
- **`"use_short_date_format": true`**: Displays dates in a short, numerical format (e.g., "8/30").
- **`"use_short_date_format": false`** (Default): Displays dates in a more descriptive format with an ordinal suffix (e.g., "Aug 30th").
### Example `config.json`
```json
"display": {
"hardware": {
...
},
"runtime": {
...
},
"display_durations": {
...
},
"use_short_date_format": false // Set to true for "8/30" format
},
```
## Project Structure ## Project Structure

View File

@@ -70,7 +70,8 @@
"ncaam_basketball_recent": 30, "ncaam_basketball_recent": 30,
"ncaam_basketball_upcoming": 30, "ncaam_basketball_upcoming": 30,
"music": 30 "music": 30
} },
"use_short_date_format": true
}, },
"clock": { "clock": {
"enabled": true, "enabled": true,

View File

@@ -472,3 +472,13 @@ class DisplayManager:
# Reset the singleton state when cleaning up # Reset the singleton state when cleaning up
DisplayManager._instance = None DisplayManager._instance = None
DisplayManager._initialized = False DisplayManager._initialized = False
def format_date_with_ordinal(self, dt):
"""Formats a datetime object into 'Mon Aug 30th' style."""
day = dt.day
if 11 <= day <= 13:
suffix = 'th'
else:
suffix = {1: 'st', 2: 'nd', 3: 'rd'}.get(day % 10, 'th')
return dt.strftime(f"%b %-d{suffix}")

View File

@@ -205,7 +205,14 @@ class BaseMiLBManager:
if game_time.tzinfo is None: if game_time.tzinfo is None:
game_time = game_time.replace(tzinfo=pytz.UTC) game_time = game_time.replace(tzinfo=pytz.UTC)
local_time = game_time.astimezone(tz) local_time = game_time.astimezone(tz)
game_date = local_time.strftime("%b %d")
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
game_time_str = self._format_game_time(game_data['start_time']) game_time_str = self._format_game_time(game_data['start_time'])
# Draw date and time using NHL-style fonts # Draw date and time using NHL-style fonts

View File

@@ -245,7 +245,14 @@ class BaseMLBManager:
if game_time.tzinfo is None: if game_time.tzinfo is None:
game_time = game_time.replace(tzinfo=pytz.UTC) game_time = game_time.replace(tzinfo=pytz.UTC)
local_time = game_time.astimezone(tz) local_time = game_time.astimezone(tz)
game_date = local_time.strftime("%b %d")
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
game_time_str = self._format_game_time(game_data['start_time']) game_time_str = self._format_game_time(game_data['start_time'])
# Draw date and time using NHL-style fonts # Draw date and time using NHL-style fonts

View File

@@ -443,7 +443,13 @@ class BaseNBAManager:
# Convert to local time # Convert to local time
local_time = start_time_utc.astimezone(self._get_timezone()) local_time = start_time_utc.astimezone(self._get_timezone())
game_time = local_time.strftime("%I:%M%p").lstrip('0') game_time = local_time.strftime("%I:%M%p").lstrip('0')
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d") game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
# Calculate if game is within recent window # Calculate if game is within recent window
is_within_window = False is_within_window = False

View File

@@ -253,7 +253,14 @@ class BaseNCAABaseballManager:
if game_time.tzinfo is None: if game_time.tzinfo is None:
game_time = game_time.replace(tzinfo=pytz.UTC) game_time = game_time.replace(tzinfo=pytz.UTC)
local_time = game_time.astimezone(tz) local_time = game_time.astimezone(tz)
game_date = local_time.strftime("%b %d")
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
game_time_str = self._format_game_time(game_data['start_time']) game_time_str = self._format_game_time(game_data['start_time'])
date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8) date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8)

View File

@@ -484,7 +484,13 @@ class BaseNCAAFBManager: # Renamed class
if start_time_utc: if start_time_utc:
local_time = start_time_utc.astimezone(self._get_timezone()) local_time = start_time_utc.astimezone(self._get_timezone())
game_time = local_time.strftime("%I:%M%p").lstrip('0') game_time = local_time.strftime("%I:%M%p").lstrip('0')
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d") game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
# --- Football Specific Details (Likely same for NFL/NCAAFB) --- # --- Football Specific Details (Likely same for NFL/NCAAFB) ---
situation = competition.get("situation") situation = competition.get("situation")

View File

@@ -450,7 +450,13 @@ class BaseNCAAMBasketballManager:
# Convert to local time # Convert to local time
local_time = start_time_utc.astimezone(self._get_timezone()) local_time = start_time_utc.astimezone(self._get_timezone())
game_time = local_time.strftime("%I:%M%p").lstrip('0') game_time = local_time.strftime("%I:%M%p").lstrip('0')
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d") game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
# Calculate if game is within recent window # Calculate if game is within recent window
is_within_window = False is_within_window = False

View File

@@ -286,25 +286,6 @@ class BaseNFLManager: # Renamed class
else: else:
self.logger.debug("No clear favorite - spreads: home={home_spread}, away={away_spread}") self.logger.debug("No clear favorite - spreads: home={home_spread}, away={away_spread}")
# Show the negative spread on the appropriate side
if favored_spread is not None:
spread_text = str(favored_spread)
font = self.fonts['detail'] # Use detail font for odds
if favored_side == 'home':
# Home team is favored, show spread on right side
spread_width = draw.textlength(spread_text, font=font)
spread_x = width - spread_width # Top right
spread_y = 0
self._draw_text_with_outline(draw, spread_text, (spread_x, spread_y), font, fill=(0, 255, 0))
self.logger.debug(f"Showing home spread '{spread_text}' on right side")
else:
# Away team is favored, show spread on left side
spread_x = 0 # Top left
spread_y = 0
self._draw_text_with_outline(draw, spread_text, (spread_x, spread_y), font, fill=(0, 255, 0))
self.logger.debug(f"Showing away spread '{spread_text}' on left side")
# Show over/under on the opposite side of the favored team # Show over/under on the opposite side of the favored team
over_under = odds.get('over_under') over_under = odds.get('over_under')
if over_under is not None: if over_under is not None:
@@ -413,7 +394,13 @@ class BaseNFLManager: # Renamed class
if start_time_utc: if start_time_utc:
local_time = start_time_utc.astimezone(self._get_timezone()) local_time = start_time_utc.astimezone(self._get_timezone())
game_time = local_time.strftime("%I:%M%p").lstrip('0') game_time = local_time.strftime("%I:%M%p").lstrip('0')
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d") game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
# --- NFL Specific Details --- # --- NFL Specific Details ---
situation = competition.get("situation") situation = competition.get("situation")

View File

@@ -393,7 +393,13 @@ class BaseNHLManager:
# Convert to local time # Convert to local time
local_time = start_time_utc.astimezone(self._get_timezone()) local_time = start_time_utc.astimezone(self._get_timezone())
game_time = local_time.strftime("%-I:%M%p") game_time = local_time.strftime("%-I:%M%p")
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d") game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
# Calculate if game is within recent window # Calculate if game is within recent window
is_within_window = False is_within_window = False

View File

@@ -579,7 +579,13 @@ class BaseSoccerManager:
if start_time_utc: if start_time_utc:
local_time = start_time_utc.astimezone(self._get_timezone()) local_time = start_time_utc.astimezone(self._get_timezone())
game_time = local_time.strftime("%I:%M%p").lower().lstrip('0') # e.g., 2:30pm game_time = local_time.strftime("%I:%M%p").lower().lstrip('0') # e.g., 2:30pm
# Check date format from config
use_short_date_format = self.config.get('display', {}).get('use_short_date_format', False)
if use_short_date_format:
game_date = local_time.strftime("%-m/%-d") game_date = local_time.strftime("%-m/%-d")
else:
game_date = self.display_manager.format_date_with_ordinal(local_time)
status_type = status["type"]["name"] status_type = status["type"]["name"]
is_live = status_type == "STATUS_IN_PROGRESS" is_live = status_type == "STATUS_IN_PROGRESS"