В данной теме хочется поговорить о функциях работы с датами.
Очень часто в своих разработках мы используем данные функции п.э. далее перечислим самые популярные и полезные на мой взгляд.
Очень часто в своих разработках мы используем данные функции п.э. далее перечислим самые популярные и полезные на мой взгляд.
Даты передается и возвращается в стандартном формате типа SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День):
data: begda like sy-datum,
endda like sy-datum.
Я думаю все знают как получить первый день месяца.
CONCATENATE YYYY MM '01' into begda.
* Возвращает последний день месяца в формате YYYYMMDD (YYYY - Год, MM - Месяц, DD - День).
* Определение номера недели для даты в формате YYYYWW (YYYY - Год, WW - Неделя):
* Возвращает дату, с которой начинается неделя по ее номеру. Номер недели в формате YYYYWW (YYYY - Год, WW - Неделя). Дата в стандартном формате типа SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День):
* Преобразование внутреннего представления даты в стандартный вид типа SY-DATUM. Знаю только одну ситуацию, где используется такое, это таблица курсов валют TCURR, там все даты заданы именно во внутреннем формате. Передается дата в формате вида TCURR-GDATU, а возвращается стандартное представление типа SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День):
* Дата начала периода к варианту финансового года. Стандартные параметры - год вида YYYY. Вариант финансового года для БЕ в виде CC. Номер требуемого периода задается в формате NNN. Возвращаемая дата представлена в стандартном типе SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День). Стандартно как бы используется практически везде вариант финансового года K4 - т.е. 4 квартала. Если пишем универсальную программу, то начало периода лучше считать используя данный ФМ:
* Дата конца периода к варианту финансового года. Стандартные параметры - год вида YYYY. Вариант финансового года для БЕ в виде CC. Номер требуемого периода задается в формате NNN. Возвращаемая дата представлена в стандартном типе SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День). Собственно причина почему её желательно использовать такая же как и для предыдущего функционального модуля FIRST_DAY_IN_PERIOD_GET:
* Дата через NN-Дней, MM-Месяцев и YY-Лет от заданной. При этом можно как суммировать так и отнимать требуемое количество дней, месяцев и лет. О високосном годе, вроде, как тоже знает. Из полезного можно добавлять например 55 дней и 1 месяц и т.д. Если даты нужно отнимать, тогда нужно задать параметр SIGNUM = '-':
* Возвращает внутреннюю таблицу со списком, как сокращенных наименований месяцев (3 символа), так и полных, в именительном падеже на заданном языке. По умолчанию, используется язык регистрации в системе:
Так же есть еще одна хорошая функция попоиску имени месяца в именительном и родительном падеже:
* Возвращает в заданном диапазоне список выходных/праздничных дней для выбранного производственного и праздничного календаря. Праздничные и выходные дни берутся из настройки соответствующих календарей, так что если там пусто, то и список будет пустой. Если заданные календари не найдены тогда l_returncode = '4':
* Функция округления даты. В общем виде возвращает последний/первый день недели, месяца, года... иногда полезно, чтобы не вызвать кучу функций расчета даты:
* Выдает текстовое имя дня недели и полную строку дня. Возвращает таблицу дней, так что можно задать диапазон дат:
* Возвращает кол-во лет, месяцев, дней между 2-мя датами.
Для точности отнять от даты окончания один день
t_date = t_date - 1.
CALL FUNCTION 'HR_HK_DIFF_BT_2_DATES'
EXPORTING
date1 = t_date
date2 = t_dat01
output_format = '05'
IMPORTING
years = years
months = months
days = days
EXCEPTIONS
invalid_dates_specified = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
endda like sy-datum.
Я думаю все знают как получить первый день месяца.
CONCATENATE YYYY MM '01' into begda.
* Возвращает последний день месяца в формате YYYYMMDD (YYYY - Год, MM - Месяц, DD - День).
CALL FUNCTION 'LAST_DAY_OF_MONTHS'EXPORTING
DAY_IN = begda
IMPORTING
LAST_DAY_OF_MONTH = endda
EXCEPTIONS
DAY_IN_NO_DATE = 1
OTHERS = 2.
* Определение номера недели для даты в формате YYYYWW (YYYY - Год, WW - Неделя):
DATA: l_week LIKE scal-week.
CALL FUNCTION 'DATE_GET_WEEK'
EXPORTING
date = sy-datum
IMPORTING
week = l_week
EXCEPTIONS
date_invalid = 1
OTHERS = 2.
* Возвращает дату, с которой начинается неделя по ее номеру. Номер недели в формате YYYYWW (YYYY - Год, WW - Неделя). Дата в стандартном формате типа SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День):
DATA: l_week LIKE scal-week,
l_datum like sy-datum.
CALL FUNCTION 'WEEK_GET_FIRST_DAY'
EXPORTING
week = l_week
IMPORTING
DATE = l_datum
EXCEPTIONS
WEEK_INVALID = 1
OTHERS = 2.
* Преобразование внутреннего представления даты в стандартный вид типа SY-DATUM. Знаю только одну ситуацию, где используется такое, это таблица курсов валют TCURR, там все даты заданы именно во внутреннем формате. Передается дата в формате вида TCURR-GDATU, а возвращается стандартное представление типа SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День):
DATA: l_datum LIKE sy-datum,
l_gdatu LIKE tcurr-gdatu.
l_gdatu = '79948998'.
CALL FUNCTION 'DATE_CONV_EXT_TO_INT'
EXPORTING
i_date_ext = l_gdatu
IMPORTING
e_date_int = l_datum
EXCEPTIONS
error = 1
OTHERS = 2.
* Дата начала периода к варианту финансового года. Стандартные параметры - год вида YYYY. Вариант финансового года для БЕ в виде CC. Номер требуемого периода задается в формате NNN. Возвращаемая дата представлена в стандартном типе SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День). Стандартно как бы используется практически везде вариант финансового года K4 - т.е. 4 квартала. Если пишем универсальную программу, то начало периода лучше считать используя данный ФМ:
DATA: l_gjahr LIKE t009b-bdatj,
l_periv LIKE t009b-periv,
l_poper LIKE t009b-poper,
l_datum LIKE sy-datum.
l_gjahr = '2007'.
l_periv = 'K4'.
l_poper = '002'.
CALL FUNCTION 'FIRST_DAY_IN_PERIOD_GET'
EXPORTING
i_gjahr = l_gjahr
* I_MONMIT = 00
i_periv = l_periv
i_poper = l_poper
IMPORTING
e_date = l_datum
EXCEPTIONS
input_false = 1
t009_notfound = 2
t009b_notfound = 3
OTHERS = 4.
* Дата конца периода к варианту финансового года. Стандартные параметры - год вида YYYY. Вариант финансового года для БЕ в виде CC. Номер требуемого периода задается в формате NNN. Возвращаемая дата представлена в стандартном типе SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День). Собственно причина почему её желательно использовать такая же как и для предыдущего функционального модуля FIRST_DAY_IN_PERIOD_GET:
DATA: l_gjahr LIKE t009b-bdatj,
l_periv LIKE t009b-periv,
l_poper LIKE t009b-poper,
l_datum LIKE sy-datum.
l_gjahr = '2007'.
l_periv = 'K4'.
l_poper = '002'.
CALL FUNCTION 'LAST_DAY_IN_PERIOD_GET'
EXPORTING
i_gjahr = l_gjahr
* I_MONMIT = 00
i_periv = l_periv
i_poper = l_poper
IMPORTING
e_date = l_datum
EXCEPTIONS
input_false = 1
t009_notfound = 2
t009b_notfound = 3
OTHERS = 4.
* Дата через NN-Дней, MM-Месяцев и YY-Лет от заданной. При этом можно как суммировать так и отнимать требуемое количество дней, месяцев и лет. О високосном годе, вроде, как тоже знает. Из полезного можно добавлять например 55 дней и 1 месяц и т.д. Если даты нужно отнимать, тогда нужно задать параметр SIGNUM = '-':
DATA: l_days LIKE t5a4a-dlydy,
l_months LIKE t5a4a-dlymo,
l_years LIKE t5a4a-dlyyr,
l_datum LIKE sy-datum.
l_days = '10'.
l_month = '05'.
l_years = '02'
call function 'RP_CALC_DATE_IN_INTERVAL'
exporting
date = sy-datum
days = l_days
months = l_months
signum = '+'
years = l_years
importing
calc_date = l_datum.
В данном вызове для даты 01.02.2007 будет возвращена дата 11.07.2009.
* Разница в днях и часах между двумя произвольно заданными датами. Дата и время начала и конца диапазона задаются в стандартном типе SY-DATUM (YYYYMMDD, YYYY - Год, MM - Месяц, DD - День). Из особенностей работы:
- Разница вычисляется только для полного количества часов, т.е. между 01:00 и 02:30 будет возвращено все равно 1 час.
- Обязательно нужно задавать поля времени, например хотя бы 1 минута, иначе функция ничего не вернет (Спасибо индусам за наше счастливое детство, но оказывается в этой Индии 00:00:00 времени не бывает в принципе).
- Даты можно задавать как от большей к меньшей так и наоборот, при этом переменная l_earliest будет содержать следующие значения =2 - дата1 больше даты2, =1 - дата1 меньше дата2, если даты равны, тогда сравниваются времена и =2 - время1 больше времени2 и =1 - время 1 меньше времени2, если даты и время совпадают, тогда переменная = 0.
DATA: l_datum_one LIKE sy-datum,
l_time_one LIKE sy-uzeit,
l_datum_two LIKE sy-datum,
l_time_two LIKE sy-uzeit.
DATA: l_datediff TYPE p,
l_timediff TYPE p,
l_earliest TYPE c.
CALL FUNCTION 'SD_DATETIME_DIFFERENCE'
EXPORTING
date1 = l_datum_one
time1 = l_time_on
date2 = l_datum_two
time2 = l_time_two
IMPORTING
datediff = l_datediff
timediff = l_timediff
earliest = l_earliest
EXCEPTIONS
invalid_datetime = 1
OTHERS = 2.
* Возвращает внутреннюю таблицу со списком, как сокращенных наименований месяцев (3 символа), так и полных, в именительном падеже на заданном языке. По умолчанию, используется язык регистрации в системе:
DATA: l_retcode LIKE like sy-subrc,
lt_month LIKE t247 OCCURS 1 WITH HEADER LINE.
CALL FUNCTION 'MONTH_NAMES_GET'
EXPORTING
language = sy-langu
IMPORTING
return_code = l_retcode
TABLES
month_names = lt_month
EXCEPTIONS
month_names_not_found = 1
OTHERS = 2.
Так же есть еще одна хорошая функция попоиску имени месяца в именительном и родительном падеже:
DATA: period(2) TYPE n, month_name(25) type c. CALL FUNCTION 'HR_PAY_UA_MONTH_NAME' EXPORTING MONTHNUM = period IMPORTING MN_NOM = month_name.
* Возвращает в заданном диапазоне список выходных/праздничных дней для выбранного производственного и праздничного календаря. Праздничные и выходные дни берутся из настройки соответствующих календарей, так что если там пусто, то и список будет пустой. Если заданные календари не найдены тогда l_returncode = '4':
DATA: l_holiday_calendar LIKE scal-hcalid,
l_factory_calendar LIKE scal-fcalid,
l_date_from LIKE scal-date,
l_date_to LIKE scal-date,
l_year_of_valid_from LIKE scal-year,
l_year_of_valid_to LIKE scal-year,
l_returncode LIKE sy-subrc,
lt_holidays LIKE iscal_day OCCURS 1 WITH HEADER LINE.
l_factory_calendar = 'UA'.
l_holiday_calendar = 'UA'
l_date_from = '18.07.2007'.
l_date_to = '18.07.2007'.
CALL FUNCTION 'HOLIDAY_GET'
EXPORTING
holiday_calendar = l_holiday_calendar
factory_calendar = l_factory_calendar
date_from = l_date_from
date_to = l_date_to
IMPORTING
year_of_valid_from = l_year_of_valid_from
year_of_valid_to = l_year_of_valid_to
returncode = l_returncode
TABLES
holidays = lt_holidays
EXCEPTIONS
factory_calendar_not_found = 1
holiday_calendar_not_found = 2
date_has_invalid_format = 3
date_inconsistency = 4
OTHERS = 5.
Формат вывода таблички lt_holidays, для приведенного пример следующий:
| DATE | F | H | HOL | TXT_SHORT | TXT_LONG |
| 28.06.2007 | X | X | 168 | День конст | День конституції |
| 24.08.2007 | X | X | 169 | День Незал | День Незалежності |
| 01.01.2008 | X | X | 171 | Новий Рік | Новий Рік |
| 07.01.2008 | X | X | 172 | Різдво Хри | Різдво Христово |
| 01.05.2008 | X | X | 163 | 1 Травня | 1 Травня |
| 02.05.2008 | X | X | 164 | 2 Травня | 2 Травня |
| 09.05.2008 | X | X | 170 | День Перем | День Перемоги |
* Позволяет получить информацию о статусе рабочего дня исходя из данных производственного календаря, присвоенного заводу. При этом, если день не является рабочим, то функция вернет следующий рабочий день в зависимости от параметров.
| CORRECT_OPTION | = '+' - Будет возвращен следующий рабочий день = '-' - Будет возвращен предыдущий рабочий день |
| DATE | = Дата которую требуется проверить |
| FACTORY_CALENDAR_ID | = Код производственного календаря из T001W |
DATA: l_date LIKE scal-date,
l_factorydate LIKE scal-facdate,
l_workingday_indicator LIKE scal-indicator.
CALL FUNCTION 'DATE_CONVERT_TO_FACTORYDATE'
EXPORTING
correct_option = '+'
date = sy-datum
factory_calendar_id = 'RU'
IMPORTING
date = l_date
factorydate = l_factorydate
workingday_indicator = l_workingday_indicator
EXCEPTIONS
calendar_buffer_not_loadable = 1
correct_option_invalid = 2
date_after_range = 3
date_before_range = 4
date_invalid = 5
factory_calendar_not_found = 6
OTHERS = 7.
Результат:
| DATE | = Дата формата SY-DATUM |
| FACTORYDATE | = Дата во внутреннем формате виде TCURR-GDATU, полезно для чтения курса валюты например. |
| WORKINGDAY_INDICATOR |
= В принципе в нем возвращается значение, которое передается в CORRECT_OPTION, что видно из кода
CASE CORRECT_OPTION. WHEN '+'. WORKINGDAY_INDICATOR = '+'. WHEN '-'. WORKINGDAY_INDICATOR = '-'. ENDCASE. Правда зачем так сложно, через CASE сделано, это нам наверное никто не подскажет, ну хотя может найдется тот индус, который это писал, а так может были какие мысли, да так и не реализовались. |
* Номер дня в неделе, понедельник считается первым днем, воскресение 7.
DATA: l_day LIKE scal-indicator.
CALL FUNCTION 'DATE_COMPUTE_DAY'
EXPORTING
date = sy-datum
IMPORTING
day = l_day.
Для даты 16.05.2008 будет возвращен параметр 5.
* Функция возвращает дату представленную во внутреннем формате в нормальный формат, т.е. это обратная конвертация для функции DATE_CONVERT_TO_FACTORYDATE, которая описана выше. Обратите внимание, что поправка на рабочий день выполняется автоматически, т.е. к примеру, если вы укажите число 3995, что равно 01.01.2008, то будет возвращена дата 31.12.2007, т.е. фактически CORRECT_OPTION = '-'. Ну а остальное, вроде, как ясно из текста:
DATA: l_datum LIKE scal-date,
l_factorydate LIKE scal-facdate.
l_factorydate = '3 996'.
CALL FUNCTION 'FACTORYDATE_CONVERT_TO_DATE'
EXPORTING
factorydate = l_factorydate
factory_calendar_id = 'UA'
IMPORTING
date = l_date
EXCEPTIONS
calendar_buffer_not_loadable = 1
factorydate_after_range = 2
factorydate_before_range = 3
factorydate_invalid = 4
factory_calendar_id_missing = 5
factory_calendar_not_found = 6
OTHERS = 7.
Результат: 02.01.2008.
Функция позволяющая добавить или отнять месяцы от заданной даты, понимает високосный год.
DATA: l_date LIKE sy-datum.
CALL FUNCTION 'MONTH_PLUS_DETERMINE'
EXPORTING
months = '1'
olddate = '20080131'
IMPORTING
newdate = l_date.
Параметры:
- months - количество месяцев которое нужно добавить или отнять от даты. Для вычитания нужно записать значение как -1;
- olddate - дата от которой требуется вычесть месяцы;
- l_date - новое значение даты.
* Проверяет значение введенной даты на корректность и выдает, строку ошибки, которую можно показать пользователю, что не нравится в веденной им дате:
DATA: l_date LIKE vtb_market-ddate,
l_sstats LIKE vtb_market-sstats,
l_error_flg LIKE vtb_market-rupdhist,
l_error_msg LIKE vtb_market-error.
l_date = '301173'.
CALL FUNCTION 'TB_DATAFEED_CHECK_DATE'
EXPORTING
date = l_date
CHANGING
sstats = l_sstats
error_flg = l_error_flg
error_msg = l_error_msg.
В ответ будет получено типа:
- l_sstats = E
- l_error_flg = X
- l_error_msg = Дата 301173 содержит недопустимый пробел!
* Проверка значения введенной даты. Так сказать еще одна вариация, когда проверяется, что введено.
function date_check_plausibility.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*" IMPORTING
*" DATE LIKE SY-DATUM
*" EXCEPTIONS
*" PLAUSIBILITY_CHECK_FAILED
*"----------------------------------------------------------------------
data: check_year_1 type p.
data: check_year_2 type p.
if date cn '0123456789'.
message s011 with date raising plausibility_check_failed.
endif.
if date+4(2) lt '01'
or date+4(2) gt '12'.
message s003 with date+4(2) raising plausibility_check_failed.
endif.
if date+6(2) lt '01'
or date+6(2) gt '31'.
message s006 with date+6(2) raising plausibility_check_failed.
endif.
if date+4(2) eq '01'
or date+4(2) eq '03'
or date+4(2) eq '05'
or date+4(2) eq '07'
or date+4(2) eq '08'
or date+4(2) eq '10'
or date+4(2) eq '12'.
if date+6(2) gt '31'.
message s004 with date+6(2) date+4(2)
raising plausibility_check_failed.
endif.
elseif date+4(2) eq '04'
or date+4(2) eq '06'
or date+4(2) eq '09'
or date+4(2) eq '11'.
if date+6(2) gt '30'.
message s004 with date+6(2) date+4(2)
raising plausibility_check_failed.
endif.
else.
check_year_1 = date(4) mod 4. " alle 4 Jahre ist schaltjahr
if check_year_1 eq 0.
check_year_1 = date(4) mod 100. " aber nicht alle 100 Jahre
check_year_2 = date(4) mod 400. " aber alle 400 Jahre
if check_year_1 eq 0
and check_year_2 ne 0.
if date+6(2) gt '28'.
message s004 with date+6(2) date+4(2)
raising plausibility_check_failed.
endif.
else.
if date+6(2) gt '29'.
message s004 with date+6(2) date+4(2)
raising plausibility_check_failed.
endif.
endif.
else.
if date+6(2) gt '28'.
message s004 with date+6(2) date+4(2)
raising plausibility_check_failed.
endif.
endif.
endif.
endfunction.
* Возвращает начальную и конечную дату периода, для заданного варианта финансового года:
DATA: l_fday LIKE bkpf-budat,
l_lday LIKE bkpf-budat,
l_speriod LIKE bkpf-bstat.
CALL FUNCTION 'PERIOD_DAY_DETERMINE'
EXPORTING
i_gjahr = '2009'
i_monat = '02'
i_periv = 'K4'
IMPORTING
e_fday = l_fday
e_lday = l_lday
e_speriod = l_speriod
EXCEPTIONS
error_period = 1
error_period_version = 2
firstday_not_defined = 3
period_not_defined = 4
year_invalid = 5
OTHERS = 6.
На выходе получим:
L_FDAY - 01.02.2009 Дата начала периода
L_LDAY - 28.02.2009 Дата конца периода
L_SPERIOD - SPACE - Признак специального периода проводки
L_FDAY - 01.02.2009 Дата начала периода
L_LDAY - 28.02.2009 Дата конца периода
L_SPERIOD - SPACE - Признак специального периода проводки
* Функция округления даты. В общем виде возвращает последний/первый день недели, месяца, года... иногда полезно, чтобы не вызвать кучу функций расчета даты:
DATA: l_datum LIKE sy-datum.
l_datum = sy-datum.
CALL FUNCTION 'ROUND_DATE'
EXPORTING
i_iprkz = '2'
i_rdmhd = '+'
CHANGING
c_date = l_datum
EXCEPTIONS
invalid_round_rule = 1
OTHERS = 2.
WRITE: / l_datum DD/MM/YYYY.
i_iprkz - код периода. Могут быть следующие значения:
- SPACE - день, смысла в этом коде нет, так как время не округляется, а возваращаемая дата = переданной дате;
- '1' = неделя, возвращает дату конца/начала недели;
- '2' = месяца, возвращает дату конца/начала месяца;
- '3' = год, возвращает дату конца/начала года.
i_rdmhd - направление округления:
- '+' - округление до конца периода, т.е. если задан код периода 2, то текущая дата будет округлена до конца периода и будет содержать дату последнего дня месяца.
- '-' - округление до начала периода, т.е. если задан код периода 2, то текущая дата будет округлена до начала периода и будет содержать дату первого дня месяца. Наверное, это не очень полезно, так как ясно, что дата = 01, а вот началом недели уже не так просто и придется считать.
- 'F' - округление до конца периода, при этом будет возвращаться следующий день за концом периода, т.е. если выбрано тип '1', то будет возращена дата понедельника следующей недели, тогда как при '+' возвращается дата воскресения.
* Позволяет получить от заданной даты новую дату в будущем, путем добавления месяцев и дней. Про високосный год знает:
DATA: l_result_date LIKE sy-datum.
CALL FUNCTION 'CALCULATE_DATE'
EXPORTING
days = '1'
months = '10'
start_date = '20080228'
IMPORTING
result_date = l_result_date.
WRITE: / l_result_date.
В данном примере возвращает 29.12.2008.
* Возвращает название дня недели по заданной дате, но только на английском языке, по этому примера нет, только наименование:
CALL FUNCTION 'DATE_TO_DAY'
EXPORTING
date =
* IMPORTING
* WEEKDAY =.
* Возвращает красивые строчки с расшифровками запрошенных дат, например, 11.02.2008 будут сформированы строки номер дня недели = 3, краткое название дня недели в виде "Ср", полное название дня "Среда" и название дня недели + дата в виде строки "Среда, 11.Март. 2009", в общем удобно, плюс знает, что это всё может быть написано на разных языках:
DATA: l_date_from LIKE sy-datum,
l_date_to LIKE sy-datum,
l_year_of_valid_from LIKE scal-year,
l_year_of_valid_to LIKE scal-year,
l_returncode LIKE sy-subrc,
lt_day_attributes LIKE casdayattr OCCURS 1 WITH HEADER LINE.
l_date_from = sy-datum.
l_date_to = sy-datum + 7.
CALL FUNCTION 'DAY_ATTRIBUTES_GET'
EXPORTING
* FACTORY_CALENDAR = ' '
* HOLIDAY_CALENDAR = ' '
date_from = l_date_from
date_to = l_date_to
language = sy-langu
IMPORTING
year_of_valid_from = l_year_of_valid_from
year_of_valid_to = l_year_of_valid_to
returncode = l_returncode
TABLES
day_attributes = lt_day_attributes
EXCEPTIONS
factory_calendar_not_found = 1
holiday_calendar_not_found = 2
date_has_invalid_format = 3
date_inconsistency = 4
OTHERS = 5.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
Пример возвращенной таблички:
* Рассчитать количество месяцев между двумя датами. Если i_kz_incl_bis не равно SPACE, тогда к переданной дате i_datum_bis до начала вычислений добавляется один день, что само собой может увеличить/уменьшить количество месяцев на единицу:
DATA: l_datum_bis LIKE sy-datum,
l_datum_von LIKE sy-datum,
l_month TYPE i.
l_datum_bis = sy-datum + 100.
l_datum_von = sy-datum.
CALL FUNCTION 'MONTHS_BETWEEN_TWO_DATES'
EXPORTING
i_datum_bis = l_datum_bis
i_datum_von = l_datum_von
i_kz_incl_bis = ' '
IMPORTING
e_monate = l_month.
WRITE: / l_month.
В данном примере l_month = 03.
* Проверяет является переданная дата последним днем месяца + если это високосный год, то второй параметр e_tt будет содержать признак високосной даты в году, параметр e_kz_ult = space дата не последняя дата месяца, "X" - дата является последним днем месяца:
DATA: l_kz_ult(1) TYPE c,
l_tt TYPE i.
CALL FUNCTION 'END_OF_MONTH_DETERMINE_2'
EXPORTING
i_datum = '20080329'
IMPORTING
e_kz_ult = l_kz_ult
e_tt = l_tt.
* Расчёт времени в часах и минутах между двумя датами:
DATA: l_date1 LIKE sy-datum,
l_time1 LIKE sy-uzeit,
l_date2 LIKE sy-datum,
l_time2 LIKE sy-uzeit,
l_tdiff LIKE tvro-fahztd,
l_date2_early LIKE rv56a-selkz.
l_date1 = sy-datum.
l_time1 = sy-uzeit + 5.
l_date2 = sy-datum + 1.
l_time2 = sy-uzeit + 76.
CALL FUNCTION 'SD_CALC_DURATION_FROM_DATETIME'
EXPORTING
i_date1 = l_date1
i_time1 = l_time1
i_date2 = l_date2
i_time2 = l_time2
IMPORTING
e_tdiff = l_tdiff
e_date2_early = l_date2_early
EXCEPTIONS
invalid_datetime = 1
OTHERS = 2.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
WRITE: / l_tdiff,
/ l_date2_early.
Параметр e_date2_early = Х, если i_date1 > i_date2, иначе равно SPACE.
* Рассчитывает время между двумя датами в минутах:
DATA: l_date1 LIKE sy-datum,
l_time1 LIKE sy-uzeit,
l_date2 LIKE sy-datum,
l_time2 LIKE sy-uzeit,
l_delta_time LIKE mcwmit-be_ae,
l_delta_unit LIKE mcwmit-lzeit.
l_date1 = sy-datum.
l_time1 = sy-uzeit + 5.
l_date2 = sy-datum + 1.
l_time2 = sy-uzeit + 76.
CALL FUNCTION 'L_MC_TIME_DIFFERENCE'
EXPORTING
date_from = l_date1
date_to = l_date2
time_from = l_time1
time_to = l_time2
IMPORTING
delta_time = l_delta_time
delta_unit = l_delta_unit
EXCEPTIONS
from_greater_to = 1
OTHERS = 2.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
WRITE: / l_delta_time,
/ l_delta_unit.
* Возвращает не только текущий год, но и месяц. Фактически - текущий открытый период:
DATA: l_currm LIKE bkpf-monat,
l_curry LIKE bkpf-gjahr,
l_prevm LIKE bkpf-monat,
l_prevy LIKE bkpf-gjahr.
CALL FUNCTION 'GET_CURRENT_YEAR'
EXPORTING
bukrs = '1000'
date = sy-datum
IMPORTING
currm = l_currm
curry = l_curry
prevm = l_prevm
prevy = l_prevy.
* Возвращает различное представление даты в формате пользователя. Рекомендуется использовать для формирования строк даты при передаче в батч-интпуты, так как там данные должны быть введены с разделителями пользователя:
DATA: l_mdat4(5) TYPE c,
l_mdat6(7) TYPE c,
l_tdat4(5) TYPE c,
l_tdat6(8) TYPE c,
l_tdat8(10) TYPE c,
l_wdat4(5) TYPE c,
l_wdat6(7) TYPE c.
CALL FUNCTION 'DATUMSAUFBEREITUNG'
EXPORTING
flagm = 'X'
flagw = 'X'
idate = sy-datum
* IMONT = ' '
* IWEEK = ' '
IMPORTING
mdat4 = l_mdat4
mdat6 = l_mdat6
tdat4 = l_tdat4
tdat6 = l_tdat6
tdat8 = l_tdat8
wdat4 = l_wdat4
wdat6 = l_wdat6
EXCEPTIONS
datfm_ungueltig = 1
datum_ungueltig = 2
OTHERS = 3.
WRITE: / l_mdat4,
/ l_mdat6,
/ l_tdat4,
/ l_tdat6,
/ l_tdat8,
/ l_wdat4,
/ l_wdat6.
Пример:
* Позволяет к заданной дате добавить требуемое количество месяцев. Помнит про високосный год:
DATA: l_stdate LIKE sy-datum,
l_count TYPE i,
l_eddate LIKE sy-datum.
l_stdate = sy-datum.
l_count = '5'.
CALL FUNCTION 'RE_ADD_MONTH_TO_DATE'
EXPORTING
months = l_count
olddate = l_stdate
IMPORTING
newdate = l_eddate.
WRITE: / 'Начальная дата:', l_stdate,
/ '+', l_count, 'месяцев',
/ 'Конечная дата:', l_eddate.
* Позволяет получить следующее время и дату путем добавления часов, минут и секунд. На вход передаем дату и время, например текущие и время в формате HHMMSS, которое нужно добавить. На выходе получаем новую дату и время:
DATA: l_uzeit LIKE sy-datum,
l_uzeit LIKE sy-uzeit.
CALL FUNCTION 'DIMP_ADD_TIME'
EXPORTING
iv_starttime = sy-uzeit
iv_startdate = sy-datum
iv_addtime = '000001'
IMPORTING
ev_endtime = l_uzeit
ev_enddate = l_erdat.
* Данная функция позволяет получить код/номер периода для заданной даты. В общем виде для варианта финансового года К4, данная задача не является проблемной, номер месяца и есть номер периода, но стандартно в системе могут быть созданы различные варианты финансовых периодов, в банках любят обычно использовать вариант типа 365 периодов в году. Самый простой случай - это работа с кварталом:
DATA: l_period LIKE t009-anzbp,
l_year LIKE t009b-bdatj.
CALL FUNCTION 'DETERMINE_PERIOD'
EXPORTING
date = sy-datum
* PERIOD_IN = '00'
version = 'Q1' "Вариант финансового года (кварталы)
IMPORTING
period = l_period
year = l_year
EXCEPTIONS
period_in_not_valid = 1
period_not_assigned = 2
version_undefined = 3
OTHERS = 4.
Переменная PERIOD_IN используется для определения существования особых периодов для варианта финансового года. Правда работает она только в случае если дата задана для последнего возможного периода в варианте года, тогда например для вариант К4, обычно 12 периодов + 4 особых периода, при вызове для любой из дат в диапазоне 01.12 по 31.12 и задании например PERIOD_IN = 18 система будет выдавать ошибку, особый период не существует, если же вызвать с PERIOD_IN = 13, ошибки не будет.
* Возвращает дату начала и конца квартала, в который входит переданная дата:
DATA: l_start LIKE sy-tabix,
l_end LIKE sy-tabix.
CALL FUNCTION 'ISH_QUARTER_GET'
EXPORTING
ss_date = sy-datum
IMPORTING
ss_begin = l_start
ss_end = l_end
EXCEPTIONS
error = 1
wrong_date = 2
OTHERS = 3.
Например для даты 15.09.2012 вернет значения:
Begin: 01.07.2012, End: 30.09.2012.
Begin: 01.07.2012, End: 30.09.2012.
* Возвращает для заданной даты, номер дня в неделе и название дня недели. Название дня в неделе выполняется путем вывода текстовой константы на английском и большими буквами:
DATA: l_day LIKE scal-indicator,
l_weekday TYPE sc_day_txt.
CALL FUNCTION 'DATE_COMPUTE_DAY_ENHANCED'
EXPORTING
date = sy-datum
IMPORTING
day = l_day
weekday = l_weekday.
WRITE: / 'Номер дня в неделе:', l_day, 'День недели:', l_weekday.
Data: l_year_of_valid_from LIKE scal-year,
l_year_of_valid_to LIKE scal-year,
l_returncode LIKE sy-subrc,
l_date_from LIKE scal-date,
l_date_to LIKE scal-date,
lt_day_attributes LIKE casdayattr OCCURS 1 WITH HEADER LINE.
l_date_from = '20130101'.
l_date_to = '20130104'.
CALL FUNCTION 'DAY_ATTRIBUTES_GET'
EXPORTING
* FACTORY_CALENDAR = ' '
* HOLIDAY_CALENDAR = ' '
date_from = l_date_from
date_to = l_date_to
language = sy-langu
non_iso = ' '
IMPORTING
year_of_valid_from = l_year_of_valid_from
year_of_valid_to = l_year_of_valid_to
returncode = l_returncode
TABLES
day_attributes = lt_day_attributes
EXCEPTIONS
factory_calendar_not_found = 1
holiday_calendar_not_found = 2
date_has_invalid_format = 3
date_inconsistency = 4
OTHERS = 5.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
Пример таблицы результата:
* Возвращает кол-во лет, месяцев, дней между 2-мя датами.
Для точности отнять от даты окончания один день
t_date = t_date - 1.
CALL FUNCTION 'HR_HK_DIFF_BT_2_DATES'
EXPORTING
date1 = t_date
date2 = t_dat01
output_format = '05'
IMPORTING
years = years
months = months
days = days
EXCEPTIONS
invalid_dates_specified = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
*****
ОтветитьУдалитьISH_QUARTER_GET - Его больше нет в sap
ОтветитьУдалить