Преобразуйте дату в ближайшую дату конца месяца MATLAB

Мне нужно преобразовать число даты в ближайшую дату конца месяца. Я нашел онлайн-ссылку, но она очень неэффективна для большой матрицы (по адресу http://www.mathworks.com/matlabcentral/fileexchange/26374-round-off-dates-and-times). Есть ли в Matlab (Financial Toolbox) встроенная функция для этого? Я не мог найти его.

date_in = 734421 ;
somefunction(date_in) --> Sept 2010

Спасибо!


person Maddy    schedule 20.07.2011    source источник
comment
Что значит ближайший конец месяца? 734421 — это 10 октября 2010 года, а вы хотите, чтобы это был сентябрь 2010 года? Так будет ли 28 сентября 2010 года октябрём 2010 года?   -  person abcd    schedule 20.07.2011
comment
Да Йода. Представьте, что у вас есть финансовые данные, и вы должны использовать ближайший обменный курс на конец месяца. Спасибо!   -  person Maddy    schedule 20.07.2011
comment
??? Почему конец сентября 2010 года не ближе к 28 сентября 2010 года, чем к октябрю 2010 года???   -  person Jonas Heidelberg    schedule 21.07.2011
comment
... Я думаю, что теперь я могу понять: может ли конец может также означать до начала в вашем случае? Если у вас есть день в сентябре, вам нужен ближайший месяц (до или после), который НЕ является самим сентябрем?   -  person Jonas Heidelberg    schedule 21.07.2011
comment
@Jonas Heidelberg: Вот как я интерпретировал это на основе комментариев выше: ближайший предыдущий или следующий месяц. Кажется немного странным, но похоже на то, что хочет ОП.   -  person gnovice    schedule 21.07.2011
comment
@gnovice Мне интересно, следует ли изменить заголовок / текст вопроса. Для меня конец месяца действительно вводит в заблуждение относительно того, что на самом деле здесь спрашивают...   -  person Jonas Heidelberg    schedule 21.07.2011


Ответы (2)


У меня были некоторые ошибки в моей предыдущей версии. Вот логика, встроенная в функцию. Он также проверяет месяц и соответственно обновляет.

function out = roundMonth(dateNumber)
    dateVector = datevec(dateNumber);
    day = dateVector(3);
    month = dateVector(2);
    year = dateVector(1);

    month = month + sign(day - 15 + double(~(month-2)))...
        + double(~(day-15 + double(~(month-2))));

    dateVector(1) = year + double((month-12)==1) - double((1-month)==1);
    dateVector(2) = mod(month,12) + 12*double(~mod(month,12));

    out = datestr(dateVector,'mmm yyyy');

ПРИМЕРЫ:

1.

roundMonth(datenum('10-Oct-2010'))

ans =

Sep 2010

2.

roundMonth(datenum('20-Oct-2010'))

ans =

Nov 2010

3.

roundMonth(datenum('20-Dec-2010'))

ans =

Jan 2011

4.

roundMonth(datenum('10-Jan-2010'))

ans =

Dec 2009
person abcd    schedule 20.07.2011
comment
Кроме того, вы должны быть осторожны с крайними случаями, такими как обычный/високосный год с 28/29 днями в феврале, поэтому его не всегда сравнивают с 15... Никогда не бывает легко иметь дело с датами! - person Amro; 21.07.2011
comment
@Amro: Согласен, даты всегда беспорядочные. Для февраля вы просто замените 15 на 14, а 28/29 будет таким же, как 30/31. В качестве средней точки приходится довольствоваться либо 15, либо 16 (или 14/15 февраля), и выбор произволен. Я обновил, чтобы учесть февраль и изменение года (предыдущий декабрь или следующий январь). - person abcd; 21.07.2011
comment
Кроме того, это касается только одной даты. Он не может обрабатывать массив дат. - person Marc; 21.07.2011
comment
@Marc: datestr плохо обрабатывает векторы. Однако эту часть можно легко решить, написав собственную функцию преобразования. В качестве альтернативы вы можете использовать arrayfun для работы с массивом. - person abcd; 21.07.2011
comment
... ваши ~(month-2) задачи связаны с особым случаем февраля, верно? - person Jonas Heidelberg; 21.07.2011
comment
@Jonas: Верно. Если это февраль, вычтите 14 вместо 15. - person abcd; 21.07.2011

По сути, это звучит так, как будто вы спрашиваете, ближе ли данная дата к предыдущему или следующему месяцу. Вы можете значительно упростить задействованную логику, если будете использовать функции EOMDAY для нахождения дата конца месяца и ADDTODATE для смещения текущего месяца вверх или вниз на один. Вот пример функции, которая принимает число даты в качестве входных данных:

function closestString = closest_month(dateNumber)

  dateVector = datevec(dateNumber);
  daysInMonth = eomday(dateVector(1),dateVector(2));
  if dateVector(3) > daysInMonth/2
    dateNumber = addtodate(dateNumber,1,'month');
  else
    dateNumber = addtodate(dateNumber,-1,'month');
  end
  closestString = datestr(dateNumber,'mmm yyyy');

end
person gnovice    schedule 21.07.2011
comment
+1, так как оно намного понятнее, чем решение yoda, и дает тот же результат в его четырех тестовых примерах ;-). - person Jonas Heidelberg; 21.07.2011