-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve NYE countdown ready for next year!
- Loading branch information
Showing
4 changed files
with
101 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
|
||
To run tests locally use: | ||
|
||
`MICROPYPATH=.frozen:. micropython test/test_ProviderClock.py` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,47 @@ | ||
from typing import Union, Tuple | ||
from typing import Callable, Union, Tuple | ||
|
||
from provider.Clock import Clock | ||
from provider.Provider import Provider | ||
|
||
# Number of days in each month for a common year (non-leap year) | ||
DAYS_IN_MONTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | ||
DAYS_IN_MONTHS_LEAP_YEAR = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | ||
|
||
|
||
def _days_to_new_year(year: int, month: int, day: int) -> int: | ||
is_leap_year = (year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)) | ||
days_in_months = DAYS_IN_MONTHS_LEAP_YEAR if is_leap_year else DAYS_IN_MONTHS | ||
|
||
days_passed = sum(days_in_months[:month - 1]) + day | ||
total_days_in_year = 366 if is_leap_year else 365 | ||
|
||
return total_days_in_year - days_passed | ||
|
||
|
||
class ProviderNewYearCountdown(Provider): | ||
def __init__(self, timezone: str): | ||
self.timezone = timezone | ||
def __init__(self, timezone: str, clock_now: Callable = None): | ||
self.clock_now = clock_now if clock_now else lambda: Clock.now(timezone) | ||
|
||
def get_word(self, word: str, display: Display) -> Tuple[str, Union[int, None]]: | ||
now = Clock.now(self.timezone) | ||
now = self.clock_now() | ||
|
||
if now.month == 1 and now.day == 1: # Jan 1st | ||
return now.strftime("!HAPPY NEWYEAR %Y!"), None | ||
return now.strftime("!HAPPY NEW" "YEAR %Y!"), None | ||
|
||
next_interval_ms = (60 - now.second) * 1000 | ||
if now.month == 12 and now.day == 31 and now.hour == 23 and now.minute == 59: # last minute | ||
return f"BYE {now.year:04}: {now.hour:02}:{now.minute:02}:{now.second:02}", 1 | ||
|
||
delta_hours = 23 - now.hour | ||
delta_minutes = 59 - now.minute | ||
if now.month == 12 and now.day == 31: # last day | ||
next_interval_ms = (60 - now.second) * 1000 | ||
delta_hours = 23 - now.hour | ||
delta_minutes = 59 - now.minute | ||
|
||
if delta_minutes % 2 == 0: | ||
return f"{now.year+1:04} IN {delta_hours:02}:{delta_minutes:02} ", next_interval_ms | ||
else: | ||
return f"COUNT DOWN {delta_hours:02}:{delta_minutes:02} ", next_interval_ms | ||
if delta_minutes % 2 == 0: | ||
return f"{now.year+1:04} SOON: {delta_hours:2}H {delta_minutes:02}M", next_interval_ms | ||
else: | ||
return f" NEW YEAR IN {delta_hours:2}H {delta_minutes:02}M", next_interval_ms | ||
|
||
next_interval_ms = ((59 - now.minute) * 60 + (60 - now.second)) * 1000 | ||
delta_days = _days_to_new_year(now.year, now.month, now.day) | ||
delta_hours = 23 - now.hour | ||
return f" {now.year+1:04} IN {delta_days:3}D {delta_hours:02}H", next_interval_ms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import unittest | ||
|
||
from provider.Clock import Clock | ||
from provider.ProviderNewYearCountdown import ProviderNewYearCountdown | ||
|
||
|
||
class DisplayMock: | ||
def display_length(self) -> int: | ||
return 20 | ||
|
||
|
||
class PythonNewYearCountdownTest(unittest.TestCase): | ||
def setUp(self): | ||
self.display = DisplayMock() | ||
self.provider = ProviderNewYearCountdown("Europe/Stockholm", lambda: self.mock_now) | ||
|
||
def test_dec31_even_minute(self): | ||
self.mock_now = Clock(2024, 12, 31, 22, 0) | ||
word, interval_ms = self.provider.get_word(None, self.display) | ||
self.assertEqual(word, " NEW YEAR " "IN 1H 59M") | ||
self.assertEqual(interval_ms, 60000) | ||
|
||
def test_dec31_odd_minute(self): | ||
self.mock_now = Clock(2024, 12, 31, 22, 1) | ||
word, interval_ms = self.provider.get_word(None, self.display) | ||
self.assertEqual(word, "2025 SOON:" " 1H 58M") | ||
self.assertEqual(interval_ms, 60000) | ||
|
||
def test_last_minute(self): | ||
self.mock_now = Clock(2024, 12, 31, 23, 59, 30) | ||
word, interval_ms = self.provider.get_word(None, self.display) | ||
self.assertEqual(word, "BYE 2024: " " 23:59:30") | ||
self.assertEqual(interval_ms, 1) | ||
|
||
def test_new_year(self): | ||
self.mock_now = Clock(2025, 1, 1, 1, 1) | ||
word, interval_ms = self.provider.get_word(None, self.display) | ||
self.assertEqual(word, "!HAPPY NEW" "YEAR 2025!") | ||
self.assertIsNone(interval_ms) | ||
|
||
def test_jan2(self): | ||
self.mock_now = Clock(2025, 1, 2, 1, 1) | ||
word, interval_ms = self.provider.get_word(None, self.display) | ||
self.assertEqual(word, " 2026 IN " " 363D 22H") | ||
self.assertEqual(interval_ms, 3540000) | ||
|
||
def test_jan2_leap(self): | ||
self.mock_now = Clock(2028, 1, 2, 1, 1) | ||
word, interval_ms = self.provider.get_word(None, self.display) | ||
self.assertEqual(word, " 2029 IN " " 364D 22H") | ||
self.assertEqual(interval_ms, 3540000) | ||
|
||
def test_dec30(self): | ||
self.mock_now = Clock(2025, 12, 30, 1, 1) | ||
word, interval_ms = self.provider.get_word(None, self.display) | ||
self.assertEqual(word, " 2026 IN " " 1D 22H") | ||
self.assertEqual(interval_ms, 3540000) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters