#matlab #datetime #comparison
Вопрос:
Для двух массивов (разной длины) со значениями datetime я хочу отметить те записи, в которых дата (год, месяц, день) в обоих одинакова, игнорируя значения времени. Проблема в том, что datetime
тип внутренне всегда также содержит время (даже конструктор datetime(Y,M,D)
внутренне установит время 00:00:00). Поэтому прямое сравнение времени () даст результат только в том случае, если время также совпадает. dt1 == dt2
true
Напр.:
arDt1 = datetime(2021,5,1:10,0,0,0); % 1. to 10. May, always at time 00:00:00
arDt2 = datetime(2021,5,1:2:10,12,0,0); % 1.,3.,5.,7.,9. May always at time 12:00:00
Таким образом, желаемым логическим массивом флагов для arDt1 будет
[ 1 0 1 0 1 0 1 0 1 0] % days in arDt1 which are also in arDt2, *never mind the time*
Реальные данные охватывают несколько месяцев и лет, поэтому одного только числа дней месяца недостаточно (даже если бы это было в приведенном выше примере).
Я могу придумать различные обходные пути (преобразования datetime в строку и синтаксический анализ, используя ymd()
и затем сравните год, месяц, день «кусочно», или вынудив всех времен, по крайней мере временно, чтобы быть таким же, например, 00:00:00), но все это становится немного неуклюжей, ЭСП. когда задействованы массивы разной длины, это означает ismember()
, что их следует использовать вместо прямого сравнения массивов один к одному.
Проблема обработки только части datetime
значений даты, независимо от части времени, должна быть довольно общей, но я не могу найти никаких примеров или ссылок. Может ли кто-нибудь посоветовать более элегантный/эффективный способ?
Комментарии:
1. Можете ли вы просто не конвертировать в
datenum
тоfloor
и использоватьismember
?ismember(floor(datenum(arDt1)), floor(datenum(arDt2)))
2. Да, действительно, спасибо! — Я знал , что должно быть что-то простое. 🙂 И я уже проверил
datenum
, надеясь на «целыми днями только» (доктор говорит, что он «представляет каждый момент времени, так как количество дней в январе 0, 0000.»), но потом обнаружил, что она также содержит доли день, поэтому (преждевременно) разочаровался в ней, не думая о пол(). Кроме того, я думалdatenum
, что в любом случае больше не рекомендуется (док говорит, что «лучший способ представления точек во времени-это использованиеdatetime
типа данных»). Но для этой конкретной цели это,конечно, правильно.
Ответ №1:
Вы можете использовать функцию СДВИГА дат, чтобы переместить все даты в начало дня, а затем выполнить сравнение.
ismember(dateshift(arDt1,'start','day'),dateshift(arDt2,'start','day'))
ans =
1×10 logical array
1 0 1 0 1 0 1 0 1 0
Комментарии:
1. Спасибо. До сих пор совершенно не замечал этого.
Ответ №2:
Альтернативным решением было бы использовать свойства datetime
напрямую. Это означает сравнение свойств года, месяца и дня. Я предпочитаю этот подход, так как он позволяет мне, например, также фильтровать данные за данный месяц (пренебрегая днем).
arDt1 = datetime(2021,5,1:10,0,0,0); % 1. to 10. May, always at time 00:00:00
arDt2 = datetime(2021,5,1:2:10,12,0,0); % 1.,3.,5.,7.,9. May always at time 12:00:00
arDtYMD1 = [arDt1.Year', arDt1.Month', arDt1.Day']; % 10x3 double
arDtYMD2 = [arDt2.Year', arDt2.Month', arDt2.Day']; % 5x3 double
all(ismember(arDtYMD1, arDtYMD2),2) % 10x1 logical array
Комментарии:
1. Спасибо. Это будет очень полезно и в других контекстах.