Spec-Zone.ru › NumPy 1.18

Даты и временные интервалы

Новая в версии 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 (не время):

>>> numpy.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-0600', '2002-02-03T13:56:03.172-0600'], 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-14T15Z') == np.datetime64('2010-03-14T15:00:00.00Z')
True

Арифметика дат и временных интервалов

NumPy позволяет вычитать две даты и время, что приводит к числу с единицей времени. Поскольку в NumPy нет физической системы величин, был создан тип данных timedelta64 для дополнения datetime64. Аргументы для timedelta64 — это число, представляющее количество единиц, и единица даты/времени, такая как (D)ень, (M)есяц, (Y)год, (h) часы, (m) минуты или (s) секунды. Тип данных timedelta64 также принимает строку «NAT» вместо числа для значения «Не время».

Пример

>>> numpy.timedelta64(1, 'D')
numpy.timedelta64(1,'D')
>>> numpy.timedelta64(4, 'h')
numpy.timedelta64(4,'h')
>>> numpy.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-0500')
>>> np.timedelta64(1,'W') / np.timedelta64(1,'D')
7.0
>>> np.timedelta64(1,'W') % np.timedelta64(10,'D')
numpy.timedelta64(7,'D')
>>> numpy.datetime64('nat') - numpy.datetime64('2009-01-01')
numpy.timedelta64('NaT','D')
>>> numpy.datetime64('2009-01-01') + numpy.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

микросекунда

+/- 2.9e5 лет

[290301 до н.э., 294241 н.э.]

ns

наносекунда

+/- 292 года

[ 1678 н.э., 2262 н.э.]

ps

пикосекунда

+/- 106 дней

[ 1969 н.э., 1970 н.э.]

fs

фемтосекунда

+/- 2.6 часа

[ 1969 н.э., 1970 н.э.]

as

аттосекунда

+/- 9.2 секунды

[ 1969 н.э., 1970 н.э.]

Функциональность рабочих дней

Для возможности использования datetime в контекстах, где допустимы только определенные дни недели, NumPy включает набор функций «busday» (рабочий день).

По умолчанию для функций busday допустимыми днями являются понедельник по пятницу (обычные рабочие дни). Реализация основана на «weekmask», содержащем 7 булевых флагов для указания допустимых дней; возможны пользовательские weekmask, которые задают другие наборы допустимых дней.

Функции «busday» могут дополнительно проверять список дат «выходных», конкретных дат, которые не являются рабочими днями.

Функция 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','D')
>>> np.busday_offset('2011-03-22', 0, roll='forward')
numpy.datetime64('2011-03-22','D')

Первый рабочий день строго после даты:

>>> np.busday_offset('2011-03-20', 1, roll='backward')
numpy.datetime64('2011-03-21','D')
>>> np.busday_offset('2011-03-22', 1, roll='backward')
numpy.datetime64('2011-03-23','D')

Функция также полезна для вычисления некоторых видов дней, таких как выходные. В Канаде и США День матери приходится на второе воскресенье мая, который можно вычислить с помощью пользовательского weekmask.

Пример

>>> np.busday_offset('2012-05', 1, roll='forward', weekmask='Sun')
numpy.datetime64('2012-05-13','D')

Когда производительность важна для обработки многих рабочих дат с определённым выбором 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], dtype='bool')

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"

Изменения в NumPy 1.11

В предыдущих версиях NumPy тип datetime64 всегда хранил время в UTC. По умолчанию, создание объекта datetime64 из строки или его вывод преобразовывал время из локального или в локальное время:

# old behavior
>>> np.datetime64('2000-01-01T00:00:00')
numpy.datetime64('2000-01-01T00:00:00-0800')  # note the timezone offset -08:00

Большинство пользователей datetime64 согласились, что такое поведение нежелательно и не соответствует тому, как обычно используется datetime64 (например, библиотекой pandas). Для большинства случаев использования предпочтительнее тип datetime, не привязанный к часовому поясу, аналогичный типу datetime.datetime в стандартной библиотеке Python. Соответственно, datetime64 больше не предполагает, что входное значение находится в местном времени, а также не выводит местное время:

>>> np.datetime64('2000-01-01T00:00:00')
numpy.datetime64('2000-01-01T00:00:00')

Для обратной совместимости datetime64 всё ещё анализирует смещения часовых поясов, которые обрабатываются им путём преобразования в UTC. Однако полученная дата и время не привязана к часовому поясу:

>>> np.datetime64('2000-01-01T00:00:00-08')
DeprecationWarning: parsing timezone aware datetimes is deprecated; this will raise an error in the future
numpy.datetime64('2000-01-01T08:00:00')

Вследствие этого изменения мы больше не запрещаем преобразование между датами с единицами дат и датами с единицами времени. С timezone-независимыми датами правило преобразования из дат в время больше не является неоднозначным.

© 2005–2020 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.18/reference/arrays.datetime.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API