Даты и временные интервалы
Новое в версии 1.7.0.
Начиная с NumPy 1.7, существуют базовые типы данных массивов, которые изначально поддерживают функциональность работы с датами и временем. Тип данных называется “datetime64”, так как “datetime” уже используется в библиотеке datetime, входящей в Python.
Примечание
API datetime в версии 1.7.0 является экспериментальным и может быть изменён в будущих версиях NumPy.
Основные даты и время
Самый простой способ создания дат и времени — из строк в формате ISO 8601 для дат или дат и времени. Единица для внутреннего хранения автоматически выбирается из формата строки и может быть либо единицей измерения даты, либо единицей измерения времени. Единицы измерения дат — годы (‘Y’), месяцы (‘M’), недели (‘W’) и дни (‘D’), а единицы измерения времени — часы (‘h’), минуты (‘m’), секунды (‘s’), миллисекунды (‘ms’) и некоторые дополнительные единицы измерения секунд с использованием префиксов СИ. Тип данных datetime64 также принимает строку “NAT”, в любой комбинации строчных/заглавных букв, для значения «Не время».
Пример
Простая дата в формате ISO:
>>> np.datetime64('2005-02-25')
numpy.datetime64('2005-02-25')
Использование месяцев в качестве единицы измерения:
>>> np.datetime64('2005-02')
numpy.datetime64('2005-02')
Указание только месяца, но принудительное использование единицы измерения ‘дни’:
>>> np.datetime64('2005-02', 'D')
numpy.datetime64('2005-02-01')
Из даты и времени:
>>> np.datetime64('2005-02-25T03:30')
numpy.datetime64('2005-02-25T03:30')
NAT (нет времени):
>>> np.datetime64('nat')
numpy.datetime64('NaT')
При создании массива дат и времени из строки всё ещё можно автоматически выбрать единицу измерения из входных данных, используя тип datetime с общими единицами измерения.
Пример
>>> np.array(['2007-07-13', '2006-01-13', '2010-08-13'], dtype='datetime64') array(['2007-07-13', '2006-01-13', '2010-08-13'], dtype='datetime64[D]')
>>> np.array(['2001-01-01T12:00', '2002-02-03T13:56:03.172'], dtype='datetime64')
array(['2001-01-01T12:00:00.000', '2002-02-03T13:56:03.172'],
dtype='datetime64[ms]')
Тип datetime работает со многими стандартными функциями NumPy, например, arange может использоваться для генерации диапазонов дат.
Пример
Все даты одного месяца:
>>> np.arange('2005-02', '2005-03', dtype='datetime64[D]')
array(['2005-02-01', '2005-02-02', '2005-02-03', '2005-02-04',
'2005-02-05', '2005-02-06', '2005-02-07', '2005-02-08',
'2005-02-09', '2005-02-10', '2005-02-11', '2005-02-12',
'2005-02-13', '2005-02-14', '2005-02-15', '2005-02-16',
'2005-02-17', '2005-02-18', '2005-02-19', '2005-02-20',
'2005-02-21', '2005-02-22', '2005-02-23', '2005-02-24',
'2005-02-25', '2005-02-26', '2005-02-27', '2005-02-28'],
dtype='datetime64[D]')
Объект datetime представляет собой отдельный момент во времени. Если две даты и время имеют разные единицы измерения, они всё равно могут представлять один и тот же момент во времени, и преобразование из большей единицы, такой как месяцы, в меньшую, такую как дни, считается «безопасным» преобразованием, поскольку момент во времени всё ещё представляется точно.
Пример
>>> np.datetime64('2005') == np.datetime64('2005-01-01')
True
>>> np.datetime64('2010-03-14T15') == np.datetime64('2010-03-14T15:00:00.00')
True
Устарело начиная с версии 1.11.0: NumPy не хранит информацию о часовом поясе. Для обеспечения обратной совместимости datetime64 всё ещё анализирует смещения часовых поясов, которые обрабатываются путём преобразования в UTC. Это поведение устарело и в будущем будет вызывать ошибку.
Арифметика дат и временных интервалов
NumPy позволяет вычитать две даты и время, операция, которая даёт число с единицей измерения времени. Поскольку NumPy не имеет системы физических величин в своём ядре, был создан тип данных timedelta64, дополняющий datetime64. Аргументы timedelta64 — это число, представляющее количество единиц, и единица измерения даты/времени, такие как (D)ень, (M)есяц, (Y)год, (h)часы, (m)инуты или (s)екунды. Тип данных timedelta64 также принимает строку “NAT” вместо числа для значения «Не время».
Пример
>>> np.timedelta64(1, 'D') numpy.timedelta64(1,'D')
>>> np.timedelta64(4, 'h') numpy.timedelta64(4,'h')
>>> np.timedelta64('nAt')
numpy.timedelta64('NaT')
Даты и временные интервалы работают вместе, чтобы предоставить способы для простых расчётов с датами и временем.
Пример
>>> np.datetime64('2009-01-01') - np.datetime64('2008-01-01')
numpy.timedelta64(366,'D')
>>> np.datetime64('2009') + np.timedelta64(20, 'D')
numpy.datetime64('2009-01-21')
>>> np.datetime64('2011-06-15T00:00') + np.timedelta64(12, 'h')
numpy.datetime64('2011-06-15T12:00')
>>> np.timedelta64(1,'W') / np.timedelta64(1,'D') 7.0
>>> np.timedelta64(1,'W') % np.timedelta64(10,'D') numpy.timedelta64(7,'D')
>>> np.datetime64('nat') - np.datetime64('2009-01-01')
numpy.timedelta64('NaT','D')
>>> np.datetime64('2009-01-01') + np.timedelta64('nat')
numpy.datetime64('NaT')
Существует две единицы измерения Timedelta (‘Y’, годы и ‘M’, месяцы), которые обрабатываются особым образом, поскольку количество представленного времени зависит от того, где они используются. В то время как единица измерения timedelta для дней эквивалентна 24 часам, нет способа преобразовать единицу измерения месяца в дни, потому что разные месяцы имеют разное количество дней.
Пример
>>> a = np.timedelta64(1, 'Y')
>>> np.timedelta64(a, 'M') numpy.timedelta64(12,'M')
>>> np.timedelta64(a, 'D') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Cannot cast NumPy timedelta64 scalar from metadata [Y] to [D] according to the rule 'same_kind'
Единицы измерения дат
Типы данных Datetime и Timedelta поддерживают большое количество единиц измерения времени, а также общие единицы, которые можно преобразовать в любые другие единицы в зависимости от входных данных.
Даты и время всегда хранятся на основе временной шкалы POSIX (хотя предлагается режим TAI, который позволяет учитывать добавочные секунды), с начальной точкой 1970-01-01T00:00Z. Это означает, что поддерживаемые даты всегда представляют собой симметричный интервал относительно начальной точки, называемый «временным интервалом» в таблице ниже.
Длина интервала — это диапазон 64-битного целого числа, умноженный на длину даты или единицы. Например, временной интервал для ‘W’ (неделя) ровно в 7 раз длиннее временного интервала для ‘D’ (день), а временной интервал для ‘D’ (день) ровно в 24 раза длиннее временного интервала для ‘h’ (час).
Вот единицы измерения дат:
Код | Значение | Временной интервал (относительно) | Временной интервал (абсолютно) |
|---|---|---|---|
Y | год | +/- 9.2e18 лет | [9.2e18 до н. э., 9.2e18 н. э.] |
M | месяц | +/- 7.6e17 лет | [7.6e17 до н. э., 7.6e17 н. э.] |
W | неделя | +/- 1.7e17 лет | [1.7e17 до н. э., 1.7e17 н. э.] |
D | день | +/- 2.5e16 лет | [2.5e16 до н. э., 2.5e16 н. э.] |
И вот единицы измерения времени:
Код | Значение | Временной интервал (относительно) | Временной интервал (абсолютно) |
|---|---|---|---|
h | час | +/- 1.0e15 лет | [1.0e15 до н. э., 1.0e15 н. э.] |
m | минута | +/- 1.7e13 лет | [1.7e13 до н. э., 1.7e13 н. э.] |
s | секунда | +/- 2.9e11 лет | [2.9e11 до н. э., 2.9e11 н. э.] |
ms | миллисекунда | +/- 2.9e8 лет | [ 2.9e8 до н. э., 2.9e8 н. э.] |
us / μs | микросекунда | +/- 2.9e5 лет | [290301 до н. э., 294241 н. э.] |
ns | наносекунда | +/- 292 года | [ 1678 н. э., 2262 н. э.] |
ps | пикосекунда | +/- 106 дней | [ 1969 н. э., 1970 н. э.] |
fs | фемтосекунда | +/- 2.6 часа | [ 1969 н. э., 1970 н. э.] |
as | аттосекунда | +/- 9.2 секунд | [ 1969 н. э., 1970 н. э.] |
Функциональность рабочих дней
Для возможности использования даты и времени в контекстах, где допустимы только определённые дни недели, NumPy включает набор функций «busday» (рабочие дни).
По умолчанию для функций busday допустимыми днями являются понедельник по пятницу (обычные рабочие дни). Реализация основана на «weekmask», содержащем 7 логических флагов для указания допустимых дней; возможны пользовательские weekmask, которые указывают другие наборы допустимых дней.
Функции «busday» также могут проверять список «holiday» (праздничных) дат, конкретных дат, которые не являются рабочими днями.
Функция busday_offset позволяет применять смещения, заданные в рабочих днях, к датам и времени с единицей измерения ‘D’ (день).
Пример
>>> np.busday_offset('2011-06-23', 1)
numpy.datetime64('2011-06-24')
>>> np.busday_offset('2011-06-23', 2)
numpy.datetime64('2011-06-27')
Когда входная дата приходится на выходные или праздничный день, busday_offset сначала применяет правило для перевода даты на допустимый рабочий день, а затем применяет смещение. Правило по умолчанию — «raise», которое просто вызывает исключение. Наиболее часто используемые правила — «forward» и «backward».
Пример
>>> np.busday_offset('2011-06-25', 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Non-business day date in busday_offset
>>> np.busday_offset('2011-06-25', 0, roll='forward')
numpy.datetime64('2011-06-27')
>>> np.busday_offset('2011-06-25', 2, roll='forward')
numpy.datetime64('2011-06-29')
>>> np.busday_offset('2011-06-25', 0, roll='backward')
numpy.datetime64('2011-06-24')
>>> np.busday_offset('2011-06-25', 2, roll='backward')
numpy.datetime64('2011-06-28')
В некоторых случаях необходимо соответствующее использование правила смещения, чтобы получить желаемый результат.
Пример
Первый рабочий день на или после даты:
>>> np.busday_offset('2011-03-20', 0, roll='forward')
numpy.datetime64('2011-03-21')
>>> np.busday_offset('2011-03-22', 0, roll='forward')
numpy.datetime64('2011-03-22')
Первый рабочий день строго после даты:
>>> np.busday_offset('2011-03-20', 1, roll='backward')
numpy.datetime64('2011-03-21')
>>> np.busday_offset('2011-03-22', 1, roll='backward')
numpy.datetime64('2011-03-23')
Функция также полезна для вычисления некоторых видов дней, например, праздников. В Канаде и США День матери отмечается во второе воскресенье мая, что можно вычислить с помощью пользовательского weekmask.
Пример
>>> np.busday_offset('2012-05', 1, roll='forward', weekmask='Sun')
numpy.datetime64('2012-05-13')
Когда важна производительность при манипулировании множеством дат рабочих дней с одним конкретным выбором weekmask и праздничных дней, есть объект busdaycalendar, который хранит необходимые данные в оптимизированной форме.
np.is_busday():
Для проверки значения datetime64, является ли оно допустимым днём, используйте is_busday.
Пример
>>> np.is_busday(np.datetime64('2011-07-15')) # a Friday
True
>>> np.is_busday(np.datetime64('2011-07-16')) # a Saturday
False
>>> np.is_busday(np.datetime64('2011-07-16'), weekmask="Sat Sun")
True
>>> a = np.arange(np.datetime64('2011-07-11'), np.datetime64('2011-07-18'))
>>> np.is_busday(a)
array([ True, True, True, True, True, False, False])
np.busday_count():
Для нахождения количества допустимых дней в заданном диапазоне дат datetime64, используйте busday_count:
Пример
>>> np.busday_count(np.datetime64('2011-07-11'), np.datetime64('2011-07-18'))
5
>>> np.busday_count(np.datetime64('2011-07-18'), np.datetime64('2011-07-11'))
-5
Если у вас есть массив значений дня datetime64, и вы хотите подсчитать, сколько из них являются допустимыми датами, вы можете сделать это:
Пример
>>> a = np.arange(np.datetime64('2011-07-11'), np.datetime64('2011-07-18'))
>>> np.count_nonzero(np.is_busday(a))
5
Пользовательские weekmask
Вот несколько примеров пользовательских значений weekmask. Эти примеры указывают «busday» по умолчанию, где понедельник по пятницу — допустимые дни.
Некоторые примеры:
# Positional sequences; positions are Monday through Sunday. # Length of the sequence must be exactly 7. weekmask = [1, 1, 1, 1, 1, 0, 0] # list or other sequence; 0 == invalid day, 1 == valid day weekmask = "1111100" # string '0' == invalid day, '1' == valid day # string abbreviations from this list: Mon Tue Wed Thu Fri Sat Sun weekmask = "Mon Tue Wed Thu Fri" # any amount of whitespace is allowed; abbreviations are case-sensitive. weekmask = "MonTue Wed Thu\tFri"
© 2005–2021 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.20/reference/arrays.datetime.html