Склонение слов в зависимости от числа

Есть функция которая выводит стаж.
Можно ли добавить в функцию склонить слов в зависимости от числа которое выводится?
Подставить вместо:
11111 - год, года, лет
22222 - месяц, месяцев
33333 - день, дня, дней

def stag(message):
    conn = sqlite3.connect(settings.DATABASE)
    cursor = conn.cursor()
    sql = """select last_name, first_name, third_name, data_p, data_z, 
            alldays / 365 as years,
            alldays % 365 / 31 as month,
            alldays % 30 as days
        from (select last_name, first_name, third_name, data_p, data_z,
            CAst((julianday(ifnull(data_z, 'now')) - julianday(data_p)) as Integer) as alldays
        from dovidnyk) WHERE last_name = ?"""
    cursor.execute(sql,)
    result = cursor.fetchall()
    for fn in result:
        msg =  "<i>? <u>ФИО</u></i>:  <b>{} {} {}</b>\n" \
               "<i>? <u>Дата приема</u></i>:  <b>{}</b>\n" \
               "Стаж {} 11111 {} 22222 {} 33333\n".format(fn[0], fn[1], fn[2], fn[3], fn[4], fn[5])
        bot.send_message(message.from_user.id, msg, reply_markup=keyboard, parse_mode='HTML')

Ответы (2 шт):

Автор решения: Ruslan G.

Может не самое элегантное решение, но как вариант.

dmy = {'y': 2, 'm': 5, 'd': 10}
words = {'y': ['лет', 'год', 'года'], 'm': ['месяцев', 'месяц', 'месяца'], 'd': ['дней', 'день', 'дня']}


out = []
for k, v in dmy.items():
    remainder = v % 10
    if v == 0 or remainder == 0 or remainder >= 5 or v in range(11, 19):  
        st = str(v), words[k][0]
    elif remainder == 1:  
        st = str(v), words[k][1]      
    else:  
        st = str(v), words[k][2]
    out.append(" ".join(st))

print(" ".join(out))

Вывод: 2 года 5 месяцев 10 дней

UPD: Например, вот так:

import sqlite3
conn = sqlite3.connect('111.db')
cursor = conn.cursor()

# Записи в таблице:
# Иванов  Иван    Иванович    2001-02-01  2006-08-02
# Смирнов Андрей  Анатольевич 2002-03-05  2012-08-12


sql = """select last_name, first_name, third_name, data_p, data_z, 
        alldays / 365 as years,
        alldays % 365 / 31 as month,
        alldays % 30 as days
    from (select last_name, first_name, third_name, data_p, data_z,
        CAST((julianday(ifnull(data_z, 'now')) - julianday(data_p)) as Integer) as alldays
    from dovidnyk) """

cursor.execute(sql,)
result = cursor.fetchall()
# [('Иванов', 'Иван', 'Иванович', '2001-02-01', '2006-08-02', 5, 5, 28)]

for fn in result:
    dmy = {'y': fn[5], 'm': fn[6], 'd': fn[7]}
    words = {'y': ['лет', 'год', 'года'], 'm': ['месяцев', 'месяц', 'месяца'], 'd': ['дней', 'день', 'дня']}
    out = []
    for k, v in dmy.items():
        remainder = v % 10
        if v == 0 or remainder == 0 or remainder >= 5 or v in range(11, 19):  
            st = str(v), words[k][0]
        elif remainder == 1:  
            st = str(v), words[k][1]      
        else:  
            st = str(v), words[k][2]
        out.append(" ".join(st))

    msg = "<i>? <u>ФИО</u></i>:  <b>{} {} {}</b>\n" \
          "<i>? <u>Дата приема</u></i>:  <b>{}</b>\n" \
          "Стаж {} {} {} \n".format(fn[0], fn[1], fn[2], fn[3], out[0], out[1], out[2])
    print(msg)

conn.close()

Вывод:

<i>? <u>ФИО</u></i>:  <b>Иванов Иван Иванович</b>
<i>? <u>Дата приема</u></i>:  <b>2001-02-01</b>
Стаж 5 лет 5 месяцев 28 дней 

<i>? <u>ФИО</u></i>:  <b>Смирнов Андрей Анатольевич</b>
<i>? <u>Дата приема</u></i>:  <b>2002-03-05</b>
Стаж 10 лет 5 месяцев 3 дня 

UPD2: Можно еще добавить conn.row_factory = sqlite3.Row перед cursor = conn.cursor() тогда результат запроса будет сразу в dict, и код немного упростится.

conn.row_factory = sqlite3.Row
cursor = conn.cursor()    

cursor.execute(sql,) 
for fn in cursor.fetchall():
    fn = dict(fn)
    words = {'years': ['лет', 'год', 'года'], 'month': ['месяцев', 'месяц', 'месяца'], 'days': ['дней', 'день', 'дня']}
    for k in words.keys():
        remainder = fn[k] % 10
        if fn[k] == 0 or remainder == 0 or remainder >= 5 or fn[k] in range(11, 19):  
            st = str(fn[k]), words[k][0]
        elif remainder == 1:  
            st = str(fn[k]), words[k][1]      
        else:  
            st = str(fn[k]), words[k][2]
        fn[k] = " ".join(st)
    msg = "<i>? <u>ФИО</u></i>:  <b>{} {} {}</b>\n" \
          "<i>? <u>Дата приема</u></i>:  <b>{}</b>\n" \
          "Стаж {} {} {} \n".format(fn['last_name'],
            fn['first_name'], fn['third_name'], fn['data_p'], fn['years'], fn['month'], fn['days'])
    print(msg)

conn.close()
→ Ссылка
Автор решения: Aleksei Trankov
age_token = lambda age_to: (
        (age_to in range(5, 20)) and 'лет' or
        (1 in (age_to, (diglast := age_to % 10))) and 'год' or
        ({age_to, diglast} & {2, 3, 4}) and 'года' or 'лет')
>>> f'50 {age_token(50)}'
50 лет

То же самое с подстановкой нужного слова

def numeral_noun_declension(
    number,
    nominative_singular,
    genetive_singular,
    nominative_plural
):
    return (
        (number in range(5, 20)) and nominative_plural or
        (1 in (number, (diglast := number % 10))) and nominative_singular or
        ({number, diglast} & {2, 3, 4}) and genetive_singular or nominative_plural
    )
>>> 22, numeral_noun_declension(22, 'собака', 'собаки', 'собак')
22, собаки
→ Ссылка