Поведение Datenum с конкатенацией пустой строки - PullRequest
6 голосов
/ 18 июня 2019

Я заметил странное поведение в функции datenum с MATLAB R2017a и выше:

Если вы попытаетесь запустить:

date = datenum([""],'yyyymmdd');

Получаем предупреждение:

Предупреждение: использование DATENUM с пустыми символьными векторами даты или пустыми строками не поддерживается. Результаты могут измениться в будущих версиях.

date = 
      0x1 empty double column vector

Но теперь, если мы запустим:

date = datenum(["","20181012"],'yyyymmdd')

Получаем:

date = 2x1:
          737426 % which corresponds to 20190101
          737345

Так что оба раза мы даем пустую строку для datenum, но если массив содержит несколько строк, результат будет другим. Почему может анализироваться пустая строка, когда присутствуют другие строки, даже другая пустая строка, но не сама по себе?

Ответы [ 2 ]

5 голосов
/ 18 июня 2019

Это, вероятно, ошибка.

Начало функции datenum содержит

arg1 = stringToLegacyText(arg1);

, где arg1 - первый вход datenum. Функция stringToLegacyText в соответствии со своим кодом выполняет следующие действия:

S = STRINGTOLEGACYTEXT(S) converts the string array S to a char row vector,
if S is a scalar, or to a cellstr, if S is not a scalar.

То есть

>> stringToLegacyText([""])
ans =
  0×0 empty char array

>> stringToLegacyText(["" ""])
ans =
  1×2 cell array
    {0×0 char}    {0×0 char}

>> stringToLegacyText(["" "20181012"])
ans =
  1×2 cell array
    {0×0 char}    {'20181012'}

Позже есть этот тест:

if isdatestr && isempty(arg1)
   n = zeros(0,1);
   warning(message('MATLAB:datenum:EmptyDate'));
   return;
end

выдает предупреждение, которое вы упомянули, если arg1 пусто. Тест дает истину для первого случая выше ([""]), но не для второго (["" ""]) или третьего (["" "20181012"]). Таким образом, для второго или третьего случая функция продолжается до

n = dtstr2dtnummx(arg1,matlab.internal.datetime.cnv2icudf(arg2))

Функция dtstr2dtnummx недокументирована:

>> which dtstr2dtnummx
built-in (undocumented)

Но он ожидает массив ячеек векторов символов в качестве первого аргумента и как-то дает 737426 для пустых векторов символов:

>> dtstr2dtnummx({''}, matlab.internal.datetime.cnv2icudf(arg2))
ans =
      737426

>> dtstr2dtnummx({'' ''}, matlab.internal.datetime.cnv2icudf(arg2))
ans =
      737426
      737426

>> dtstr2dtnummx({'' '20181012'}, matlab.internal.datetime.cnv2icudf(arg2))
ans =
      737426
      737345
4 голосов
/ 18 июня 2019

Мне удалось посмотреть, как datenum анализирует свои входные аргументы в R2018a, набрав edit datenum. Первое, что он делает, это передает первый аргумент функции stringToLegacyText, которая преобразует его из строкового типа в массив символов или (и это ключ) массив ячеек массивов символов :

>> import matlab.internal.datatypes.stringToLegacyText  % Get helper function
>> stringToLegacyText([""])  % Single empty string

ans =

  0×0 empty char array

>> stringToLegacyText(["", "20181012"])  % Array of strings

ans =

  1×2 cell array

    {0×0 char}    {'20181012'}

Некоторое время спустя в коде выполняется эта проверка:

if isdatestr && isempty(arg1)
    n = zeros(0,1);
    warning(message('MATLAB:datenum:EmptyDate'));
    return;
end

И здесь возникает несоответствие. Функция isempty возвращает true для пустого массива символов (выдает предупреждение), но возвращает false для непустого массива ячеек, даже если этот массив ячеек содержит все пустые объекты. По какой-то причине пустые записи по умолчанию равны 1 января ст , 2019:

>> datestr(737426)

ans =

    '01-Jan-2019'

Я думаю, что правильным решением здесь было бы обновить условие проверки массива ячеек с помощью любых пустых записей:

if isdatestr && (isempty(arg1) || (iscell(arg1) && any(cellfun('isempty', arg1))))
    n = zeros(0,1);
    warning(message('MATLAB:datenum:EmptyDate'));
    return;
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...