В этом листке вам нужно будет решать задачи, связанные с датами и временем, поэтому прежде всего нужно понять, как хранить даты и время в программе. Конечно, лучше всего для типа данных “Дата” создать класс.
class Date:
У объектов этого класса будет три поля:
day, month, year.
Подумайте, какие операции можно выполнять с датами. Например, можно преобразовывать даты в строки для удобного вывода или, наоборот, преобразовывать строки в даты. К датам можно прибавлять (вычитать) целые числа (например, прибавить число 1 — это получить следующую дату). Наконец, можно брать разность двух дат (это количество дней между ними).
Для преобразования номера месяца в строку лучше всего использовать список строк-названий:
MonthNames = ('', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
Для вывода названия дней недели также лучше использовать список:
DayOfTheWeek = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')
Данные списки лучше всего сделать глобальными и объявить в самом начале программы.
А вот для преобразования строки-названия месяца в число лучше использовать словарь:
MonthNums = {'January': 1, 'February': 2, 'March': 3, ...}
Если имя поля начинается с двух символов подчеркивания, например, __day,
__month, __year, то эти поля являются “скрытыми”,
то есть доступ к ним можно получить только из методов класса. Для работы с этими
полями нужно использовать методы класса: конструкторы, метод __str__,
перегруженные операции и т.д. При необходимости явно получить или изменить
значение поля пишутся специальные методы типа get_day или set_day.
Если специальному атрибуту класса с именем __slots__ присвоить значение,
в виде списка из нескольких текстовых строк, то только перечисленные в данном списке имена
могут использоваться в качестве имен полей (атрибутов) классов. Например:
class Date:
__slots__ = ['__day', '__month', '__year']
Это также приведет к уменьшению времени обращения к атрибутам класса за счет другого способа хранения атрибутов в экземпляре класса.
Для определения номера дня в году лучше всего использовать константный
массив количества дней в каждом месяце:
Months = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
| Ввод | Вывод |
|---|---|
1 |
January 1 |
365 |
December 31 |
Решите обратную предыдущей задачу: по записи названия месяца и дня определите номер дня в году.
| Ввод | Вывод |
|---|---|
January 1 |
1 |
December 31 |
365 |
dd.mm.yyyy.
Выведите ее в формате "Month d, y"",
где Month - английское название месяца,
d — номер дня в месяце, без
лидирующих нулей, y — номер года без лидирующих нулей.
Требования к реализации. Решение должно быть оформлено в виде класса Date.
Класс должен содержать конструктор, параметром которого является строка
вида dd.mm.yyyy. Класс должен содержать метод text(),
возвращающий представление даты в требуемом формате.
Сдайте на проверку только класс.
| Код | Вывод |
|---|---|
print(Date("12.10.2008").text())
|
October 12, 2008 |
print(Date("01.01.0001").text())
|
January 1, 1 |
Дата задаётся текстовой строкой в одном из двух
форматов, описанных в предыдущей задаче.
Выведите эту дату в формате dd.mm.yyyy.
Требования к реализации. Конструктор класса принимает на вход строку, которая может быть одного из двух возможных форматов, конструктор сам распознаёт формат строки.
Для вывода даты реализуйте метод __str__.
Для форматирования вывода удобно использовать f-строки.
| Код | Вывод |
|---|---|
print(Date("October 12, 2008"))
|
12.10.2008 |
print(Date("January 1, 1"))
|
01.01.0001 |
print(Date("03.12.2019"))
|
03.12.2019 |
Реализуйте операторы сравнения для дат:
==,
!=,
<,
<=,
>,
>=.
Реализуйте для класса Date метод next(),
который возвращает следующую дату для данной. Метод не должен изменять
экземпляр класса.
| Код | Вывод |
|---|---|
print(Date('07.12.2019').next())
|
08.12.2019 |
print(Date('31.12.2019').next())
|
01.01.2020 |
Реализуйте для класса Date метод prev(),
который возвращает предыдущую дату для данной. Метод не должен изменять
экземпляр класса.
| Код | Вывод |
|---|---|
print(Date('07.12.2019').prev())
|
06.12.2019 |
print(Date('01.01.2020').prev())
|
31.12.2019 |
Определите метод __sub__ для вычисления разности дат.
Метод должен возвращать значение типа int.
Можно считать, что левый операнд не меньше правого.
| Код | Вывод |
|---|---|
print(Date('02.01.0001') - Date('01.01.0001')) |
1 |
print(Date('01.03.2020') - Date('01.03.2019'))
|
366 |
Программа получает на вход дату. Выведите название дня недели, на который приходится эта дата. Считайте, что григорианский календарь действовал всегда, начиная с 1 года н.э. (так называемый «пролептический григорианский календарь»).
Алгоритм решения задачи оформите в виде отдельного метода. На проверку нужно сдать программу целиком.
| Ввод | Вывод |
|---|---|
07.12.2019 |
Saturday |
Пронумеруем все даты подряд, считая, что 01.01.0001 имеет номер 1, 02.01.0001 — номер 2 и т.д. По заданной дате определите ее порядковый номер.
Для этого реализуйте метод __int__,
вызываемый при преобразовании объекта к типу int.
Решение не должно содержать цикла для последовательного увеличения номера даты.
| Код | Вывод |
|---|---|
print(int(Date('01.01.0001'))) |
1 |
print(int(Date('01.01.0002'))) |
366 |
Решите обратную задачу: определите дату по номеру дня.
Решение оформите в виде конструктора, принимающего в качестве параметра значение
типа int. Все предыдущие возможности конструктора должны быть сохранены.
| Код | Вывод |
|---|---|
print(Date(1)) |
01.01.0001 |
print(Date(366)) |
01.01.0002 |
Научитесь быстро вычислять разницу между двумя датами, складывать даты с целыми числами.
Должны выполняться следующие операции:
Date - Date
Date + int
Date - int
Date += int
Date -= int
Все значения типа int могут быть положительными, отрицательными или 0.
При вычитании дат первый операнд может быть меньше второго.
Все операции должны выполняться быстро.
| Код | Вывод |
|---|---|
print(Date('01.01.0001') + 1) |
02.01.0001 |
print(Date('01.01.0001') - Date('01.01.0002')) |
-365 |
Имеется список людей с указанием их фамилии, имени и даты рождения. Напишите эффективную по времени работы и по используемой памяти программу, которая будет определять самого старшего человека из этого списка и выводить его фамилию, имя и дату рождения, а если имеется несколько самых старших людей с одинаковой датой рождения, то определять их количество.
На вход программе в первой строке подается количество людей в списке N. В каждой из последующих N строк находится информация в следующем формате:
<Фамилия> <Имя> <Дата рождения>
где <Фамилия> – строка, состоящая не более, чем из 20 символов без пробелов,
<Имя> – строка, состоящая не более, чем из 20 символов без пробелов,
<Дата рождения> – строка, имеющая вид DD.MM.YYYY.
Программа должна вывести дату рождения самого старшего человека в списке, затем через пробел его фамилию и имя. Если таких людей, несколько, то вместо фамилии и имени выводится их количество.
| Ввод | Вывод |
|---|---|
3 |
29.04.1995 Petr Sergeev |
3 |
01.05.1995 2 |
Имеется список сотрудников организации с указанием их фамилии, имени и даты рождения. Администрация ежедневно поздравляет всех сотрудников, родившихся в этот день. Напишите эффективную по времени работы и по используемой памяти программу, которая будет определять, в какой из дней года родилось больше всего сотрудников и выводить этот день (или несколько дней).
Формат входных данных аналогичен предыдущей задаче.
Программа должна вывести список дат, в которые наибольшее число сотрудников отмечает дни рождения
в формате DD.MM по возрастанию дат, каждая дата в отдельной строке.
| Ввод | Вывод |
|---|---|
5 |
01.01 |
Имеется список сотрудников организации с указанием их фамилии, имени и даты рождения. Напишите эффективную по времени работы и по используемой памяти программу, которая будет определять фамилию и имя самого молодого сотрудника, празднующего свой день рождения в течение ближайших семи дней от текущей даты (включая текущую дату).
На вход программе в первой сроке подается текущая дата,
заданная в формате DD.MM.YYYY.
Во второй строке подается количество людей в списке \(N\). В каждой из последующих \(N\) строк находится информация о каждом сотруднике, как в предыдущей задаче.
Известно, что у всех сотрудников даты рождения различаются. Программа должна вывести фамилию
и имя самого молодого сотрудника, празднующего день рождения в ближайшие 7 дней
или сообщение No birthdays in next week, если никто из сотрудников не празднует
день рождения в ближайшие 7 дней.
| Ввод | Вывод |
|---|---|
25.11.2010 |
Ivan Petrov |
25.11.2010 |
No birthdays in next week |
0.142857 |
В Python есть модуль datetime, содержащий несколько классов,
поддерживающих работу с датами и временем.
Изучите краткое описание модуля или английскую документацию.
В последующих задачах вам необходимо реализовать программу, использующую возможности модуля datetime
для работы с датами.
Дата задана в формате dd.mm.yyyy. Выведите название дня недели, на который приходится эта дата.
| Ввод | Вывод |
|---|---|
12.10.2008 |
Sunday |
13.10.2008 |
Monday |
Дата задана в формате dd.mm.yyyy.
Выведите ее в формате "Month d, y"",
где Month — английское название месяца,
d — номер дня в месяце, без
лидирующих нулей, y — номер года без лидирующих нулей.
Обратите внимание, что метод strftime выводит номер дня по подстановке
"%d" с лидирующим нулём. Вывод без лидирующего нуля является
недокументированной возможностью формата strftime, поищите в интернете.
| Ввод | Вывод |
|---|---|
12.10.2008 |
October 12, 2008 |
01.01.0001 |
January 1, 1 |
Дата задана в формате dd.mm.yyyy. Выведите
дату, следующую за ней в том же формате. Учтите правило формирования
високосных годов. Следует считать, что григорианский календарь
действовал всегда.
В этой задаче номер года не меньше 1000. Это связано с тем,
что метод strftime выводит номер года по подстановке
"%Y" без лидирующих нулей, а в Windows — с лидирующими нулями.
| Ввод | Вывод |
|---|---|
12.10.2008 |
13.10.2008 |
31.12.2008 |
01.01.2009 |
Две даты заданы в формате dd.mm.yyyy,
каждая дата в отдельной строке. Определите количество дней между этими
датами. Вторая дата больше первой.
| Ввод | Вывод |
|---|---|
01.01.0001 |
1 |
29.02.2004 |
366 |
Часы показывают время в формате hh:mm:ss.
Определите количество секунд, которое прошло с начала суток.
Программа не должна содержать циклов для решения этой задачи.
| Ввод | Вывод |
|---|---|
00:01:01 |
61 |
Часы показывают время в формате hh:mm:ss. На этих часах запустили таймер, который прозвенит через n секунд. Определите время, которое будет на часах, когда прозвенит таймер. n может принимать значения от 0 до 109. Решение задачи не дожно содержать циклов. Постарайтесь также не использовать условную инструкцию.
| Ввод | Вывод |
|---|---|
09:00:00 |
09:01:30 |
23:59:59 |
00:00:00 |
Профессор лег спать, когда на часах было время h1:m1:s1, а когда он проснулся было время h2:m2:s2. Определите, сколько времени спал профессор, если известно, что он проспал не более суток. Время выведите в формате hh:mm:ss.
| Ввод | Вывод |
|---|---|
14:00:00 |
07:10:30 |
22:00:00 |
09:00:00 |
В операционной системе UNIX, и во всех системах, имеющих сходную архитектуру
(удовлетворяющих стандарту POSIX), например, Linux, Android, macOS, iOS,
время хранится, как целое число, равное количеству секунд, прошедших с полуночи 1 января 1970 года по UTC,
то есть число 0 соответствует времени 0:00:00 01.01.1970 UTC.
Секунды координации не учитываются.
Увидеть текущее время в формате UNIX (называется также Unix timestamp) и перевести
время из формата UNIX в человекочитаемый формат можно на сайте unixtimestamp.com.
В операционной системе Linux это же можно сделать в командной строке при помощи
команды date +%s.
Для хранения времени используется 32-битное знаковое целое число, что приведёт к концу света в 03:14:07 19 января 2038 UTC. Поэтому в 64-битных системах UNIX time хранится в 64-битной переменной. Соответствующий тип данных в языке C называется time_t, он является 32-битным или 64-битным знаковым целым числом.
Напечатайте на экран текущее значение UNIX timestamp в виде целого числа
(в примере вывод соответствует вызову программы в 0:00:00 1 января 2017 UTC).
Вам помогут методы now() и timespamp().
| Ввод | Вывод |
|---|---|
1483228800 |
Переведите значение из формата UNIX timestamp
в обычную дату и время в формате UTC. Выведите результат в формате dd.mm.yyyy hh:mm:ss.
| Ввод | Вывод |
|---|---|
1483228800 |
01.01.2017 00:00:00 |
Решите обратную задачу. Для считывания времени из строки используйте метод
datetime.strptime, который позволяет из строки, содержащей
время в заданном формате, получить значение класса datetime.
| Ввод | Вывод |
|---|---|
01.01.2017 00:00:00 |
1483228800 |