9

A long while ago, I had a clock set to say things like morning, day, evening, night, for time in a panel app. Broad stroke, not very specific, It might have been a KDE desktop. I am in Ubuntu Mate now, is there a way to get this vague time description in the mate panel?

8
  • 1
    if it helps, this is called a fuzzy clock
    – Dmiters
    Mar 28 '16 at 22:42
  • It does help. :)
    – j0h
    Mar 28 '16 at 22:46
  • 1
    Here is the source code: code.google.com/archive/p/fuzzy-clock Now we need @jacobvlijm to make it into a app >:-D
    – Rinzwind
    Mar 29 '16 at 11:43
  • I started reading Mate-University for making panel apps. Im sure I can program something like this, but i have no clue about how to make it a panel app
    – j0h
    Mar 29 '16 at 12:04
  • 1
    this was in KDE, I'm sure of this, and was translated as well!
    – Antek
    May 27 '19 at 15:00
15
+100

Textual / speaking clock for Mate and other Ubuntu variants

Although the question was originally about Ubuntu Mate, luckily, from 15.10, indicators can be used on Mateas well. As a result, the answer below at least works for Unity and Mate and (tested) on Xubuntu.

A GUI to change settings is still to follow (working on it), but I tested the indicator below for at least 20 hrs, and (as expected) it did the job without an error.

Options

The indicator offers the following options:

  • Show the textual time

    enter image description here

  • Show the textual "day-area" (night, morning, day, evening)

    enter image description here

  • Show a.m. / p.m.

    enter image description here

  • Show all of them at once (or any combination of the three)

    enter image description here

  • Speak out the time every quarter of an hour (espeak required)

  • Optionally, the time is displayed fuzzy; rounded on five minutes, e.g.
    10:43 -> quarter to eleven.

The script, the module and an icon

The solution exists of a script, a separate module and an icon, which you need to store in one and the same directory.

The icon:

enter image description here

Right-clck on it and save it as (exactly) indicator_icon.png

The module:

This is the module that produces the textual time and all other displayed information. Copy the code, save it as (again, exactly) tcalc.py, together with the icon above in one and the same directory.

#!/usr/bin/env python3
import time

# --- set starttime of morning, day, evening, night (whole hrs)
limits = [6, 9, 18, 21]
# ---

periods = ["night", "morning", "day", "evening", "night"]

def __fig(n):
    singles = [
        "midnight", "one", "two", "three", "four", "five", "six",
        "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen",
        "fourteen", "quarter", "sixteen", "seventeen", "eighteen", "nineteen",
        ]
    tens = ["twenty", "half"]
    if n < 20:
        return singles[n]
    else:
        if n%10 == 0:
            return tens[int((n/10)-2)]
        else:
            fst = tens[int(n/10)-2]
            lst = singles[int(str(n)[-1])]
            return fst+"-"+lst

def __fuzzy(currtime):
    minutes = round(currtime[1]/5)*5
    if minutes == 60:
        currtime[1] = 0
        currtime[0] = currtime[0] + 1
    else:
        currtime[1] = minutes
    currtime[0] = 0 if currtime[0] == 24 else currtime[0]
    return currtime

def textualtime(fuzz):
    currtime = [int(n) for n in time.strftime("%H %M %S").split()]
    currtime = __fuzzy(currtime) if fuzz == True else currtime
    speak = True if currtime[1]%15 == 0 else False
    period = periods[len([n for n in limits if currtime[0] >= n])]
    # define a.m. / p.m.
    if currtime[0] >= 12:
        daytime = "p.m."
        if currtime[0] == 12:
            if currtime[1] > 30:
                currtime[0] = currtime[0] - 12
        else:
            currtime[0] = currtime[0] - 12
    else:
        daytime = "a.m."
    # convert time to textual time
    if currtime[1] == 0:
        t = __fig(currtime[0])+" o'clock" if currtime[0] != 0 else __fig(currtime[0])
    elif currtime[1] > 30:
        t = __fig((60 - currtime[1]))+" to "+__fig(currtime[0]+1)
    else:
        t = __fig(currtime[1])+" past "+__fig(currtime[0])
    return [t, period, daytime, currtime[2], speak]

The script:

This is the actual indicator. Copy the code, save it as moderntimes.py, together with the icon and th module above in one and the same directory.

#!/usr/bin/env python3
import os
import signal
import subprocess
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, AppIndicator3, GObject
import time
from threading import Thread
import tcalc

# --- define what to show:
# showtime = textual time, daytime = a.m./p.m. period = "night"/"morning"/day"/"evening"
# speak = speak out time every quarter, fuzzy = round time on 5 minutes
showtime = True; daytime = False; period = True; speak = True; fuzzy = True

class Indicator():
    def __init__(self):
        self.app = 'about_time'
        path = os.path.dirname(os.path.abspath(__file__))
        self.indicator = AppIndicator3.Indicator.new(
            self.app, os.path.abspath(path+"/indicator_icon.png"),
            AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)       
        self.indicator.set_menu(self.create_menu())

        self.update = Thread(target=self.get_time)
        self.update.setDaemon(True)
        self.update.start()

    def get_time(self):
        # the first loop is 0 seconds, the next loop is 60 seconds,
        # in phase with computer clock
        loop = 0; timestring1 = ""
        while True:
            time.sleep(loop)
            tdata = tcalc.textualtime(fuzzy)
            timestring2 = tdata[0]
            loop = (60 - tdata[3])+1
            mention = (" | ").join([tdata[item[1]] for item in [
                [showtime, 0], [period, 1], [daytime, 2]
                ]if item[0] == True])
            if all([
                tdata[4] == True,
                speak == True,
                timestring2 != timestring1,
                ]):
                subprocess.Popen(["espeak", '"'+timestring2+'"', "-s", "130"])
            # [4] edited
            GObject.idle_add(
                self.indicator.set_label,
                mention, self.app,
                priority=GObject.PRIORITY_DEFAULT
                )
            timestring1 = timestring2

    def create_menu(self):
        menu = Gtk.Menu()
        item_quit = Gtk.MenuItem('Quit')
        item_quit.connect('activate', self.stop)
        menu.append(item_quit)
        menu.show_all()
        return menu

    def stop(self, source):
        Gtk.main_quit()

Indicator()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

How to use

  1. The script needs espeak:

    sudo apt-get install espeak
    
  2. Copy all three files above into one and the same directory, exactly named as indicated in The script, the module and an icon

  3. In the head of the script (moderntimes.py), define which information should be displayed, and how. Simply set True or False in the line:

    # --- define what to show:
    # time = textual time, daytime = a.m./p.m. period = "night"/"morning"/day"/"evening"
    # speak = speak out time every quarter, fuzzy = round time on 5 minutes
    showtime = True; daytime = False; period = True; speak = False; fuzzy = True
    
  4. In the head of the module, you can change the hours when to start subsequently morning, day, evening, night, in the line:

    # --- set starttime of morning, day, evening, night (whole hrs)
    limits = [6, 9, 18, 21]
    # ---
    

    Don't touch anything else in the script for now :)

  5. Ubuntu Mate users need to enable the use of indicators on their system: choose System > Preferences > Look and feel > Mate tweak > Interface > "Enable indicators"

    enter image description here

  6. Run the indicator with the command:

    python3 /path/to/moderntimes.py
    

Running it from Startup Applications

Remember that if you run the command from Startup Applications, in many cases you need to add a little break, especially (among others) on indicators:

/bin/bash -c "sleep 15 && python3 /path/to/moderntimes.py"

Notes

  • No doubt the script will be changed/updated in the next few days many times. One thing I'd like feedback on in particular is the "style" in which the digital time is converted into textual time. The way it is done now:

    • whole hours, e.g.:

      six o'clock
      
    • less then 30 mins after the hour, e.g.

      twenty past eleven
      
    • 30 mins after the hour e.g.:

      half past five
      
    • more the 30 mins e.g.:

      twenty to five
      
    • 15 minutes are mentioned quarter, e.g.:

      quarter past six
      
    • exception is midnight, which is not called zero, but midnight, e.g.:

      quarter past midnight
      
  • The script is extremely low on juice, due to the fact that after the first timecheck- loop, the loop is synchronized on the computer clock automatically. Therefore the script checks time/edits the displayed time only once per minute, sleeping the rest of the time.


Edit

As per today (2016-4-9), a ppa of a polished version is available. To install from ppa:

sudo apt-add-repository ppa:vlijm/abouttime
sudo apt-get update
sudo apt-get install abouttime

The day periods in this version are changed, compared to the script version above, now it is:

morning 6:00-12:00
afternoon 12:00-18:00
evening 18:00-24:00
night 24:00-6:00

... and the indicator has tho option to change the icon during daytime:
morning/afternoon/evening/night: enter image description here enter image description here enter image description here enter image description here

As mentioned, this version was tested on both Mate (from the original question) Unity and Xubuntu.

enter image description here

3
  • 1
    I would say: fuzzy means you can be inaccurate. So 15:12 through 15:23 or so would be quarter past 3. I'd say just use: 5/10/quarter/half past/to hour. It's not called fuzzy for nothing.
    – Rinzwind
    Apr 1 '16 at 13:13
  • Yet another awesome answer. I hope this gets integrated into your PPA.... :)
    – Parto
    Apr 1 '16 at 15:39
  • @Parto wow thanks again :) I will definitely create a ppa for this one :) Apr 1 '16 at 15:42
1

If you have Kubuntu (Plasma Desktop Ubuntu distro), you have a built-in widget called "fuzzy clock" -- it's been around at least since 14.04, or as long ago as Plasma 4 has been out, and it's still in Plasma 5 as found in Kubuntu 16.04.

Fuzzy Clock can be set to be as "accurate" as five minute increments, like reading an analog clock (say, "ten after four"), but it also has three "fuzzier" settings, one of which gives readings like "afternoon" and one that just gives "Weekend!" (on a Sunday afternoon -- I presume it'll say "Monday" tomorrow).

I don't know if fuzzy clock is available in other Ubuntu flavors -- I saw it in xfce (as found in Xubuntu) on my system, but the OS was installed as Kubuntu, so I'm not sure if the fuzzy clock is native to xfce as well as KDE/Plasma, nor whether it's available in Unity or Mate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.