Fuzzy-Clock for Ubuntu
Solution 1:
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 Mate
as 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
-
Show the textual "day-area" (night, morning, day, evening)
-
Show a.m. / p.m.
-
Show all of them at once (or any combination of the three)
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:
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
-
The script needs
espeak
:sudo apt-get install espeak
Copy all three files above into one and the same directory, exactly named as indicated in The script, the module and an icon
-
In the head of the script (
moderntimes.py
), define which information should be displayed, and how. Simply setTrue
orFalse
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
-
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 :)
-
Ubuntu Mate users need to enable the use of indicators on their system: choose System > Preferences > Look and feel > Mate tweak > Interface > "Enable indicators"
-
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
, butmidnight
, 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:
As mentioned, this version was tested on both Mate
(from the original question) Unity
and Xubuntu
.
Solution 2:
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.