# Inky Frame Word Clock - BST modification

**URL:** <https://forums.pimoroni.com/t/inky-frame-word-clock-bst-modification/25227>\
**Category:** Support\
**Created:** [August 7, 2024, 2:21pm UTC](https://forums.pimoroni.com/t/inky-frame-word-clock-bst-modification/25227 "2024-08-07T14:21:36Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![djfreeman](https://avatars.discourse-cdn.com/v4/letter/d/6de8d8/32.png) [@djfreeman](https://forums.pimoroni.com/u/djfreeman)\
**Post date:** [August 7, 2024, 2:21pm UTC](https://forums.pimoroni.com/t/inky-frame-word-clock-bst-modification/25227/1 "2024-08-07T14:21:36Z")

</div>

The Inky Frame word clock is excellent but doesn’t account for British Summer Time (or any other daylight saving time).

I have written a Medium article ([here](https://medium.com/@djfreeman2007/modifying-pimoroni-inky-frame-word-clock-for-british-summer-time-f51345a81ee1)) in this topic:

For this post, here is my modified code for the word\_clock.py program.

```auto
# New Code word_clock.py
import machine
import ntptime

# Length of time between updates in minutes.
UPDATE_INTERVAL = 15
graphics = None

rtc = machine.RTC()
time_string = None
words = ["it", "d", "is", "m", "about", "l", "half", "c", "quarter", "b", "to", "u", "past", "n", "one",
         "two", "three", "four", "five", "six", "eleven", "ten", "nine", "eight", "seven", "rm", "twelve", "rt", "O'Clock", "q"]

def approx_time(hours, minutes):
    nums = {0: "twelve", 1: "one", 2: "two",
            3: "three", 4: "four", 5: "five", 6: "six",
            7: "seven", 8: "eight", 9: "nine", 10: "ten",
            11: "eleven", 12: "twelve"}

    if hours == 12:
        hours = 0
    if minutes > 0 and minutes < 8:
        return "it is about " + nums[hours] + " O'Clock"
    elif minutes >= 8 and minutes < 23:
        return "it is about quarter past " + nums[hours]
    elif minutes >= 23 and minutes < 38:
        return "it is about half past " + nums[hours]
    elif minutes >= 38 and minutes < 53:
        return "it is about quarter to " + nums[hours + 1]
    else:
        return "it is about " + nums[hours + 1] + " O'Clock"

def is_bst(date_tuple):
    year, month, day, weekday, hour, minute, second, subseconds = date_tuple[:8]

    # BST starts on the last Sunday in March
    if month > 3 and month < 10:
        return True
    if month == 3:
        # Calculate the last Sunday in March
        last_sunday = 31 - (weekday if day > 24 else weekday + 7)
        return day > last_sunday
    if month == 10:
        # BST ends on the last Sunday in October
        last_sunday = 31 - (weekday if day > 24 else weekday + 7)
        return day <= last_sunday
    return False

def update():
    global time_string
    # grab the current time from the NTP server and update the Pico RTC
    try:
        ntptime.settime()
    except OSError:
        print("Unable to contact NTP server")

    # Get the current time from the RTC
    current_t = rtc.datetime()

    # Extract the hour and minute
    hour = current_t[4] # Hours since midnight [0, 23]
    minute = current_t[5] # Minutes after the hour [0, 59]

    # Manually check if BST should apply
    if is_bst(current_t):
        hour += 1

        # Handle hour overflow (24-hour format)
        if hour == 24:
            hour = 0

    # Calculate the approximate time in words
    time_string = approx_time(hour - 12 if hour > 12 else hour, minute)

    # Splits the string into an array of words for displaying later
    time_string = time_string.split()

    print(time_string)

def draw():
    global time_string
    graphics.set_font("bitmap8")

    WIDTH, HEIGHT = graphics.get_bounds()

    # Clear the screen
    graphics.set_pen(1)
    graphics.clear()
    graphics.set_pen(6)

    # Values for the layout and spacing
    if WIDTH == 640: # Inky Frame 4.0"
        default_x = 5
        x = default_x
        y = 10
        line_space = 70
        letter_space = 40
    elif WIDTH == 800:
        default_x = 5
        x = default_x
        y = 70
        line_space = 60
        letter_space = 50
    else: # Inky Frame 5.7"
        default_x = 20
        x = default_x
        y = 40
        line_space = 65
        letter_space = 35

    scale = 5
    spacing = 2

    for word in words:

        if word in time_string:
            graphics.set_pen(0)
        else:
            graphics.set_pen(graphics.create_pen(220, 220, 220))

        for letter in word:
            text_length = graphics.measure_text(letter, scale, spacing)
            if not x + text_length <= WIDTH:
                y += line_space
                x = default_x

            graphics.text(letter.upper(), x, y, 640, scale=scale, spacing=spacing)
            x += letter_space

    graphics.update()

```

I hope this helps.

---

<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:** [August 9, 2024, 1:51pm UTC](https://forums.pimoroni.com/t/inky-frame-word-clock-bst-modification/25227/2 "2024-08-09T13:51:02Z")

</div>

Instead of calculating the daylight saving time period manually, it would be easier to query [http://worldtimeapi.org/api/ip](http://worldtimeapi.org/api/ip) directly instead of ntp. The problem with your approach: it is not universally valid: British DST-rules are British DST-rules, but not universally valid.

The output of [worldtimeapi.org](http://worldtimeapi.org) is an easy to parse JSON-structure:

```auto
{
  "utc_offset": "+02:00",
  "timezone": "Europe/Berlin",
  "day_of_week": 5,
  "day_of_year": 222,
  "datetime": "2024-08-09T15:46:01.818053+02:00",
  "utc_datetime": "2024-08-09T13:46:01.818053+00:00",
  "unixtime": 1723211161,
  "raw_offset": 3600,
  "week_number": 32,
  "dst": true,
  "abbreviation": "CEST",
  "dst_offset": 3600,
  "dst_from": "2024-03-31T01:00:00+00:00",
  "dst_until": "2024-10-27T01:00:00+00:00",
  "client_ip": "xx.xx.xx.xx"
}

```

Instead of querying by IP, you can also pass a timezone to the API.

---

<div class="post-metadata">

**Author:** ![MikeB\_50](https://avatars.discourse-cdn.com/v4/letter/m/b9e5f3/32.png) [@MikeB\_50](https://forums.pimoroni.com/u/MikeB_50)\
**Post date:** [September 30, 2024, 12:40pm UTC](https://forums.pimoroni.com/t/inky-frame-word-clock-bst-modification/25227/3 "2024-09-30T12:40:43Z")

</div>

I came across this thread while looking for sample Micropython code to handle British Summer Time when not connected to the internet.

I would like to offer an alternative algorithm for calculating the last Sunday in March and October:  
` last_sunday = 25 + (day + 9 - weekday)%7`  
as I didn’t understand the original version.

Although this is not universally valid, it should work in the EU as well as the UK, as I believe we use the same DST rules.

Here is a little program to check the results:

```auto
import time

def is_bst(date_tuple):
  # year, month, day, weekday, hour, minute, second, subseconds = date_tuple[:8]
    year, month, day, hour, minute, second, weekday, yearday = date_tuple[:8]

    # BST starts at 01:00 GMT on the last Sunday in March
    # and ends at 02:00 BST on the last Sunday in October
    if 3 < month < 10:
        return True
    if month == 3:
        # Calculate the last Sunday (weekday 6) in March
      # last_sunday = 31 - (weekday if day > 24 else weekday + 7)
      # return day > last_sunday
        last_sunday = 25 + (day + 9 - weekday)%7
        return day >= last_sunday
    if month == 10:
      # last_sunday = 31 - (weekday if day > 24 else weekday + 7)
      # return day <= last_sunday
        last_sunday = 25 + (day + 9 - weekday)%7
        return day < last_sunday
    return False

# Main program...

for year in range(2015, 2025):
    for month in (3, 10):
        print("")
        for day in range(32):
            date_time = time.gmtime(time.mktime((year, month, day, 0, 0, 0, 0, 0, 0)))
            print(date_time, is_bst(date_time))

```

I used time.gmtime and time.mktime to provide the appropriate weekday for each date.

Note that gmtime and mktime use a slightly different date-time format to machine.RTC.
