Turkish Time and Clock

Introduction

Turkish Time with Turkish flag

This chapter of our Python tutorial deals with turkish times. You will learn how to tell the time in turkish, but what is more him important: We will teach Python to tell the time in Turkish given the time numerically. Turkish grammar and sentence structures as well as vocabulary differ extremely from Indo-European languages like English and Persian, and also Semitic languages like Arabic and Hebrew and many other languages. So, telling the time in Turkish is also extremely difficult for speakers of English, German, French, Italian and many other languages. Fortunately, there are strict rules available. Rules which are so regular that it is easy to write a Python program to the job.

"Saat kaç?" means "What is the time?" in Turkish.

The task of hour program is to answer this question, given the time as string in the form "03:00" or "10:30".

We will need the words for the digits 0, 1, ... 9. We use a Pyhton list for this:

digits_list = ["bir", "iki", "üç", 
               "dört", "beş", "altı",
               "yedi", "sekiz", "dokuz"]  

The digits are not enough. We will need the words for the tens as well. The following list corresponds to the numbers "ten", "twenty", "thirty", "forty", and "fifty". We do not need more:

tens_list = ["on", "yirmi", "otuz",  "kırk",  "elli"]

Verbal Representation of Numbers

Now, we need a function to transform any number between 1 and 59 to a turkish verbal representation. We can easily define this function, because it is more regular than in English. You will hopefully understand it by just looking at the function:

def num2txt(min):
    digits = min % 10
    tens = min // 10
    if digits > 0:
        if tens:
            return tens_list[tens-1] + " " + digits_list[digits-1]
        else:
            return digits_list[digits-1]
    else:
        return tens_list[tens-1]
    
for number in range(60):
    print(number, num2txt(number), end=", ")
0 elli, 1 bir, 2 iki, 3 üç, 4 dört, 5 beş, 6 altı, 7 yedi, 8 sekiz, 9 dokuz, 10 on, 11 on bir, 12 on iki, 13 on üç, 14 on dört, 15 on beş, 16 on altı, 17 on yedi, 18 on sekiz, 19 on dokuz, 20 yirmi, 21 yirmi bir, 22 yirmi iki, 23 yirmi üç, 24 yirmi dört, 25 yirmi beş, 26 yirmi altı, 27 yirmi yedi, 28 yirmi sekiz, 29 yirmi dokuz, 30 otuz, 31 otuz bir, 32 otuz iki, 33 otuz üç, 34 otuz dört, 35 otuz beş, 36 otuz altı, 37 otuz yedi, 38 otuz sekiz, 39 otuz dokuz, 40 kırk, 41 kırk bir, 42 kırk iki, 43 kırk üç, 44 kırk dört, 45 kırk beş, 46 kırk altı, 47 kırk yedi, 48 kırk sekiz, 49 kırk dokuz, 50 elli, 51 elli bir, 52 elli iki, 53 elli üç, 54 elli dört, 55 elli beş, 56 elli altı, 57 elli yedi, 58 elli sekiz, 59 elli dokuz, 

We will start now implementing the function translate_time. This function will produce a reply to the question "Saat kaç?". It takes hours and minutes as parameters. We will only implement the funciton for full hours, because this is the easiest case.

def translate_time(hours, minutes=0):
    if minutes == 0:
        return "Saat " + num2txt(hours) + "."
    else:
        return "I still do not know how to say it!"
    
for hour in range(1, 13):
    print(hour, translate_time(hour))
1 Saat bir.
2 Saat iki.
3 Saat üç.
4 Saat dört.
5 Saat beş.
6 Saat altı.
7 Saat yedi.
8 Saat sekiz.
9 Saat dokuz.
10 Saat on.
11 Saat on bir.
12 Saat on iki.

Easy, isn't it? What about "half past"? This is similar to English, if you consider that "buçuk" means "half". We extend our function:

def translate_time(hours, minutes=0):
    if minutes == 0:
        return "Saat " + num2txt(hours) + "."
    elif minutes == 30:
        return "Saat " + num2txt(hours) + " buçuk."
    else:
        return "I still do not know how to say it!"
    
for hour in range(1, 13):
    print(hour, translate_time(hour, 30))
1 Saat bir buçuk.
2 Saat iki buçuk.
3 Saat üç buçuk.
4 Saat dört buçuk.
5 Saat beş buçuk.
6 Saat altı buçuk.
7 Saat yedi buçuk.
8 Saat sekiz buçuk.
9 Saat dokuz buçuk.
10 Saat on buçuk.
11 Saat on bir buçuk.
12 Saat on iki buçuk.

We want to go on with telling the time in Turkish, and teach our Python program to say "a quarter past" and a "quarter to". It is getter more complicated or interesting now. Our Python implementation needs to learn some grammar rules now. The Python program has to learn now how to produce the Dative and the Accusative in Turkish.

Turkish Dative

The dative case is formed by adding e or a as a suffix to the end of the word (not necessarily a noun). If the last syllable of the word has one of the vowels 'a', 'ı', 'o' or 'u', an 'a' has to be added to the end of the word. If the last syllable of the word has one of the vowels 'e', 'i', 'ö', or 'ü', an 'e' has to be appended. One more important thing: Turkish doesn't like to vowels beside of each other. Therefore, we will add a "y" in front ot the 'e' or 'a', if the last letter of the word is a vowel.

Now we are ready to implement the dative function. It will suffix the dative ending to a given word. The dative function needs a function last_vowel which comes back with two values:

  • the vowel in the last syllable
  • True or False to indicate if the word ends with a vowel
def last_vowel(word):
    vowels = {'ı', 'a', 'e', 'i', 'o', 'u', 'ö', 'ü'}
    ends_with_vowel = True
    for char in word[::-1]:
        if char in vowels:
            return char, ends_with_vowel
        ends_with_vowel = False

def dative(word):
    lv, ends_with_vowel = last_vowel(word)
    if lv in {'i', 'e', 'ö', 'ü'}:
        ret_vowel = 'e' 
    elif lv in {'a', 'ı', 'o', 'u'}:
        ret_vowel = 'a'
    if ends_with_vowel:
        return word + "y" + ret_vowel
    else:
        return word + ret_vowel

We can check the dative function by calling it with the numbers in digits_list:

for word in digits_list:
    print(word, dative(word))
bir bire
iki ikiye
üç üçe
dört dörte
beş beşe
altı altıya
yedi yediye
sekiz sekize
dokuz dokuza

Turkish Accusative

'-i', '-ı', '-u' or '-ü' will be added to a word according to the last vowel of the word.

Last vowel Vowel to be Added
ı or a ı
e or i i
o or u u
ö or ü ü

This can be easily implemented as a Python function:

def accusative(word):
    lv, ends_with_vowel = last_vowel(word)
    if lv in {'ı', 'a'}:
        ret_vowel = 'ı' 
    elif lv in {'e', 'i'}:
        ret_vowel = 'i'
    elif lv in {'o', 'u'}:
        ret_vowel = 'u'
    elif lv in {'ö', 'ü'}:
        ret_vowel = 'ü'
    if ends_with_vowel:
        return word + "y" + ret_vowel
    else:
        return word + ret_vowel

Let us have a look at the dative and accusative together:

print(f"{'word':<20s} {'dative':<20s} {'accusative':<20s}")
for word in digits_list:
    print(f"{word:<20s} {dative(word):<20s} {accusative(word):<20s}")
word                 dative               accusative          
bir                  bire                 biri                
iki                  ikiye                ikiyi               
üç                   üçe                  üçü                 
dört                 dörte                dörtü               
beş                  beşe                 beşi                
altı                 altıya               altıyı              
yedi                 yediye               yediyi              
sekiz                sekize               sekizi              
dokuz                dokuza               dokuzu              

Now, we have programmed what we need to further extend the translate_time function. We will add now the branches for "a quarter to" and "a quarter past". A "quarter" means "çeyrek" in Turkish. "to" and "past" are translated by adding "var" and "geçiyor" to the end. The verbal representation of the hour number has to be put into the dative in case of "var" and into the accusative form in case of "geçiyor".

def translate_time(hours, minutes=0):
    if minutes == 0:
        return "Saat " + num2txt(hours) + "."
    elif minutes == 30:
        return "Saat " + num2txt(hours) + " buçuk."
    elif minutes == 15:
        return "Saat " + accusative(num2txt(hours)) + " çeyrek geçiyor."
    elif minutes == 45:
        if hours == 12: 
            hours = 0
        return "Saat " + dative(num2txt(hours+1)) + " çeyrek var."
    else:
        return "I still do not know how to say it!"

    
for hour in range(1, 13):
    print(f"{hour:02d}:{15:02d} {translate_time(hour, 15):25s}")
    print(f"{hour:02d}:{45:02d} {translate_time(hour, 45):25s}")
01:15 Saat biri çeyrek geçiyor.
01:45 Saat ikiye çeyrek var.   
02:15 Saat ikiyi çeyrek geçiyor.
02:45 Saat üçe çeyrek var.     
03:15 Saat üçü çeyrek geçiyor. 
03:45 Saat dörte çeyrek var.   
04:15 Saat dörtü çeyrek geçiyor.
04:45 Saat beşe çeyrek var.    
05:15 Saat beşi çeyrek geçiyor.
05:45 Saat altıya çeyrek var.  
06:15 Saat altıyı çeyrek geçiyor.
06:45 Saat yediye çeyrek var.  
07:15 Saat yediyi çeyrek geçiyor.
07:45 Saat sekize çeyrek var.  
08:15 Saat sekizi çeyrek geçiyor.
08:45 Saat dokuza çeyrek var.  
09:15 Saat dokuzu çeyrek geçiyor.
09:45 Saat ona çeyrek var.     
10:15 Saat onu çeyrek geçiyor. 
10:45 Saat on bire çeyrek var. 
11:15 Saat on biri çeyrek geçiyor.
11:45 Saat on ikiye çeyrek var.
12:15 Saat on ikiyi çeyrek geçiyor.
12:45 Saat bire çeyrek var.    

We can finish the translate_time function now. We have to branches for the minutes.

def translate_time(hours, minutes=0):
    if minutes == 0:
        return "Saat " + num2txt(hours) + "."
    elif minutes == 30:
        return "Saat " + num2txt(hours) + " buçuk."
    elif minutes == 15:
        return "Saat " + accusative(num2txt(hours)) + " çeyrek geçiyor."
    elif minutes == 45:
        if hours == 12: 
            hours = 0
        return "Saat " + dative(num2txt(hours+1)) + " çeyrek var."
    elif minutes < 30:
        return "Saat " + accusative(num2txt(hours)) + " " + num2txt(minutes) + " geçiyor."
    elif minutes > 30:
        minutes = 60 - minutes
        if hours == 12:
            hours = 0
        hours = dative(num2txt(hours + 1))
        mins = num2txt(minutes)
        return  "Saat " + hours + " " + mins + " var."

for hour in range(1, 13, 1):
    for min in range(1, 60, 9):
        print(f"{hour:02d}:{min:02d} {translate_time(hour, min):25s}")
01:01 Saat biri bir geçiyor.   
01:10 Saat biri on geçiyor.    
01:19 Saat biri on dokuz geçiyor.
01:28 Saat biri yirmi sekiz geçiyor.
01:37 Saat ikiye yirmi üç var. 
01:46 Saat ikiye on dört var.  
01:55 Saat ikiye beş var.      
02:01 Saat ikiyi bir geçiyor.  
02:10 Saat ikiyi on geçiyor.   
02:19 Saat ikiyi on dokuz geçiyor.
02:28 Saat ikiyi yirmi sekiz geçiyor.
02:37 Saat üçe yirmi üç var.   
02:46 Saat üçe on dört var.    
02:55 Saat üçe beş var.        
03:01 Saat üçü bir geçiyor.    
03:10 Saat üçü on geçiyor.     
03:19 Saat üçü on dokuz geçiyor.
03:28 Saat üçü yirmi sekiz geçiyor.
03:37 Saat dörte yirmi üç var. 
03:46 Saat dörte on dört var.  
03:55 Saat dörte beş var.      
04:01 Saat dörtü bir geçiyor.  
04:10 Saat dörtü on geçiyor.   
04:19 Saat dörtü on dokuz geçiyor.
04:28 Saat dörtü yirmi sekiz geçiyor.
04:37 Saat beşe yirmi üç var.  
04:46 Saat beşe on dört var.   
04:55 Saat beşe beş var.       
05:01 Saat beşi bir geçiyor.   
05:10 Saat beşi on geçiyor.    
05:19 Saat beşi on dokuz geçiyor.
05:28 Saat beşi yirmi sekiz geçiyor.
05:37 Saat altıya yirmi üç var.
05:46 Saat altıya on dört var. 
05:55 Saat altıya beş var.     
06:01 Saat altıyı bir geçiyor. 
06:10 Saat altıyı on geçiyor.  
06:19 Saat altıyı on dokuz geçiyor.
06:28 Saat altıyı yirmi sekiz geçiyor.
06:37 Saat yediye yirmi üç var.
06:46 Saat yediye on dört var. 
06:55 Saat yediye beş var.     
07:01 Saat yediyi bir geçiyor. 
07:10 Saat yediyi on geçiyor.  
07:19 Saat yediyi on dokuz geçiyor.
07:28 Saat yediyi yirmi sekiz geçiyor.
07:37 Saat sekize yirmi üç var.
07:46 Saat sekize on dört var. 
07:55 Saat sekize beş var.     
08:01 Saat sekizi bir geçiyor. 
08:10 Saat sekizi on geçiyor.  
08:19 Saat sekizi on dokuz geçiyor.
08:28 Saat sekizi yirmi sekiz geçiyor.
08:37 Saat dokuza yirmi üç var.
08:46 Saat dokuza on dört var. 
08:55 Saat dokuza beş var.     
09:01 Saat dokuzu bir geçiyor. 
09:10 Saat dokuzu on geçiyor.  
09:19 Saat dokuzu on dokuz geçiyor.
09:28 Saat dokuzu yirmi sekiz geçiyor.
09:37 Saat ona yirmi üç var.   
09:46 Saat ona on dört var.    
09:55 Saat ona beş var.        
10:01 Saat onu bir geçiyor.    
10:10 Saat onu on geçiyor.     
10:19 Saat onu on dokuz geçiyor.
10:28 Saat onu yirmi sekiz geçiyor.
10:37 Saat on bire yirmi üç var.
10:46 Saat on bire on dört var.
10:55 Saat on bire beş var.    
11:01 Saat on biri bir geçiyor.
11:10 Saat on biri on geçiyor. 
11:19 Saat on biri on dokuz geçiyor.
11:28 Saat on biri yirmi sekiz geçiyor.
11:37 Saat on ikiye yirmi üç var.
11:46 Saat on ikiye on dört var.
11:55 Saat on ikiye beş var.   
12:01 Saat on ikiyi bir geçiyor.
12:10 Saat on ikiyi on geçiyor.
12:19 Saat on ikiyi on dokuz geçiyor.
12:28 Saat on ikiyi yirmi sekiz geçiyor.
12:37 Saat bire yirmi üç var.  
12:46 Saat bire on dört var.   
12:55 Saat bire beş var.       
digits_list = ["bir", "iki", "üç", 
               "dört", "beş", "altı",
               "yedi", "sekiz", "dokuz"]  

tens_list = ["on", "yirmi", "otuz",  "kırk",  "elli"]

def num2txt(min):
    """ numbers are mapped into verbal representation """
    digits = min % 10
    tens = min // 10
    if digits > 0:
        if tens:
            return tens_list[tens-1] + " " + digits_list[digits-1]
        else:
            return digits_list[digits-1]
    else:
        return tens_list[tens-1]

    
def last_vowel(word):
    """ returns a tuple 'vowel', 'ends_with_vowel' 
        'vowel' is the last vowel of the word 'word'
        'ends_with_vowel' is True if the word ends with a vowel
        False otherwise
    """
    vowels = {'ı', 'a', 'e', 'i', 'o', 'u', 'ö', 'ü'}
    ends_with_vowel = True
    for char in word[::-1]:
        if char in vowels:
            return char, ends_with_vowel
        ends_with_vowel = False

        
def dative(word):
    """  returns 'word' in dative form """
    lv, ends_with_vowel = last_vowel(word)
    if lv in {'i', 'e', 'ö', 'ü'}:
        ret_vowel = 'e' 
    elif lv in {'a', 'ı', 'o', 'u'}:
        ret_vowel = 'a'
    if ends_with_vowel:
        return word + "y" + ret_vowel
    else:
        return word + ret_vowel

    
def accusative(word):
    """ return 'word' in accusative form """
    lv, ends_with_vowel = last_vowel(word)
    if lv in {'ı', 'a'}:
        ret_vowel = 'ı' 
    elif lv in {'e', 'i'}:
        ret_vowel = 'i'
    elif lv in {'o', 'u'}:
        ret_vowel = 'u'
    elif lv in {'ö', 'ü'}:
        ret_vowel = 'ü'
    if ends_with_vowel:
        return word + "y" + ret_vowel
    else:
        return word + ret_vowel

    
def translate_time(hours, minutes=0):
    """ construes the verbal represention
        of the time 'hours':'minutes
    '"""
    if minutes == 0:
        return "Saat " + num2txt(hours) + "."
    elif minutes == 30:
        return "Saat " + num2txt(hours) + " buçuk."
    elif minutes == 15:
        return "Saat " + accusative(num2txt(hours)) + " çeyrek geçiyor."
    elif minutes == 45:
        if hours == 12: 
            hours = 0
        return "Saat " + dative(num2txt(hours+1)) + " çeyrek var."
    elif minutes < 30:
        return "Saat " + accusative(num2txt(hours)) + " " + num2txt(minutes) + " geçiyor."
    elif minutes > 30:
        minutes = 60 - minutes
        if hours == 12:
            hours = 0
        hours = dative(num2txt(hours + 1))
        mins = num2txt(minutes)
        return  "Saat " + hours + " " + mins + " var."
Overwriting turkish_time.py

Let us test the previous Python code with some times:

from turkish_time import translate_time
for hour, min in [(12, 47), (1, 23), (16, 9)]:
        print(f"{hour:02d}:{min:02d} {translate_time(hour, min):25s}")
12:47 Saat bire on üç var.     
01:23 Saat biri yirmi üç geçiyor.
16:09 Saat on altıyı dokuz geçiyor.

We implement in the following Python program a clock, which uses a graphical user interface. This clock shows the current time in a verbal representation. Of course, in Turkish:

In [ ]:
import tkinter as tk
import datetime
from turkish_time import translate_time

def get_time():
    now = datetime.datetime.now()
    return now.hour, now.minute

def time_text_label(label):
    def new_time():
        now = datetime.datetime.now()
        res = translate_time(now.hour, now.minute)
        label.config(text=res)
        label.after(1000, new_time)
    new_time()

flag_img = "images/turkish_flag_clock_background.png"
root = tk.Tk()
root.option_add( "*font", "lucida 36 bold" )
root.title("Turkish Time")
flag_img = tk.PhotoImage(file=flag_img)
flag_img = flag_img.subsample(4, 4) # shrink image, divide by 4
flag_label = tk.Label(root, image=flag_img)
flag_label.pack(side=tk.LEFT)
label = tk.Label(root, 
                 font = "Latin 18 bold italic",
                 fg="dark green")
label.pack(side=tk.RIGHT)
time_text_label(label)
button = tk.Button(root, 
                   text='Stop', 
                   font = "Latin 12 bold italic",
                   command=root.destroy)
button.pack(side=tk.RIGHT)
root.mainloop()