Every so often a developer needs to involve code related to dates in their work. I have come across some "interesting" and "creative" approaches to this which might work under some conditions, but do provide a risk. Let's talk dates in ABAP. I'll explain how they work, common mistakes and my suggestion for consistent handling... Please let me know if you have other suggestions!
(This is a blog post I originally posted on LinkedIn a while back, but obviously this is where it belongs.)
There is a predefined data type DATS which you declare just as you would expect:
DATA lv_date type dats.
To assign it the value of todays date, which always is available in the sy-datum field:
lv_date = sy-datum.
The type dats is a character type field formatted as YYYYMMDD. This means that you can also assign a specific date using this format, like so:
lv_date = '20190329'.
There is also some additional functionality using this datatype compared to using just any 8 characters, in that you can add or subtract a number of days to the date and it will still be consistent:
The first addition will give lv_date = 20160229 and the next one lv_date = 20160301
Year, month and day
The simplest way to separate year, month or day from a date is to use the offset and length specifications to specify only a section of the date. This is possible as the date type is a character type field.
By adding an offset using plus-sign and a number, like +4, the starting position of the section is defined.
By adding a length using a number in parantheses, like (2), the length of the section is defined.
Since the internal formatting of the date is YYYYMMDD, the sections are as follows:
The "day section" starts at offset 6 and is 2 characters long. (YYYYMMDD).
The "month section" starts at offset 4 and is 2 characters long. (YYYYMMDD).
The "year section" starts at the beginning, i.e. offset 0, and is 4 characters long. (YYYYMMDD).
lv_day will be '29', lv_month '03' and lv_year '2019'. Note that for the year, since the offset is 0 it can be omitted in the code.
How about changing the date?
Ok, so far so good. This works just fine. But now we get to the risky business I've seen people attempt. We can also use offset and length at the LHS (left hand side) of the assignment operaion. This means manipulating only a section of the date. This comes in handy and quite useful at many times, but will be quite a risk when it comes to dates.
So lets change the month:
lv_date = '20190329'.
lv_date+4(2) = '05'.
Setting the "month section" to 05 results, correctly, in lv_date = 20190529.
We can also use offset and length on both sides of the assignment operation:
Results in lv_date = 20190431. And since april only has 30 days, we're screwed again. And then there is february with it's 28 days and the leap years. Fully possible to fix it all, of course, but there are a couple of considerations to make.
I've seen some close-enough solutions, like considering a month to be 30 days, and simply adding 30 days to the entire date for each month, like so:
Results in lv_date = 20240327. 2 days missing again, this time due to leap years in 2020 and 2024.
So what do we do?
Enter class cl_reca_date. This is a neat class for doing almost anything date-related. In addition to not having to think about all the odds and ends, using this class will also yield a code that is a lot more readable and easier to understand and maintain. And that is more important than one might think.
Let's try it out using the last example above, adding 5 years to 20190329:
IF cl_reca_date=>is_date_ok( lv_date ).
" Date is ok
" No can do
To summarize, ABAP has a somewhat powerful built-in date datatype, but it's easy to get lost in the details when more than adding days is needed. The class cl_reca_date is my go-to for anything date-related and is what I keep recommending to colleagues as well.
There are more methods than I gave examples of here, including calculating with business calendar, intersections, weekdays, periods, and so on, etc. I am not going to provide examples for every one of them but I recommend you check them out next time you need to work with dates, if you haven't already.
Happy dating! Stay safe! And please let me know If you have other suggestions!