AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 06.01.2009, 17:15   #6  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,719 / 1204 (44) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от mazzy Посмотреть сообщение
Разница между месяцами существенно проще разницы между датами (потому что нет проблемы 29 февраля).
Наоброт. Как только возникает задача получение разницы между датами в формате "Лет-Месяцев-Дней" вместо простой разницы дней, то возникает такое количество "наворотов", что без "пол-литры" не разберешся.

Проблема здесь в том, что именно требуется получить. Т.е. что подразумевается под термином "месяц" и, в меньшей степени, под термином "год".

Разумеется, есть некоторые стандартные наработки. Например, функция IntvNo() или тот же класс RHRMDateDiff(). Вопрос только в том, ЧТО они считают?

================================================================

Вопрос

Как получить разницу двух дат в формате: лет, месяцев, дней

Ответ

В общем случае, данный вопрос не имеет решения.

Пожалуйста, не надо сразу бросаться писать опровержения, что вот у меня есть готовый код, который это делает или вот есть ссылка на решение. Сначала дочитайте до конца, что именно подразумевается в данном случае под фразой "решения не имеет".

Проблема заключается в том, что нет однозначного определения того, что есть "месяц" и "год". Как правило, под этим подразумевают календарные месяцы. Но сложность в том, что календарный месяц - это понятие не абсолютное, а относительное. Календарный месяц - это не просто некоторое количество дней. Это количество дней, прошедших с определенной даты.

Для лучшего понимания проблемы рассмотрим простой пример.

Надо определить разницу дат между 30 января и 2 апреля одного 2008 года.

Если бы задача заключалась в определении количества дней, то все решалось бы простым вычитанием


X++:
fromDate = 30\01\2008;
toDate = 02\04\2008;

print  toDate - fromDate;     // 63 дня
pause;

А как определить количество месяцев? Результат будет существенно зависеть от того, как именно будет определяться один месяц. Возможно несколько идеологий расчета:

Вариант 1

Прибавляем к начальной дате последовательно по одному месяцу до тех пор, пока результат не превысит конечной даты.

Под термином "месяц" в процессе прибавления подразумевается такая операция, в результате которой номер дня остается тот же самый, а номер месяца увеличивается на 1. Если у нового месяца нет такой даты, то устанавливается дата равная последнему дню нового месяца.

Это значит, что если прибавить один месяц к 30 января, то получим 29 февраля (2008 год - високосный), поскольку в феврале нет 30 числа.

Затем прибавляем к 29 февраля еще один месяц, получаем 29 марта. Прибавлять еще один месяц уже не надо, поскольку результат будет заведомо больше 2 апреля.

Между 29 марта и 2 апреля остается 4 дня. Значит, результат будет 2 месяца и 4 дня.

Заметьте, что в не високосном году результат был бы 2 месяца и 5 дней

Обратите внимание на тот факт, что если начальная дата равна 29, 30 или 31 января результат был бы один и тот же! Поскольку прибавление одного месяца давало бы все то же 29 февраля. Получается парадоксальная ситуация - количество дней разное, а результат одинаковый.


Вариант 2

Алгоритм похож на "Вариант 1", но прибавлять будем не по одному месяцу за раз, а сразу прибавим столько месяцев, чтобы оказаться как можно ближе к конечной дате. Т.е. прибавим к 30 января сразу 2 месяца и получим 30 марта.

Между 30 марта и 2 апреля остается 3 дня. Значит, результат будет 2 месяца и 3 дня.

Заметьте, что если бы конечным месяцем был бы не апрель, а март, то данный вариант расчета ничем не отличался бы от "Варианта 1".

Именно этот алгоритм заложен в классе RHRMDateDiff()

Вариант 3

Под термином "месяц" будем понимать именно календарный месяц. Т.е. февраль - это интервал от 01 февраля до 29 февраля, март - это интервал от 01 марта до 31 марта.

В этом случае имеем 2 полных месяца - февраль и март. И "остатки" от граничных месяцев: 1 день до конца января и 2 дня апреля. Значит, результат будет 2 месяца и 3 дня.

Но в данном случае повезло. Оставшихся дней явно не хватает для полного месяца. А если бы оставшихся дней было бы, например, 40 (с 10 января по 20 апреля)? Встал бы вопрос, сколько дней надо выделить из этого количества дней, чтобы получить еще 1 месяц? Берем количество дней в январе (месяце начала периода) или в апреле (месяце конца периода)?


Вариант 4

Принимаем, что все месяцы имеют одинаковое количество дней, которое вычисляется по следующей формуле:


(365+365+365+366)/4/12 = 30.4375

Тогда количество месяцев - это просто отношение количества дней к данной константе, округленное до целого. Значит, результат будет 2 месяца и 2 дня.


Могут быть и другие варианты расчета.


Как видите, результат существенно зависит от того, что именно понимается под термином "месяц". Точнее, как именно этот самый месяц выделяется в заданном диапазоне. Причем, даже нельзя сказать, что один способ является "правильным", а другие "не правильные". Они все "правильные". Но в рамках определенной идеологии.

Другими словами, вопрос расчета интервала в формате "лет, месяцев, дней" заключается не столько в коде, сколько в идеологии (алгоритме) расчета. Как только будет принята определенная идеология расчета, запрограммировать ее не составит труда.

Выбор того или иного способа определения месяца, как правило, определяется той задачей, которую необходимо решить. Просто поздравить именинника (можно и несколько дней подряд - не страшно ), определить трудовой стаж или статистика в родильном отделении.

Следует еще заметить, что те же проблемы касаются и определения любых других календарных интервалов. Таких как "неделя", "квартал", "год". Т.е. прежде чем писать код, необходимо описать по каким правилам будут определяться указанные интервалы.

Вы можете поискать уже готовые примеры расчета на данном сайте или в интернете. Но всегда следует иметь в виду, что все эти примеры кодируют определенную идеологию определения месяца и года. К сожалению, как именно (по какой идеологии) происходит это определение из кода далеко не всегда видно. Поэтому, результат работы найденных примеров может оказаться далек от ожидаемых Вами. Каждый пример следует тщательно протестировать для определения его пригодности под Вашу конкретную задачу.
За это сообщение автора поблагодарили: mazzy (2), lev (1), petr (2), oip (2), Gustav (5).
Теги
дата

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Странное количество в строке журнала инвентаризации pitersky DAX: Функционал 7 16.01.2009 16:46
как отдельно учитывать фактическое и финансовое количество? romulis DAX: Функционал 4 08.02.2007 15:01
Количество знаков после запятой для количества в Закупке. dimit DAX: Функционал 18 20.11.2006 17:23
Функция возвращающая количество месяцев нужна, никто не видел?.. MironovI DAX: Программирование 3 29.09.2005 12:05
Закупка. Количество введенное в таблицу PurchLine не отображается в накладной ATimTim DAX: Программирование 15 21.06.2004 10:11

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 18:27.