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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 06.01.2009, 14:43   #1  
V777 is offline
V777
совсем зелен
 
249 / 10 (1) +
Регистрация: 15.04.2008
количество месяцев...
как быстрее и проще вычислить количество месяцев за период с первой даты по вторую???
Старый 06.01.2009, 16:00   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
в ax4 стандартной функции вроде нет.
стоит попытаться через mthonyr.

Что-нибудь вроде
X++:
{
   Date dateFrom = 01\06\1995;
   Date dateTo = 01\04\2008;
   int years = year(dateTo) - year(dateFrom);
   int month = mthofyr(DateTo) - mthofYear(dateFrom);

   return ((years * 12) + month;
}

В ax2009 тип Date изменен на dateTime. Поэтому стоит посмотреть в сторону .net функций
__________________
полезное на axForum, github, vk, coub.
Старый 06.01.2009, 16:33   #3  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
AxPath://AOT/Classes/RAssetTableInterval_Month/monthDifference
За это сообщение автора поблагодарили: gefr (1).
Старый 06.01.2009, 16:37   #4  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Может, вот это пригодится:

Функция, вычисляющая разницу между датами.

--- возвращает контейнер из семи значений:
1. полные годы разницы - от 0 до бесконечности
2. полные месяцы (свыше полных лет) - от 0 до 11
3. дни неполного месяца (свыше полных месяцев) - от 0 до 30
4. недели месяца (свыше полных месяцев) - от 0 до 4
5. дни неполной недели (свыше полных недель) - от 0 до 6
6. общей кол-во дней разности - от 0 до бесконечности
7. дни неполного года - от 0 до 365
Старый 06.01.2009, 16:42   #5  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Gustav Посмотреть сообщение
Погоди.

Разница между месяцами существенно проще разницы между датами (потому что нет проблемы 29 февраля).
Поэтому вычислять число месяцев через число дней... Это тоже изврат... Конечно не такой как мегаизврат с циклом... Но...
__________________
полезное на axForum, github, vk, coub.
Старый 06.01.2009, 16:54   #6  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от mazzy Посмотреть сообщение
Поэтому вычислять число месяцев через число дней... Это тоже изврат...
Никто и не предлагает этим заниматься. Для получения полного количества месяцев надо умножить полное кол-во лет (элемент 1 контейнера) на 12 и добавить месяцы неполного года (элемент 2).

Я просто выдаю все те величины, которые, как правило, не могут быть получены тривиальным путем, оставляя выбор пользователю функции выполнять заключительные тривиальные действия. Например, для получения общего количества недель срока надо всего лишь общее кол-во дней (элемент 6) разделить на 7. И т.п.
Цитата:
Сообщение от mazzy Посмотреть сообщение
Кроме того, и этот класс не работает, если дата начала больше даты конца.
Вот! А функцайка работает, возвращая отрицательные значения
Старый 06.01.2009, 17:15   #7  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,692 / 1195 (43) ++++++++
Регистрация: 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).
Старый 06.01.2009, 16:53   #8  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Кстати, спасибо за ссылку.
Здесь njd дал информацию о русском классе RHRMDateDiff

Он вычисляет число лет, месяцев, дней.
Причем число месяцев не может быть больше 12, а число дней не может быть больше 31.
Т.е. для вычисления полного числа месяцев придется вычислять еще одно выражение (getYear() * 12 + getMonth()).
Кроме того, и этот класс не работает, если дата начала больше даты конца.

Кроме того, они зачем-то делают вычисления в момент инициализации класса (что теоретически не есть хорошо поскольку может значительно снизить эргономичность работы, если кто-то начнет инициализировать подобные структуры в init'е формы).
__________________
полезное на axForum, github, vk, coub.
Старый 06.01.2009, 17:27   #9  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от mazzy Посмотреть сообщение
Кстати, спасибо за ссылку.
Здесь njd дал информацию о русском классе RHRMDateDiff
Ну и в той же ветке чуть выше этот класс раскритикован
Старый 06.01.2009, 16:39   #10  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от belugin Посмотреть сообщение
AxPath://AOT/Classes/RAssetTableInterval_Month/monthDifference
Ты хоть смотрел туда?
Максим не надо гадость советовать.
Вычсиление числа месяцев через цикл...
Кроме того, он вообще не работает, если date dateFrom > dateTo....

Это такой антипаттерн... Что у меня просто слов не хватает... Название: bad.gif
Просмотров: 4975

Размер: 2.7 Кб
Никогда так не делайте!
__________________
полезное на axForum, github, vk, coub.
Старый 12.01.2009, 07:12   #11  
petergunn is offline
petergunn
Участник
 
118 / 274 (10) ++++++
Регистрация: 30.08.2005
Адрес: Tyumen
? intvNo
Цитата:
Сообщение от mazzy Посмотреть сообщение
в ax4 стандартной функции вроде нет.
стоит попытаться через mthonyr.

Что-нибудь вроде
X++:
{
   Date dateFrom = 01\06\1995;
   Date dateTo = 01\04\2008;
   int years = year(dateTo) - year(dateFrom);
   int month = mthofyr(DateTo) - mthofYear(dateFrom);

   return ((years * 12) + month;
}
Возможно повторюсь, но в стандарте Microsoft Dynamics AX 4 - intvNo Function вызов функции intvNo( dateTo, dateFrom, intvScale::YearMonth ) с параметром IntvScale::YearMonth дает аналогичный результат.
За это сообщение автора поблагодарили: mazzy (2), belugin (5), V777 (1).
Старый 12.01.2009, 07:23   #12  
V777 is offline
V777
совсем зелен
 
249 / 10 (1) +
Регистрация: 15.04.2008
lev
гы...то что надо...вот из-за не знаний таких мелочей куча проблем..,
Старый 06.01.2009, 16:59   #13  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Упс, я помнил что русский класс имеется для вычиление разницы, но не помнил какой приношу извинения
Старый 08.01.2009, 12:11   #14  
V777 is offline
V777
совсем зелен
 
249 / 10 (1) +
Регистрация: 15.04.2008
а что за функция mthofYear??? ругается говорит не объявлена...
Старый 08.01.2009, 13:04   #15  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
А блин... Извините.
mthofyr, конечно.
исправил код в предыдущем сообщении.
__________________
полезное на axForum, github, vk, coub.
Старый 08.01.2009, 13:53   #16  
V777 is offline
V777
совсем зелен
 
249 / 10 (1) +
Регистрация: 15.04.2008
вопщем писщу для размышлений дали...спасибо будим думать...а то я про функции year, mthofYr и dayofmth и не знал..,
Старый 11.01.2009, 16:37   #17  
lev is offline
lev
Ищущий знания...
Аватар для lev
Oracle
MCBMSS
Axapta Retail User
 
1,723 / 491 (20) +++++++
Регистрация: 18.01.2005
Адрес: Москва
Lightbulb
Цитата:
Сообщение от V777 Посмотреть сообщение
вопщем писщу для размышлений дали...спасибо будим думать...а то я про функции year, mthofYr и dayofmth и не знал..,
для справки, список существующих функций можно вызвать горячими клавишами shift+F4, а так же посмотреть в классе Global.
Изменяюсь что не по теме
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с)
С Уважением,
Елизаров Артем
За это сообщение автора поблагодарили: V777 (1).
Старый 12.01.2009, 17:08   #18  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,692 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от lev Посмотреть сообщение
для справки, список существующих функций можно вызвать горячими клавишами shift+F4, а так же посмотреть в классе Global.
Изменяюсь что не по теме
Добавлю, что список того, что вызывается через Shift+F4 находится в ветке

\System Documentation\Functions
Теги
дата

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Странное количество в строке журнала инвентаризации 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, время: 08:53.