Даты и временные интервалы
Введено в версии 1.7.0.
Начиная с NumPy 1.7, существуют основные типы данных массивов, которые изначально поддерживают функциональность дат и времени. Тип данных называется «datetime64», так как «datetime» уже используется библиотекой datetime, включённой в Python.
Основные даты и время
Самый простой способ создания дат и времени — из строк в формате даты или даты и времени ISO 8601. Также можно создать даты и время из целого числа, смещённого относительно эпохи Unix (00:00:00 UTC 1 января 1970 года). Единица для внутреннего хранения автоматически выбирается из формата строки и может быть либо единицей измерения даты, либо единицей измерения времени. Единицы измерения дат — годы (‘Y’), месяцы (‘M’), недели (‘W’) и дни (‘D’), а единицы измерения времени — часы (‘h’), минуты (‘m’), секунды (‘s’), миллисекунды (‘ms’) и некоторые дополнительные единицы измерения секунд с использованием префиксов СИ. Тип данных datetime64 также принимает строку «NAT» (в любом сочетании строчных/заглавных букв) для значения «Не время».
Пример
Простая дата ISO:
>>> np.datetime64('2005-02-25')
numpy.datetime64('2005-02-25')
Из целого числа и единицы измерения даты, 1 год от эпохи Unix:
>>> np.datetime64(1, 'Y')
numpy.datetime64('1971')
Используя месяцы в качестве единицы:
>>> 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'
Единицы измерения дат
Типы данных Дата и Время поддерживают большое количество единиц измерения времени, а также общие единицы, которые могут быть преобразованы в любые другие единицы в зависимости от входных данных.
Даты всегда хранятся на основе времени 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» могут дополнительно проверять список дат «праздников», конкретных дат, которые не являются рабочими днями.
Функция 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
Вот несколько примеров значений custom 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–2022 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.21/reference/arrays.datetime.html