# Badger 2040W Birthday calendar time.sleep loop?

**URL:** <https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830>\
**Category:** Support\
**Created:** [January 12, 2024, 11:03am UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830 "2024-01-12T11:03:22Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![PJS](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@PJS](https://forums.pimoroni.com/u/PJS)\
**Post date:** [January 12, 2024, 11:03am UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/1 "2024-01-12T11:03:22Z")

</div>

Hi,

I wrote a little script for the Badger 2040W to function as a birthday calendar. Basicly, it show the days untill the next persons birthday from a dictionary of people and birthdays. Something like an offline Facebook Reminder, without the need of Facebook.

The first time I run this, the code runs great. Then, I make the device sleep for 8 hours (30 seconds right now for testing purpose), then check the date again to see if a day has passed. When someone has a birthday, the screen colors are inverted, the LED turns on and the display reads “Happy Birthday!”

```auto
import time
import machine
import badger2040

# Define the birthdays dictionary
birthdays = {
    "Person 1": (1, 9),
    "Person 2": (1, 20),
    "Person 3": (2, 4),
}
badger = badger2040.Badger2040()

# Function to get the current date from the onboard Wi-Fi chip
def get_current_date_wifi():
    display = badger2040.Badger2040()
    display.set_update_speed(2)
    display.set_thickness(4)
    WIDTH, HEIGHT = display.get_bounds()

    if badger2040.is_wireless():
        import ntptime
        try:
            display.connect()
            if display.isconnected():
                ntptime.settime()
                badger2040.pico_rtc_to_pcf()
        except (RuntimeError, OSError) as e:
            print(f"Wireless Error: {e.value}")

    # Thonny overwrites the Pico RTC, so re-sync from the physical RTC if we can
    try:
        badger2040.pcf_to_pico_rtc()
    except RuntimeError:
        pass

    rtc = machine.RTC()
    return list(rtc.datetime())[1:3]

# Function to calculate days in a month
def days_in_month(month, year):
    if month == 2 and ((year % 4 == 0 and year % 100 != 0) or year % 400 == 0):
        return 29
    return (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month - 1]

# Function to display birthday message
def display_birthday_message(display, next_birthday_person, days_until_birthday):
    display.clear() # White background
    display.set_pen(15) # Black text

    display.set_font("bitmap8")

    text_width = display.measure_text(next_birthday_person, scale=6)
    display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)

    if days_until_birthday == 0:
        # Display "Gelukkige verjaardag!" centered and larger
        birthday_message = "Happy Birthday"
        badger.led(255)
        text_width = display.measure_text(birthday_message, scale=3)
        display.text(birthday_message, (296 - text_width) // 2, 95, scale=3)
    else:
        # Display remaining days larger and centered
        days_text = f"Still {days_until_birthday} days"
        badger.led(0)
        text_width = display.measure_text(days_text, scale=4)
        display.text(days_text, (296 - text_width) // 2, 95, scale=4) # Updated height to 95

    display.update()
    time.sleep(5) # Display the message for 5 seconds

# Display Setup
display = badger2040.Badger2040()

# Run the script every 8 hours
while True:
    current_month, current_day = get_current_date_wifi()

    next_birthday_person = None
    days_until_birthday = float('inf')

    for person, birthday in birthdays.items():
        birthday_month, birthday_day = birthday

        current_days = current_day + sum(days_in_month(m, 2023) for m in range(1, current_month))
        birthday_days = birthday_day + sum(days_in_month(m, 2023) for m in range(1, birthday_month))

        days_until = birthday_days - current_days

        if days_until < 0:
            # Adjust for the next year
            days_until += sum(days_in_month(m, 2023) for m in range(current_month, 13))

        if days_until < days_until_birthday:
            days_until_birthday = days_until
            next_birthday_person = person

    display.clear()
    display.set_pen(15) # Black text
    display.set_font("bitmap8")

    text_width = display.measure_text(next_birthday_person, scale=6)
    display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)

    days_text = f"Still {days_until_birthday} days"
    badger.led(0)
    text_width = display.measure_text(days_text, scale=4)
    display.text(days_text, (296 - text_width) // 2, 95, scale=4)

    display.update()

    if days_until_birthday == 0:
        display_birthday_message(display, next_birthday_person, days_until_birthday)
        
time.sleep(30)

```

The second time this code runs, it shows me a white display. I get the “connected” promt and my IP adress, then white. Is this a pen color/background color issue? Is my code incorrect?

---

<div class="post-metadata">

**Author:** ![ahnlak](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/ahnlak/32/5610_2.png) [@ahnlak](https://forums.pimoroni.com/u/ahnlak)\
**Post date:** [January 12, 2024, 11:41am UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/2 "2024-01-12T11:41:01Z")

</div>

Yes, it’s a pen colour issue.

First off, despite your comments, `set_pen(15)` selects a _white_ pen, not black (see [badger2040/docs/reference.md at 9b6acf25c2e79f5821f38ae7dcf881d2433c86f6 · pimoroni/badger2040 · GitHub](https://github.com/pimoroni/badger2040/blob/9b6acf25c2e79f5821f38ae7dcf881d2433c86f6/docs/reference.md#pen-colour))

Secondly, you only ever set the pen to 15 (white), so everything ends up white on white.

`clear()` clears the display to the _current_ pen colour; so if you were to want (for example) a white background and black text, you would need to do:

```auto
...
display.set_pen(15) # White pen
display.clear()
display.set_pen(0) # Black pen
display.set_font("bitmap8")
...

```

It works the first time because the system will default to pen 0 (black) until the first time you change it.

---

<div class="post-metadata">

**Author:** ![PJS](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@PJS](https://forums.pimoroni.com/u/PJS)\
**Post date:** [January 12, 2024, 12:20pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/3 "2024-01-12T12:20:18Z")

</div>

So sorry, stupid mistake. this fixes it!

```auto
import time
import machine
import badger2040

# Define the birthdays dictionary
birthdays = {
    "Person 1": (1, 12),
    "Person 2": (1, 20),
    "Person 3": (2, 4),
}

badger = badger2040.Badger2040()

def connect_and_sync_time():
    display = badger2040.Badger2040()
    display.set_update_speed(2)
    display.set_thickness(4)
    WIDTH, HEIGHT = display.get_bounds()

    if badger2040.is_wireless():
        import ntptime
        try:
            display.connect()
            if display.isconnected():
                ntptime.settime()
                badger2040.pico_rtc_to_pcf()
        except (RuntimeError, OSError) as e:
            print(f"Wireless Error: {e.value}")

    try:
        badger2040.pcf_to_pico_rtc()
    except RuntimeError:
        pass

def get_current_date_wifi():
    connect_and_sync_time()
    rtc = machine.RTC()
    return list(rtc.datetime())[1:3]

def days_in_month(month, year):
    if month == 2 and ((year % 4 == 0 and year % 100 != 0) or year % 400 == 0):
        return 29
    return (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month - 1]

def display_birthday_message(display, next_birthday_person, days_until_birthday):
    display.set_pen(15) # White pen
    display.clear()
    display.set_pen(0) # Black pen
    display.set_font("bitmap8")

    text_width = display.measure_text(next_birthday_person, scale=6)
    display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)

    if days_until_birthday == 0:
        birthday_message = "Happy Birthday"
        badger.led(255)
        text_width = display.measure_text(birthday_message, scale=3)
        display.text(birthday_message, (296 - text_width) // 2, 95, scale=3)
    else:
        days_text = f"Still {days_until_birthday} days"
        badger.led(0)
        text_width = display.measure_text(days_text, scale=4)
        display.text(days_text, (296 - text_width) // 2, 95, scale=4)

    display.update()
    time.sleep(5)

def main():
    display = badger2040.Badger2040()

    while True:
        current_month, current_day = get_current_date_wifi()

        next_birthday_person = None
        days_until_birthday = float('inf')

        for person, birthday in birthdays.items():
            birthday_month, birthday_day = birthday

            current_days = current_day + sum(days_in_month(m, 2023) for m in range(1, current_month))
            birthday_days = birthday_day + sum(days_in_month(m, 2023) for m in range(1, birthday_month))

            days_until = birthday_days - current_days

            if days_until < 0:
                days_until += sum(days_in_month(m, 2023) for m in range(current_month, 13))

            if days_until < days_until_birthday:
                days_until_birthday = days_until
                next_birthday_person = person

        display.set_pen(0) # White pen
        display.clear()
        display.set_pen(15) # Black pen
        display.set_font("bitmap8")

        text_width = display.measure_text(next_birthday_person, scale=6)
        display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)

        days_text = f"Still {days_until_birthday} days"
        badger.led(0)
        text_width = display.measure_text(days_text, scale=4)
        display.text(days_text, (296 - text_width) // 2, 95, scale=4)

        display.update()

        if days_until_birthday == 0:
            display_birthday_message(display, next_birthday_person, days_until_birthday)

        time.sleep(30)

if __name__ == " __main__":
    main()

```

---

<div class="post-metadata">

**Author:** ![bablokb](https://avatars.discourse-cdn.com/v4/letter/b/ee59a6/32.png) [@bablokb](https://forums.pimoroni.com/u/bablokb)\
**Post date:** [January 12, 2024, 1:09pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/4 "2024-01-12T13:09:52Z")

</div>

Very nice project!

Some suggestions:

- order your entries by date. Then you don’t need to sleep eight hours, you could just sleep until the the next birthday is due (maybe minus some days so you have time to buy some gifts). This requires running on USB-power. As an alternative:
- The badger2040w has a sophisticated power-down and wake-up circuit. You could probably run for years on a set of batteries. The only thing to keep in mind is that the RTC the badger uses has a time horizon of one month, so you would have to wake-up at least once a month.

---

<div class="post-metadata">

**Author:** ![PJS](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@PJS](https://forums.pimoroni.com/u/PJS)\
**Post date:** [January 14, 2024, 7:48pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/5 "2024-01-14T19:48:10Z")

</div>

These are great ideas! I will continue to work on it, I’ll let you know!

---

<div class="post-metadata">

**Author:** ![Mad\_Monk](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/mad_monk/32/9433_2.png) [@Mad\_Monk](https://forums.pimoroni.com/u/Mad_Monk)\
**Post date:** [January 19, 2024, 10:12pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/6 "2024-01-19T22:12:12Z")

</div>

Changed it a bit for Tufty 2040 (as there is no built-in WiFi) and added day of week calculations, so you know where you stand…

```auto
import time
import machine
from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332

# Define the birthdays dictionary
birthdays = {
    "L": (2, 10),
    "M": (2, 28),
    "A": (4, 17),
    "T": (6,10),
    "S": (10,17),
    "C": (12,8),
}

display = PicoGraphics(DISPLAY_TUFTY_2040, pen_type=PEN_RGB332)
WIDTH, HEIGHT = display.get_bounds()

def days_in_month(month, year):
    if month == 2 and ((year % 4 == 0 and year % 100 != 0) or year % 400 == 0):
        return 29
    return (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month - 1]

def display_birthday_message(display, next_birthday_person, days_until_birthday):
    display.set_pen(15) # White pen
    display.clear()
    display.set_pen(0) # Black pen
    display.set_font("bitmap8")

    text_width = display.measure_text(next_birthday_person, scale=6)
    display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)

    if days_until_birthday == 0:
        birthday_message = "Happy Birthday"
        text_width = display.measure_text(birthday_message, scale=3)
        display.text(birthday_message, (296 - text_width) // 2, 95, scale=3)
    else:
        days_text = f"Still {days_until_birthday} days"
        text_width = display.measure_text(days_text, scale=4)
        display.text(days_text, (296 - text_width) // 2, 95, scale=4)

    display.update()
    time.sleep(5)

while True:
        year, month, day, hour, minute, second, seconds, subseconds = time.localtime()
         
        # Day of Week
        day_of_week = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
    
        # Common Year Offsets
        month_offset = [0,3,3,6,1,4,6,2,5,0,3,5]
        
        # Leap Year Offsets
        if ((year%4)==0) and ((year%100)==0) and ((year%400)==0):
           month_offset=[0,3,4,0,2,5,0,3,6,1,4,6]
           
        gregor_weekday = (((day+month_offset[month-1]) + 5*((year-1)%4) + 4*((year-1)%100) + 6*((year-1)%400))%7)

        next_birthday_person = None
        days_until_birthday = float('inf')

        for person, birthday in birthdays.items():
            birthday_month, birthday_day = birthday

            current_moment = day + sum(days_in_month(m, year) for m in range(1, month))
            birthday_days = birthday_day + sum(days_in_month(m, year) for m in range(1, birthday_month))

            days_until = birthday_days - current_moment

            if days_until < 0:
                days_until += sum(days_in_month(m, year) for m in range(month, 13))

            if days_until < days_until_birthday:
                days_until_birthday = days_until
                next_birthday_person = person

        display.set_pen(0) # White pen
        display.clear()
        display.set_pen(15) # Black pen
        display.set_font("bitmap8")

        text_width = display.measure_text(next_birthday_person, scale=6)
        display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)

        days_text = f"Still {days_until_birthday} days"
        text_width = display.measure_text(days_text, scale=4)
        display.text(days_text, (296 - text_width) // 2, 95, scale=4)

        #Display current date (day of week: year, month, day)
        current_date = (f'{day_of_week[gregor_weekday]} + {year} + {month} + {day}')
        text_width = display.measure_text(current_date, scale=2)
        display.text(current_date, (296 - text_width) // 2, 195, scale=2)

        display.update()

        if days_until_birthday == 0:
            display_birthday_message(display, next_birthday_person, days_until_birthday)

        time.sleep(30)

```

---

<div class="post-metadata">

**Author:** ![bablokb](https://avatars.discourse-cdn.com/v4/letter/b/ee59a6/32.png) [@bablokb](https://forums.pimoroni.com/u/bablokb)\
**Post date:** [January 20, 2024, 9:44am UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/7 "2024-01-20T09:44:45Z")

</div>

To calculate day of week, there is a much simpler solution if you base it on seconds since 01/01/1970 (epoch-time):

```auto
now_epoch = time.time() # seconds since 01/01/1970
now_day = (int(now_epoch/86400)+3) % 7 # 01/01/1970 is Thursday

```

Note: my code uses Monday as day-zero (that is how struct\_time defines it), so you will need `+4` instead of `+3`.

---

<div class="post-metadata">

**Author:** ![PJS](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@PJS](https://forums.pimoroni.com/u/PJS)\
**Post date:** [January 20, 2024, 7:06pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/8 "2024-01-20T19:06:41Z")

</div>

Lovely! I’m very happy some people are using and adapting this idea. I intend to use it in elementary school, my students love looking forward to festivities.

I was also wondering:

- Is there a way to try different Wifi networks? For example, can I load the wificonfig file with 3 different networks, then let the device try to connect ten times with each. If no connection can be made, wait an hour then try again all 3? Is there a known way?

- Also, sometimes people share a birthday. Quite often, it would seem!  
[Birthday problem - Wikipedia](https://en.wikipedia.org/wiki/Birthday_problem)  
Multiple people dont fit quite well onscreen (Person1/Person2/Person3 : 20 january). Is there a way to automaticaly resize the names when they don’t fit onscreen?

---

<div class="post-metadata">

**Author:** ![Mad\_Monk](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/mad_monk/32/9433_2.png) [@Mad\_Monk](https://forums.pimoroni.com/u/Mad_Monk)\
**Post date:** [January 21, 2024, 7:17pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/9 "2024-01-21T19:17:13Z")

</div>

lol…

Yeah… epoch-time. Thanks for that one. Some how I got lost in the weeds. Ended up using the sledgehammer method vs a nice and simple mallet.

Working on the sorting functionality now.

@PJS:

I was thinking of using alternating screens every x minutes with the words “(shared birthday)” below the ‘Still x days’… so you know that day there are more then just one. I have a few friends [3] born the same day, so will use them as test subjects…

---

<div class="post-metadata">

**Author:** ![PJS](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@PJS](https://forums.pimoroni.com/u/PJS)\
**Post date:** [January 21, 2024, 8:35pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/10 "2024-01-21T20:35:23Z")

</div>

Also an interesting approach! I’m still try some things whenever I find the time on my end here, will you posted!

---

<div class="post-metadata">

**Author:** ![Mad\_Monk](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/mad_monk/32/9433_2.png) [@Mad\_Monk](https://forums.pimoroni.com/u/Mad_Monk)\
**Post date:** [January 31, 2024, 10:24pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/12 "2024-01-31T22:24:42Z")

</div>

Ok… here is my stab at dealing with shared birthdays both in the future and day of.

The script will sorted the data via birthdays and then names. So the user is free to enter in any order their birthdays. The script will note any shared days with a 10 second delay between each member.

This script should work on most devices, as I used basic colours/fonts. Feel free to modify to your heart’s content.

Keep me posted if you find something I can tighten or overlooked. Cheers and thanks!!!

```auto
import time
import machine
from pimoroni import Button
from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332

display = PicoGraphics(DISPLAY_TUFTY_2040, pen_type=PEN_RGB332)
WIDTH, HEIGHT = display.get_bounds()

# Define the birthdays dictionary
birthdays = {
    "S": (1,12),
    "R": (1,21),
    "L": (2,11),
    "M": (2,21),
    "K": (2,21),
    "P": (2,21),
    "N": (2,23),
    "A": (3,5),
    "I": (4,27),
    "J": (8,12),
    "E": (9,3),
    "G": (9,16),
    "T": (10,31),
    "Y": (11,7),
    "C": (12,25),
    "N_Y": (1,1),
}

# Sort Dictionary By: Birthdays, then Names
sorted_birthdays = dict()
sorted_birthdays = sorted (birthdays.items(), key=lambda item: (item[1] , item[0]))
dictionary_count=len(sorted_birthdays)
birthdays.clear()

# Identify Shared Birthdays
for n in range (dictionary_count):
        person,birthday = sorted_birthdays[n]
        sorted_birthdays[n] = person,birthday,0

for n in range (dictionary_count-1):
        person, birthday, shared = sorted_birthdays[n]
        comp_person, comp_birthday , comp_shared = sorted_birthdays[n+1]
        if (birthday) == (comp_birthday):
            sorted_birthdays[n] = person,birthday,1
            sorted_birthdays[n+1] = comp_person,comp_birthday,1

# Functions for Main Program
def days_in_month(month, year):
        if month == 2 and ((year % 4 == 0 and year % 100 != 0) or year % 400 == 0):
            return 29
        return (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month - 1]

def day_of_week(year,month,day):
        named_day = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
        month_offset = [0,3,3,6,1,4,6,2,5,0,3,5]
        if ((year%4)==0) and ((year%100)==0) and ((year%400)==0):
           month_offset=[0,3,4,0,2,5,0,3,6,1,4,6]
        gregor_weekday = (((day+month_offset[month-1]) + 5*((year-1)%4) + 4*((year-1)%100) + 6*((year-1)%400))%7)
        return named_day[gregor_weekday] #Gauss's algorithm
    
def completed_display():
        current_date = (f'{day_of_week(year,month,day)} + {year} + {month} + {day}')
        text_width = display.measure_text(current_date, scale=2)
        display.text(current_date, (296 - text_width) // 2, 195, scale=2)
        display.update()
        time.sleep(10)

def birthday_message():
        display.set_pen(15) # White pen
        display.clear()
        display.set_pen(0) # Black pen
        display.set_font("bitmap8")
        text_width = display.measure_text(next_birthday_person, scale=6)
        display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)
        text_width = display.measure_text("Happy Birthday", scale=3)
        display.text("Happy Birthday", (296 - text_width) // 2, 95, scale=3)

def days_to_birthday_message():
        display.set_pen(0) # White pen
        display.clear()
        display.set_pen(15) # Black pen
        display.set_font("bitmap8")
        text_width = display.measure_text(next_birthday_person, scale=6)
        display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)
        days_text = f"Still {days_until_birthday} days"
        text_width = display.measure_text(days_text, scale=4)
        display.text(days_text, (296 - text_width) // 2, 95, scale=4)

def shared_birthday_message():
        shared_text =f"(shared birthday)"
        text_width = display.measure_text(shared_text, scale=2)
        display.text(shared_text, (296 - text_width) // 2, 130, scale=2)

while True:
        days_until_birthday = float('inf')
        year, month, day, hour, minute, second, seconds, subseconds = time.localtime()

        # Search for various birthday scenarios
        for n in range (dictionary_count):
            person, birthday, shared = sorted_birthdays[n]
            birthday_month, birthday_day = birthday
            
            current_moment = day + sum(days_in_month(m, year) for m in range(1, month))
            birthday_days = birthday_day + sum(days_in_month(m, year) for m in range(1, birthday_month))
            days_until = birthday_days - current_moment
  
            if days_until < 0:
                days_until += sum(days_in_month(m, year) for m in range(month, 13))

            if days_until < days_until_birthday:
                days_until_birthday = days_until
                next_birthday_person = person

            # Actual Birthday
            if (days_until_birthday == 0):
                if (shared == 0) and (person == next_birthday_person):
                    birthday_message()
                    completed_display()
                
                if (shared == 1) and (person == next_birthday_person):
                    current_birthday_person,current_birthday_date,current_birthday_shared = sorted_birthdays[n]
                    for s in range (dictionary_count-1):
                         person_a,birthday_a,shared_a = sorted_birthdays[s+1]
                         if birthday_a == current_birthday_date:
                            next_birthday_person = person_a
                            birthday_message()
                            shared_birthday_message()
                            completed_display()
                         

            # Shared & Unshared Day of Birth
            if (days_until_birthday !=0):
                if (shared == 1) and (person == next_birthday_person):
                    days_to_birthday_message()
                    shared_birthday_message()
                    completed_display()
                    
                    current_birthday_person,current_birthday_date,current_birthday_shared = sorted_birthdays[n]
                    for s in range (dictionary_count-1):
                        person_a,birthday_a,shared_a = sorted_birthdays[s+1]
                        if birthday_a == current_birthday_date:
                            next_birthday_person = person_a
                            days_to_birthday_message()
                            shared_birthday_message()
                            completed_display()
                    
                if (shared == 0) and (person == next_birthday_person):
                    days_to_birthday_message()
                
        completed_display()    
    

```

---

<div class="post-metadata">

**Author:** ![Mad\_Monk](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/mad_monk/32/9433_2.png) [@Mad\_Monk](https://forums.pimoroni.com/u/Mad_Monk)\
**Post date:** [February 25, 2024, 4:27pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/13 "2024-02-25T16:27:40Z")

</div>

Mornin’ P J S!! –

How is your [elementary school] birthday calendar programming coming along? - curious if you come up with any new angles.

Cheers,  
Tomas

---

<div class="post-metadata">

**Author:** ![PJS](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@PJS](https://forums.pimoroni.com/u/PJS)\
**Post date:** [February 29, 2024, 12:22pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/14 "2024-02-29T12:22:10Z")

</div>

Hi Tomas, still working on it! Right now, it is sitting on my desk, and as my work days move along I check the code somedays. The leap year is calculated wrong for example, as I noticed recently. Progress is slow, but I don’t really mind, this way, my kids can see that working on something can be a steady slow process. "Don’t give up’ and ‘Mistakes are okay’ types of messages!

---

<div class="post-metadata">

**Author:** ![Mad\_Monk](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/mad_monk/32/9433_2.png) [@Mad\_Monk](https://forums.pimoroni.com/u/Mad_Monk)\
**Post date:** [March 1, 2024, 4:46am UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/15 "2024-03-01T04:46:01Z")

</div>

Hello PJS!!

My apologies, thank you for pointing out my coding error, I’ve fixed it as noted in the screenshot

 ![Capture](https://us1.discourse-cdn.com/flex016/uploads/pimoroni/original/2X/9/9489061f5b2413f1266475b82017c8e6670226d6.jpeg)

That should correct for the leap year miscalculations. Tested with several years ahead and with 2100 as a sample…

Cheers,  
Tomas

---

<div class="post-metadata">

**Author:** ![Mad\_Monk](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/mad_monk/32/9433_2.png) [@Mad\_Monk](https://forums.pimoroni.com/u/Mad_Monk)\
**Post date:** [May 31, 2024, 6:35pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/16 "2024-05-31T18:35:30Z")

</div>

Hello PJS!! – How is the project with your students coming along?

---

<div class="post-metadata">

**Author:** ![PJS](https://avatars.discourse-cdn.com/v4/letter/p/ad7895/32.png) [@PJS](https://forums.pimoroni.com/u/PJS)\
**Post date:** [July 27, 2024, 5:41am UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/17 "2024-07-27T05:41:27Z")

</div>

Hi Mad\_Monk, life has been hectic, still no concrete solution. But happing to wrap it up this school year, will keep you posted here!

---

<div class="post-metadata">

**Author:** ![Mad\_Monk](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/mad_monk/32/9433_2.png) [@Mad\_Monk](https://forums.pimoroni.com/u/Mad_Monk)\
**Post date:** [November 5, 2024, 1:06pm UTC](https://forums.pimoroni.com/t/badger-2040w-birthday-calendar-time-sleep-loop/23830/18 "2024-11-05T13:06:03Z")

</div>

```auto
import time
import machine
from picographics import PicoGraphics, DISPLAY_TUFTY_2040, PEN_RGB332

display = PicoGraphics(DISPLAY_TUFTY_2040, pen_type=PEN_RGB332)
WIDTH, HEIGHT = display.get_bounds()

# Define the birthdays dictionary
birthdays = {
    "S": (1,18),
    "R": (1,19),
    "L": (1,21),
    "M": (2,2),
    "K": (2,2),
    "P": (2,2),
    "W": (2,14),
    "A": (3,15),
    "L": (4,8),
    "J": (8,12),
    "N": (9,3),
    "G": (9,26),
    "T": (10,24),
    "Y": (11,27),
    "XM": (12,25),
    "NY": (1,1),
}

# Sort Dictionary By: Birthdays, then Names
sorted_birthdays = dict()
sorted_birthdays = sorted (birthdays.items(), key=lambda item: (item[1] , item[0]))
dictionary_count=len(sorted_birthdays)
birthdays.clear()

# Identify Shared Birthdays
for n in range (dictionary_count):
        person,birthday = sorted_birthdays[n]
        sorted_birthdays[n] = person,birthday,0

for n in range (dictionary_count-1):
        person, birthday, shared = sorted_birthdays[n]
        comp_person, comp_birthday , comp_shared = sorted_birthdays[n+1]
        if (birthday) == (comp_birthday):
            sorted_birthdays[n] = person,birthday,1
            sorted_birthdays[n+1] = comp_person,comp_birthday,1

# Functions for Main Program
def days_in_month(month, year):
        if month == 2 and ((year % 4 == 0 and year % 100 != 0) or year % 400 == 0):
            return 29
        return (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month - 1]

def day_of_week(year,month,day):
        named_day = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
        month_offset = [0,3,3,6,1,4,6,2,5,0,3,5]
        if (((year%4)==0) and ((year%100)!=0)) or ((year%400)==0):
           month_offset=[0,3,4,0,2,5,0,3,6,1,4,6]
        gregor_weekday = (((day+month_offset[month-1]) + 5*((year-1)%4) + 4*((year-1)%100) + 6*((year-1)%400))%7)
        return named_day[gregor_weekday] #Gauss's algorithm
    
def completed_display():
        current_date = (f'{day_of_week(year,month,day)} + {year} + {month} + {day}')
        text_width = display.measure_text(current_date, scale=2)
        display.text(current_date, (296 - text_width) // 2, 195, scale=2)
        display.update()
        time.sleep(10)

def birthday_message():
        display.set_pen(15) # White pen
        display.clear()
        display.set_pen(0) # Black pen
        display.set_font("bitmap8")
        text_width = display.measure_text(next_birthday_person, scale=6)
        display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)
        text_width = display.measure_text("Happy Birthday", scale=3)
        display.text("Happy Birthday", (296 - text_width) // 2, 95, scale=3)

def days_to_birthday_message():
        display.set_pen(0) # White pen
        display.clear()
        display.set_pen(15) # Black pen
        display.set_font("bitmap8")
        text_width = display.measure_text(next_birthday_person, scale=6)
        display.text(next_birthday_person, (296 - text_width) // 2, 30, scale=6)
        days_text = f"Still {days_until_birthday} days"
        text_width = display.measure_text(days_text, scale=4)
        display.text(days_text, (296 - text_width) // 2, 95, scale=4)

def shared_birthday_message():
        shared_text =f"(shared birthday)"
        text_width = display.measure_text(shared_text, scale=2)
        display.text(shared_text, (296 - text_width) // 2, 130, scale=2)

while True:
        days_until_birthday = float('inf')
        year, month, day, hour, minute, second, seconds, subseconds = time.localtime()

        # Search for various birthday scenarios
        for n in range (dictionary_count):
            person, birthday, shared = sorted_birthdays[n]
            birthday_month, birthday_day = birthday
            
            current_moment = day + sum(days_in_month(m, year) for m in range(1, month))
            birthday_days = birthday_day + sum(days_in_month(m, year) for m in range(1, birthday_month))
            days_until = birthday_days - current_moment
  
            if days_until < 0:
                days_until = 365 + days_until

            if days_until < days_until_birthday:
                days_until_birthday = days_until
                next_birthday_person = person

            # Actual Birthday
            if (days_until_birthday == 0):
                if (shared == 0) and (person == next_birthday_person):
                    birthday_message()
                    completed_display()
                
                if (shared == 1) and (person == next_birthday_person):
                    current_birthday_person,current_birthday_date,current_birthday_shared = sorted_birthdays[n]
                    for s in range (dictionary_count-1):
                         person_a,birthday_a,shared_a = sorted_birthdays[s+1]
                         if birthday_a == current_birthday_date:
                            next_birthday_person = person_a
                            birthday_message()
                            shared_birthday_message()
                            completed_display()
                         

            # Shared & Unshared Day of Birth
            if (days_until_birthday !=0):
                if (shared == 1) and (person == next_birthday_person):
                    days_to_birthday_message()
                    shared_birthday_message()
                    completed_display()
                    
                    current_birthday_person,current_birthday_date,current_birthday_shared = sorted_birthdays[n]
                    for s in range (dictionary_count-1):
                        person_a,birthday_a,shared_a = sorted_birthdays[s+1]
                        if birthday_a == current_birthday_date:
                            next_birthday_person = person_a
                            days_to_birthday_message()
                            shared_birthday_message()
                            completed_display()
                    
                if (shared == 0) and (person == next_birthday_person):
                    days_to_birthday_message()
                
        completed_display()

```

Fixed a calculation error in my code. Apologies.
