В этом листке вам нужно будет решать задачи, связанные с датами и временем, поэтому прежде всего нужно понять, как хранить даты и время в программе. Конечно, лучше всего для типа данных “Дата” создать класс.
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"
с лидирующим нулём.
Ввод | Вывод |
---|---|
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 |