Работа со временем

Для работы со временем в Python импортируют библиотеку datetime (англ. date «дата», time «время»). В ней есть не только отдельные функции, но и целый новый тип данных.

Называется он точно так же, как библиотека — datetime. Чтобы не путаться, будем подключать библиотеку под именем dt и так всегда к ней обращаться.

import datetime as dt
1

Тип данных datetime похож на уже привычные вам int, string и dict. Он нужен, чтобы хранить информацию о конкретном моменте времени: год, месяц, день, час, минуты, секунды и микросекунды.

Чтобы создать объект этого типа, нужно вызвать функцию datetime() из библиотеки dt. Она принимает обязательные аргументы — год, месяц и день, — и необязательные: час, минута, секунда и микросекунда, которые по умолчанию равны нулю.

Создадим объект типа datetime с датой и временем старта Гагарина:

import datetime as dt

# взлёт: 1961 год, 12 апреля, 9 часов утра, 7 минут
start_time = dt.datetime(1961, 4, 12, 9, 7, 0)
print(start_time)           # 1961-04-12 09:07:00
1
2
3
4
5

Тип данных datetime позволяет просто вычитать даты друг из друга, как обычные числа. Вот время между стартом Гагарина и его приземлением:

import datetime as dt

start_time = dt.datetime(1961, 4, 12, 9, 7, 0)
# дата и время посадки: 1961 год, 12 апреля, 10 часов, 55 минут
landing_time = dt.datetime(1961, 4, 12, 10, 55, 0)
print(landing_time - start_time)                # 1:48:00
1
2
3
4
5
6

Упражнения

  1. Научите Виту сообщать пользователю, сколько времени шёл его любимый сериал.
  • Дата выхода первой серии - 17 апреля 2011 года.
  • Дата выхода последней серии - 15 апреля 2019 года.
  1. Напишите код, отвечающий на запрос пользователя "Сколько времени у меня уже ушло на этот курс по разработке?" Вспомните, в какой день и во сколько вы начали проходить курс. Запишите этот момент времени в переменную start_moment. В переменную current_moment запишите текущий момент времени. Затем вычислите разницу двух этих моментов, запишите её в переменную total_time, и напечатайте её на экране.

Стандарт UTC

Есть несколько стандартов измерения и записи времени. Раньше в основном придерживались GMT (англ. «Greenwich Mean Time», среднее время по гринвичскому меридиану). Позже прежний всемирный формат был отменен и приняли новый, определяемый атомными часами. Это UTC — «coordinated universal time» — всемирное координированное время.

У каждой переменной типа данных datetime можно вызвать метод utcnow() (англ. now «сейчас»). Он вернёт текущий момент времени по UTC с эталонной точностью до микросекунд.

import datetime as dt

moment_in_time = dt.datetime(1961, 4, 12, 9, 7, 0)  # снова старт Гагарина
now = moment_in_time.utcnow()
print(now)  # напечатать на экран текущий момент времени
1
2
3
4
5

Более того, метод utcnow() настолько хитрый, что для его вызова необязательно явно создавать объект типа datetime. Можно просто написать:

print(dt.datetime.utcnow())  # будет напечатан текущий момент времени
1

Для получения времени другого часового пояса, есть тип timedelta (от англ. delta, «промежуток»), в котором можно сохранить определенный промежуток времени. Этот тип тоже живёт в библиотеке dt. А объект такого типа создаётся функцией timedelta():

import datetime as dt

period = dt.timedelta(hours=3) # сохраняем промежуток времени в три часа
print(period)           # 3:00:00
1
2
3
4

И прибавляем его к значению времени по UTC:

now = dt.datetime.utcnow()
period = dt.timedelta(hours=3)
moscow_moment = now + period
print(moscow_moment) # будет напечатано текущее время в Москве
1
2
3
4

В аргументах функции timedelta() среди прочего можно указывать days (дни), hours (часы), minutes (минуты), seconds (секунды), microseconds (микросекунды).

Пример: Победитель Гран-при Австралии чемпионата мира Формулы-1 2019 года, Вале Боттас проехал свой самый быстрый круг за 1 минуту 25 секунд и 273250 микросекунд. Второй результат показал Льюис Хэмилтон с разницей в 208860 микросекунд. Вычислим время самого быстрого круга Хэмилтона.

import datetime as dt

time_bottas = dt.timedelta(minutes=1, seconds=25, microseconds=273250)
time_hamilton = time_bottas + dt.timedelta(microseconds=208860)
print(time_hamilton)            # 0:01:25.482110
1
2
3
4
5

Упражнения

  1. Напишите функцию, которая по названию города скажет, сколько там сейчас времени. В словарь UTC_OFFSET (англ. offset, «сдвиг»), для каждого города записана разница местного времени и UTC в часах.
import datetime as dt

UTC_OFFSET = {
    'Санкт-Петербург': 3,
    'Москва': 3,
    'Самара': 4,
    'Новосибирск': 7,
    'Екатеринбург': 5,
    'Нижний Новгород': 3,
    'Казань': 3,
    'Челябинск': 5,
    'Омск': 6,
    'Ростов-на-Дону': 3,
    'Уфа': 5,
    'Красноярск': 7,
    'Пермь': 5,
    'Воронеж': 3,
    'Волгоград': 3,
    'Краснодар': 3,
    'Калининград': 2
}

def what_time(city):
    # напишите код функции который вернет время в городе

print(what_time('Екатеринбург'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  1. Подключите метод перебора и выведите фразу для каждого города: "В Уфе 5 часов." Используйте проверку для правильно подобранного окончания слова "часы" в зависимости от числа.

  2. Напишите функцию, которая по имени друга скажет, сколько у него сейчас времени. В словаре DATABASE хранятся данные о том, кто из друзей где живёт.

import datetime as dt

DATABASE = {
    'Серёга': 'Омск',
    'Соня': 'Москва',
    'Дима': 'Челябинск',
    'Алина': 'Красноярск',
    'Егор': 'Пермь'
}

UTC_OFFSET = {
    'Санкт-Петербург': 3,
    'Москва': 3,
    'Самара': 4,
    'Новосибирск': 7,
    'Екатеринбург': 5,
    'Нижний Новгород': 3,
    'Казань': 3,
    'Челябинск': 5,
    'Омск': 6,
    'Ростов-на-Дону': 3,
    'Уфа': 5,
    'Красноярск': 7,
    'Пермь': 5,
    'Воронеж': 3,
    'Волгоград': 3,
    'Краснодар': 3,
    'Калининград': 2
}

def what_time(friend):
    # напишите код функции, который вернет время у друга из аргумента friend

print(what_time('Алина'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  1. Подключите метод перебора друзей и выведите фразу для каждого друга: "У Димы сейчас 15 часов." Используйте проверку для правильно подобранного окончания слова "часы" в зависимости от числа.

Форматирование времени

До сих пор вы печатали время только в одном формате.

import datetime as dt

arrival_time = dt.datetime(2019, 5, 10, 19, 45)
print('Самолёт прибывает в', arrival_time)      # Самолёт прибывает в 2019-05-10 19:45:00
1
2
3
4

Что делать, если хочется напечатать сообщение по-человечески, скажем: "Сейчас 10:31"? Для этого существует метод strftime() (от англ. string format time, «строковый формат времени»). Его можно применить к любому объекту типа datetime и аргументом задать формат вывода времени:

print('Самолёт прибывает в', arrival_time.strftime('%H:%M'))    # Самолёт прибывает в 19:45
1

Здесь %H означает часы, %M — минуты. Кроме этих параметров, бывают ещё, например %B — месяц, %Y — год и %S — секунды, %A — название дня недели по-английски, %U — номер недели в году.

import datetime as dt

# дата первого осеннего снега в Новосибирске в 2018
first_snow = dt.datetime(2018, 9, 9)
# дата последнего весеннего снега в Новосибирске в 2018
last_snow = dt.datetime(2018, 5, 19)

print(last_snow.strftime('Последний снег выпал в %U-ю неделю года.'))
print(first_snow.strftime('А первый снег пошёл в %U-ю неделю.'))
1
2
3
4
5
6
7
8
9

Результат вывода:

Последний снег выпал в 19-ю неделю года.
А первый снег пошёл в 36-ю неделю.
1
2

Упражнения

  1. Сделайте так, чтобы функция what_time() возвращала время в формате часы:минуты.
  2. Примените все полученные в этой теме знания, чтобы научить Виту отвечать на вопросы про друзей, сколько у них сейчас времени:
  • Артём, который час?
  • Антон, который час?

Примеры таких запросов уже добавлены в список queries в функции runner().

  • Измените функцию process_friend(), чтобы она обрабатывала ещё один запрос, а именно query == 'который час?'
  • Если город друга есть в базе UTC_OFFSET, вызовите функцию what_time() и, подставив полученный результат, верните ответ в формате Там сейчас 19:28.
  • Если город отсутствует в базе UTC_OFFSET, то верните сообщение об ошибке <не могу определить время в городе {название}>
# подключите библиотеку datetime под именем dt

DATABASE = {
    'Сергей': 'Омск',
    'Соня': 'Москва',
    'Алексей': 'Калининград',
    'Миша': 'Москва',
    'Дима': 'Челябинск',
    'Алина': 'Красноярск',
    'Егор': 'Пермь',
    'Коля': 'Красноярск',
    'Артём': 'Владивосток',
    'Петя': 'Михайловка'
}

UTC_OFFSET = {
    'Москва': 3,
    'Санкт-Петербург': 3,
    'Новосибирск': 7,
    'Екатеринбург': 5,
    'Нижний Новгород': 3,
    'Казань': 3,
    'Челябинск': 5,
    'Омск': 6,
    'Самара': 4,
    'Ростов-на-Дону': 3,
    'Уфа': 5,
    'Красноярск': 7,
    'Воронеж': 3,
    'Пермь': 5,
    'Волгоград': 3,
    'Краснодар': 3,
    'Калининград': 2,
    'Владивосток': 10
}


def format_count_friends(count_friends):
    if count_friends == 1:
        return '1 друг'
    elif 2 <= count_friends <= 4:
        return f'{count_friends} друга'
    else:
        return f'{count_friends} друзей'


def what_time(city):
    offset = UTC_OFFSET[city]
    city_time = dt.datetime.utcnow() + dt.timedelta(hours=offset)
    f_time = city_time.strftime("%H:%M")
    return f_time


def process_vita(query):
    if query == 'сколько у меня друзей?':
        count_string = format_count_friends(len(DATABASE))
        return f'У тебя {count_string}'
    elif query == 'кто все мои друзья?':
        friends_string = ', '.join(DATABASE.keys())
        return f'Твои друзья: {friends_string}'
    elif query == 'где все мои друзья?':
        unique_cities = set(DATABASE.values())
        cities_string = ', '.join(unique_cities)
        return f'Твои друзья в городах: {cities_string}'
    else:
        return '<неизвестный запрос>'


def process_friend(name, query):
    if name in DATABASE:
        city = DATABASE[name]
        if query == 'ты где?':
            return f'{name} в городе {city}'
        # допишите код функции
        else:
            return '<неизвестный запрос>'
    else:
        return f'У тебя нет друга по имени {name}'


def process_query(query):
    tokens = query.split(', ')
    name = tokens[0]
    if name == 'Вита':
        return process_vita(tokens[1])
    else:
        return process_friend(name, tokens[1])


def runner():
    queries = [
        'Вита, сколько у меня друзей?',
        'Вита, кто все мои друзья?',
        'Вита, где все мои друзья?',
        'Вита, кто виноват?',
        'Коля, ты где?',
        'Соня, что делать?',
        'Антон, ты где?',
        'Алексей, который час?',
        'Артём, который час?',
        'Антон, который час?',
        'Петя, который час?'
    ]
    for query in queries:
        print(query, '-', process_query(query))


runner()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108