Дата и время
Contents
(datetime=)
Дата и время#
Для представления времени в компьютере обычно используется так называемое Unix-время (иногда Epoch time
, Posix time
, seconds since the Epoch
, или UNIX Epoch time
), которое
Определяется как количество секунд, прошедших с полуночи (00:00:00 UTC) 1 января 1970 года (четверг); этот момент называют «эпохой Unix» (англ. Unix Epoch). Unix-время представлено целым числом, которое увеличивается с каждой прошедшей секундой без необходимости вычислений для определения года, месяца, дня, часа или минуты для удобства восприятия человеком.
Модуль стандартной библиотеки time#
Функция time.time модуля time возвращает именно Unix-время, только не в виде целого числа, а в виде float
, т.е. доли секунды тоже учитываются. Если доли секунды играют роль, то лучше прибегать к time.time_ns, которое возвращает количество наносекунд с Unix epoch
.
Tip
Для измерения промежутков времени (например, замер времени исполнения блока кода) лучше использовать функцию time.perf_counter или time.perf_counter_ns, т.к. она точнее измеряет время. Но важно знать, что возвращаемое время отсчитывается от произвольной точки отсчета, т.е. только разница между двумя значениями имеет смысл.
Функция time.ctime преобразует Unix-время в строку в формате 'Sun Jun 20 23:21:05 1993'
, т.е. какая дата и какое время было при пройденном количестве секунд с Unix-epoch
. Чтобы получить строку в другом формате, можно воспользоваться функцией time.strftime, которая в качестве первого аргумента принимает форматирующую строку. Как составить форматирующую строку можно прочитать здесь и здесь. Ниже приводится не полная таблица с допустимыми директивами в форматирующей строке.
Директива |
Значение |
Пример |
---|---|---|
|
Аббревиатура дня недели |
Sun, Mon, …, Sat (en_US) |
|
Полное имя дня недели |
Sunday, Monday, …, Saturday (en_US) |
|
Номер дня в неделе, где 0 - воскресенье, 6 — суббота. |
0, 1, …, 6 |
|
Номер дня в месяце (двузначное десятичное число) |
01, 02, …, 31 |
|
Аббревиатура месяца |
Jan, Feb, …, Dec (en_US); |
|
Полное название месяца. |
January, February, …, December (en_US); |
|
Номер месяца (двузначное десятичное число) |
01, 02, …, 12 |
|
Год без учета века |
00, 01, …, 99 |
|
Год с учетом века |
0001, 0002, …, 2013, 2014, …, 9998, 9999 |
|
Номер часа в 24-часовом формате |
00, 01, …, 23 |
|
Номер часа в 12-часовом формате |
01, 02, …, 12 |
|
До полудня или после |
AM, PM (en_US); |
|
Номер минуты в часе |
00, 01, …, 59 |
|
Номер секунды в минуте |
00, 01, …, 59 |
|
Номер микросекунды в секунде. |
000000, 000001, …, 999999 |
Директивы %a
, %A
, %b
, %B
, %p
вставляют строковые представления в соответствии с переменными среды. Хотя в стандартной библиотеке есть модуль locale, который позволяет локализовать вывод таких значений методом locale.setlocale (locale.setlocale(locale.LC_ALL, "ru_RU")
для русского), рекомендуется использовать для таких целей библиотеку babel (подробнее здесь).
import time
t0 = time.time()
time.sleep(1.0) # in seconds
print(t0)
print(time.ctime(t0))
print(time.ctime())
print(time.localtime(t0))
print(time.localtime())
print(time.strftime(r"%d.%m.%Y %H:%M:%S", time.localtime(t0)))
print(time.strftime(r"%d.%m.%Y %H:%M:%S"))
1638382039.2391078
Wed Dec 1 21:07:19 2021
Wed Dec 1 21:07:20 2021
time.struct_time(tm_year=2021, tm_mon=12, tm_mday=1, tm_hour=21, tm_min=7, tm_sec=19, tm_wday=2, tm_yday=335, tm_isdst=0)
time.struct_time(tm_year=2021, tm_mon=12, tm_mday=1, tm_hour=21, tm_min=7, tm_sec=20, tm_wday=2, tm_yday=335, tm_isdst=0)
01.12.2021 21:07:19
01.12.2021 21:07:20
Модуль стандартной библиотеки datetime#
datetime — модуль стандартной библиотеки для работы с датами и временем, который предназначен для работы с временем в разном формате (парсинг и форматирование), а так же предусматривает арифметические операции над моментами во времени.
Основные типы объектов в модуле datetime
:
datetime.date
— дата с аттрибутамиyear
,month
иday
;datetime.time
— время с аттрибутамиhour
,minute
,second
,microsecond
;datetime.datetime
— комбинация datetime.date и datetime.time (и те и те аттрибуты);datetime.timedelta
— промежуток времени между двумяdatetime.datetime
(или простоtime
иdate
);datetime.tzinfo
иdatetime.timezone
— информация о часовом поясе.
Note
Объекты datetime
и time
опционально могут содержать информацию о часовом поясе. Тогда их называют aware
. Объекты без информации о часовом поясе называют naive
. Здесь будут рассматриваться только naive
объекты.
Кроме того, что объекты классов date
, time
, datetime
можно сразу печатать функцией print
(по умолчанию YYYY-MM-DD
), они ещё имеют метод strftime
, который работает аналогично функции из модуля time
.
Note
Минимальный возможный год для объектов этого модуля — 1 год нашей эры, а максимальный — 9999 год нашей эры (все согласно григорианскому календарю). Для работы с датами до нашей эры или, например, для дат в астрономическом масштабе, этот модуль не подходит.
import datetime
datetime.date#
datetime.date
— объект с атрибутами
year
\(\in \{1, 2, ..., 9999\}\) — год (2021, например);month
\(\in \{1, 2, ..., 12\}\) — месяц;day
\(\in \{1, 2, ..., N\}\) — номер дня в месяце (\(N\) — количество дней в месяце);
Создать объект datetime.date
можно несколькими способами.
Например, явно вызвав конструктор.
the_date = datetime.date(year=1963, month=4, day=12)
the_date_formatted = the_date.strftime("%m/%d/%Y")
print(f"Первый полёт в космос: {the_date_formatted}")
Первый полёт в космос: 04/12/1963
Из Unix-времени
методом datetime.date.fromtimestamp.
unix_epoch = datetime.date.fromtimestamp(0)
print(f"Unix-epoch соответствует дате {unix_epoch}.")
Unix-epoch соответствует дате 1970-01-01.
Или методом datetime.date.today, если нужна дата на сегодня (согласно часам компьютера).
Note
Этот метод аналогичен datetime.date.fromtimestamp(time.time())
.
today = datetime.date.today()
print(today)
print(f"День: {today.day}, месяц: {today.month}, год {today.year}")
print(f"{today.weekday() + 1} день недели: {today.strftime('%A')}")
2021-12-01
День: 1, месяц: 12, год 2021
3 день недели: Wednesday
datetime.time#
datetime.time — объект для хранения времени внутри суток, т.е. он имеет поля
hour
\(\in \{0, 1, ..., 23\}\) — час,minute
\(\in \{0, 1, ..., 59\}\) — минута,second
\(\in \{0, 1, ..., 59\}\) — секунда,microsecond
\(\in \{0, 1, ..., 999999\}\) — микросекунда,fold
\(\in [0, 1]\) — параметр, который используется для разрешения противоречий, если есть данные о часовом поясе (переводы часов назад и так далее).
the_time = datetime.time(hour=9, minute=7)
the_time_formatted = the_time.strftime("%H:%M")
print(f"Старт корабля Восток 1 состоялся в {the_time_formatted} по Московскому времени.")
Старт корабля Восток 1 состоялся в 09:07 по Московскому времени.
Редко возникают ситуации, когда нужно только время внутри суток без даты, поэтому datetime.time
используется значительное реже, чем datetime.datetime
.
datetime.datetime#
datetime.datetime — по сути дела комбинация предыдущих двух типов datetime.date
и datetime.time
, т.е. имеет аттрибуты и того и того:
year
;month
;day
;hour
;minute
;second
;microsecond
;fold
;
Конструктор datetime.datetime
в качестве входных параметров принимает параметры обоих классов datetime.date
и datetime.time
. Также, можно предварительно создать объекты datetime.date
и datetime.time
и объединить их в datetime.datetime
методом combine.
olympics = datetime.datetime(year=1980, month=7, day=19, hour=16)
print(olympics.strftime("Церемония открытия московской олимпиады началась %d.%m.%Y в %H:%M."))
the_date_the_time = datetime.datetime.combine(the_date, the_time)
print(the_date_the_time.strftime("Старт корабля Восток 1 состоялся %d/%m/%y в %H:%M по Московскому времени."))
Церемония открытия московской олимпиады началась 19.07.1980 в 16:00.
Старт корабля Восток 1 состоялся 12/04/63 в 09:07 по Московскому времени.
Также есть и метод fromtimestamp, который в данном случае учитывает часовой пояс системы, т.е. по количеству секунд, прошедших с полуночи по Гринвичу 1 января 1970 года, он возвращает дату и время, которые были в это время в этом часовом поясе. Метод utcfromtimestamp делает то же самое, но не учитывая часовой пояс.
unix_epoch_moscow = datetime.datetime.fromtimestamp(0)
print(unix_epoch_moscow.strftime("Мировое Unix-время отсчитывается с %H:%M по московскому времени"))
unix_epoch_UTC = datetime.datetime.utcfromtimestamp(0)
print(unix_epoch_UTC.strftime("Мировое Unix-время отсчитывается с %H:%M UTC"))
Мировое Unix-время отсчитывается с 03:00 по московскому времени
Мировое Unix-время отсчитывается с 00:00 UTC
Но чаще всего datetime.datetime
образуются методом datetime.datetime.strptime из текстового представления. Формат текстового представления для времени отличается для разных стран/учреждений/организаций и т.д. Например, где-то 26 января записывается в виде “26.01”, а где-то в “01/26”. Чтобы модуль datetime
смог разобраться, где в строке расположены значения, соответствующие номеру месяца, а где номеру дня, году, времени и т.п., необходимо передать в метод strptime
форматирующую строку в качестве второго аргумента.
t1 = "14 March 1879"
t2 = "2019-05-18T15:17:08.132263"
t3 = "11/12/63"
print(datetime.datetime.strptime(t1, "%d %B %Y"))
print(datetime.datetime.strptime(t2, "%Y-%m-%dT%H:%M:%S.%f"))
print(datetime.datetime.strptime(t3, "%m/%d/%y"))
1879-03-14 00:00:00
2019-05-18 15:17:08.132263
2063-11-12 00:00:00
Разберем примеры выше:
В строковом представлении
t1
идут сначала две цифры, обозначающие день, т.е. используем директива%d
. Затем идёт полное название месяца (директива%B
, а затем идёт год с указанием всех 4 цифр (директива%Y
)). Т.к. все эти элементы разделены пробелом, то форматирующая строка равна"%d %B %Y"
;t1
соответствует iso-формату. Полный год (%Y
), месяц (%m
), день%d
, символ"T"
, час (%H
), минута (%M
), секунда (%S
), микро секунда (%f
). Месяц отделяется от дня и год символом дефиса"-"
, минута отделяется от часа и секунды символом двоеточия ("-"
), и микросекунда отделяется точкой перед ней. Комбинируя это всё, получаем форматирующую строку"%Y-%m-%dT%H:%M:%S.%f"
Дата разделенная символами
/
, в годе не указан век. Подразумевается, что дата представлена в формате, используемом вUSA
, т.е. сначала идёт месяц, а затем день (день убийства Кеннеди). Хочется использоваться форматирующую строку"11/12/63"
, но она возвращает 2063 год. Т.к. такая строка не содержит достаточно информации, чтобы определить правильный век, то её необходимо обрабатывать отдельно.
timedelta#
Объекты datetime.timedelta позволяют производить арифметику с объектами datetime.datetime
, datetime.date
и datetime.time
. Пусть t
— объект datetime
или его аналог, а dt
— объект deltatime
, тогда определенны следующие операции:
dt
=t2
-t1
;t2
=t1
\(\pm\)dt
;t1
<t2
;др.
today - datetime.date(2000, 1, 1)
datetime.timedelta(days=8005)
Между сегодня и началом века прошло 8005 дней.
a_day = datetime.timedelta(days=1)
yesterday = today - a_day
tomorrow = today + a_day
print(f"Вчера: {yesterday},\nСегодня: {today},\nЗавтра: {tomorrow}")
print(yesterday < today)
Вчера: 2021-11-30,
Сегодня: 2021-12-01,
Завтра: 2021-12-02
True
dt = datetime.datetime.now() - datetime.datetime.fromtimestamp(t0)
dt
datetime.timedelta(seconds=1, microseconds=509398)
pandas.DateTime#
Для работы со временем pandas
опирается на типы данных np.datetime64 и np.timedelta64 из библиотеки NumPy
. Например, сделать pd.Series
типа datetime64[ns]
можно методом pd.to_datetime.
import pandas as pd
t = ["2022-1-1", "2022-1-2"]
t = pd.to_datetime(t)
t
DatetimeIndex(['2022-01-01', '2022-01-02'], dtype='datetime64[ns]', freq=None)
Если аргумент метода pd_todatetime
— список, то создаётся объект pd.DateTimeIndex, а если pd.Series
, то создаётся другая pd.Series
типа datetime64[ns]
.
По умолчанию pandas
парсит в формате "%Y-%m-%d"
, но если данные представлены в другом формате, то можно его указать параметром format.
t = pd.Series(["12:00 1.1.22", "11:00 2.1.22"])
t = pd.to_datetime(t, format="%H:%M %d.%m.%y")
t
0 2022-01-01 12:00:00
1 2022-01-02 11:00:00
dtype: datetime64[ns]
Иногда необходимо задавать точки времени с определенной периодичностью. Для это удобно использовать функцию pd.date_range.
datetimerange = pd.date_range(start=t.iloc[0], end=t.iloc[1], freq="H")
datetimerange
DatetimeIndex(['2022-01-01 12:00:00', '2022-01-01 13:00:00',
'2022-01-01 14:00:00', '2022-01-01 15:00:00',
'2022-01-01 16:00:00', '2022-01-01 17:00:00',
'2022-01-01 18:00:00', '2022-01-01 19:00:00',
'2022-01-01 20:00:00', '2022-01-01 21:00:00',
'2022-01-01 22:00:00', '2022-01-01 23:00:00',
'2022-01-02 00:00:00', '2022-01-02 01:00:00',
'2022-01-02 02:00:00', '2022-01-02 03:00:00',
'2022-01-02 04:00:00', '2022-01-02 05:00:00',
'2022-01-02 06:00:00', '2022-01-02 07:00:00',
'2022-01-02 08:00:00', '2022-01-02 09:00:00',
'2022-01-02 10:00:00', '2022-01-02 11:00:00'],
dtype='datetime64[ns]', freq='H')