diff --git a/README.md b/README.md index 155f4f97..2d25e284 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/config/config.json b/config/config.json index 5161b5e9..b5688894 100644 --- a/config/config.json +++ b/config/config.json @@ -70,7 +70,8 @@ "ncaam_basketball_recent": 30, "ncaam_basketball_upcoming": 30, "music": 30 - } + }, + "use_short_date_format": true }, "clock": { "enabled": true, diff --git a/src/display_manager.py b/src/display_manager.py index f85e7acc..60102ee7 100644 --- a/src/display_manager.py +++ b/src/display_manager.py @@ -471,4 +471,14 @@ class DisplayManager: self.matrix.Clear() # Reset the singleton state when cleaning up DisplayManager._instance = None - DisplayManager._initialized = False \ No newline at end of file + 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}") \ No newline at end of file diff --git a/src/milb_manager.py b/src/milb_manager.py index c996749a..fc2cf423 100644 --- a/src/milb_manager.py +++ b/src/milb_manager.py @@ -205,7 +205,14 @@ class BaseMiLBManager: if game_time.tzinfo is None: game_time = game_time.replace(tzinfo=pytz.UTC) 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']) # Draw date and time using NHL-style fonts diff --git a/src/mlb_manager.py b/src/mlb_manager.py index 296af3a6..5a4444bd 100644 --- a/src/mlb_manager.py +++ b/src/mlb_manager.py @@ -245,7 +245,14 @@ class BaseMLBManager: if game_time.tzinfo is None: game_time = game_time.replace(tzinfo=pytz.UTC) 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']) # Draw date and time using NHL-style fonts diff --git a/src/nba_managers.py b/src/nba_managers.py index 0f651fac..03ce489f 100644 --- a/src/nba_managers.py +++ b/src/nba_managers.py @@ -443,7 +443,13 @@ class BaseNBAManager: # Convert to local time local_time = start_time_utc.astimezone(self._get_timezone()) game_time = local_time.strftime("%I:%M%p").lstrip('0') - game_date = local_time.strftime("%-m/%-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) # Calculate if game is within recent window is_within_window = False diff --git a/src/ncaa_baseball_managers.py b/src/ncaa_baseball_managers.py index d148d3c0..01f93264 100644 --- a/src/ncaa_baseball_managers.py +++ b/src/ncaa_baseball_managers.py @@ -253,7 +253,14 @@ class BaseNCAABaseballManager: if game_time.tzinfo is None: game_time = game_time.replace(tzinfo=pytz.UTC) 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']) date_font = ImageFont.truetype("assets/fonts/PressStart2P-Regular.ttf", 8) diff --git a/src/ncaa_fb_managers.py b/src/ncaa_fb_managers.py index 48a23b8b..d15b2bc1 100644 --- a/src/ncaa_fb_managers.py +++ b/src/ncaa_fb_managers.py @@ -484,7 +484,13 @@ class BaseNCAAFBManager: # Renamed class if start_time_utc: local_time = start_time_utc.astimezone(self._get_timezone()) game_time = local_time.strftime("%I:%M%p").lstrip('0') - game_date = local_time.strftime("%-m/%-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) # --- Football Specific Details (Likely same for NFL/NCAAFB) --- situation = competition.get("situation") diff --git a/src/ncaam_basketball_managers.py b/src/ncaam_basketball_managers.py index fd114196..f63d6e83 100644 --- a/src/ncaam_basketball_managers.py +++ b/src/ncaam_basketball_managers.py @@ -450,7 +450,13 @@ class BaseNCAAMBasketballManager: # Convert to local time local_time = start_time_utc.astimezone(self._get_timezone()) game_time = local_time.strftime("%I:%M%p").lstrip('0') - game_date = local_time.strftime("%-m/%-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) # Calculate if game is within recent window is_within_window = False diff --git a/src/nfl_managers.py b/src/nfl_managers.py index f5abeceb..ecf40921 100644 --- a/src/nfl_managers.py +++ b/src/nfl_managers.py @@ -286,25 +286,6 @@ class BaseNFLManager: # Renamed class else: 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 over_under = odds.get('over_under') if over_under is not None: @@ -413,7 +394,13 @@ class BaseNFLManager: # Renamed class if start_time_utc: local_time = start_time_utc.astimezone(self._get_timezone()) game_time = local_time.strftime("%I:%M%p").lstrip('0') - game_date = local_time.strftime("%-m/%-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) # --- NFL Specific Details --- situation = competition.get("situation") diff --git a/src/nhl_managers.py b/src/nhl_managers.py index 4bc60ed7..d9d79a6d 100644 --- a/src/nhl_managers.py +++ b/src/nhl_managers.py @@ -393,7 +393,13 @@ class BaseNHLManager: # Convert to local time local_time = start_time_utc.astimezone(self._get_timezone()) game_time = local_time.strftime("%-I:%M%p") - game_date = local_time.strftime("%-m/%-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) # Calculate if game is within recent window is_within_window = False diff --git a/src/soccer_managers.py b/src/soccer_managers.py index 9cbb4197..02f51939 100644 --- a/src/soccer_managers.py +++ b/src/soccer_managers.py @@ -579,7 +579,13 @@ class BaseSoccerManager: if start_time_utc: 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_date = local_time.strftime("%-m/%-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) status_type = status["type"]["name"] is_live = status_type == "STATUS_IN_PROGRESS"