Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
joachimrees1
Active Contributor
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
11 Comments