Often, a seemingly small and simple task is actually a little bigger, the more and deeper you think of it, you sure have experienced this as well. Here's an example:
Task: Select something from the
last 24 hours (e.g. sales orders (VBAK) maybe to see the turnover in $ in the last 24h hours, or how many units of Product X have been produced per plant )
So, we need to calculate the "target" date and time -> 24 hours in the past.
1.st approach:
data(lv_target_date) = sy-datum - 1.
data(lv_target_time) = sy-uzeit.
simple.
But we probably want 24hours back from the users "
definition of now", not from the system-time (yeah, they might be different, if user and server are in different timezones), so better use sy-datlo + sy-timlo:
data(lv_target_date) = sy-datlo - 1.
data(lv_target_time) = sy-timlo.
Now the following was not explicitly stated, but implicitly it is: If "today" is a Monday, we would want to look back as far as Friday ('cause there's not turnover/production/... at the weekend - well, unless we have online sales, but that's another story.)
So, things are clear: we have to take the
factory calendar into account.
SELECT SINGLE fabkl FROM t001w INTO data(lv_factory_calendar)
WHERE werks = iv_werks.
*if there is no factory calendar, we're fine with what we already calculated!
CHECK sy-subrc EQ 0.
CHECK lv_factory_calendar IS NOT INITIAL.
CALL FUNCTION 'DATE_CONVERT_TO_FACTORYDATE'
EXPORTING
correct_option = '-'
date = lv_target_date
factory_calendar_id = lv_factory_calendar
IMPORTING
date = lv_target_date
* factorydate =
* 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.
IF sy-subrc <> 0.
*doesn't matter.
ENDIF.
What does it do: if what we calculated as lv_target_day in the first step is NOT a working day, go as far back, until you hit a working day.
That’s what I wanted to say about the date part, but I also have
one for the time:
If it's
March, 28th (this year, 2018),
8 O'clock in the morning, what's the target if we go 24h back? Well: March, 27th,
7 O’clock in the morning! That's right, at least if we are in a timezone which switched to
daylight-saving-time: the hour between 2 and 3 didn't exist that night!
I have no solution to that, I think this can or at least should not be coded by hand. I would hope + guess that
there's a library somewhere, which takes care of exactly those things I mentioned here. If you know it, please share in the comments.
Let me end with a nice blog I read a few years ago and now went searching for again:
http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time
( If you like it, you probably like this one about names as well:
https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/ )
Also, to link to a currently
trending topic: you probably can and should write #unit-tests for those edge-cases displayed here.
Over to you:
- Do you see
other problems not yet addressed here?
- Do you know
the library (e.g. ABAP-Class) that helps me with all the time-handling
- I guess there should be a
more modern way (ABAP-Class) for "CALL FUNCTION 'DATE_CONVERT_TO_FACTORYDATE'" , do you know it?
- would you have fallen for one of the ‘
traps’ I mentioned here, where they all obvious to you?
This and other input is most welcome!
best
Joachim