## Quarter calculation

115 pts.
Tags:
IBM iSeries
iSeries RPG programming
RPG IV
I have a fiscal calendar that runs from March to February. I need to be able to calculate the quarter number and determine the months that compose that quarter. Doing all of this with out prompting the user.

Thanks. We'll let you know when a new response is added.

Going by the information you provided, I would probably set up a physical file that contains the month and the quarter the month falls in. I would then create a logical file over the physical keyed by quarter number. Then in the program, retrieve the current month and chain to the physical file and get the quarter. From there I would do a reade of the logical file to get all of the months that make up that quarter.

I realize that this way causes you to read the same file twice, but you are only talking about 12 records.

You could replace the file with an array, but I think that a file would offer more flexibility.

////////////////////////
A file would be good here. the File calendar contains fields catm, caqtr, camo1, camo2, and camo3.
Field catm (this month) is the file key – and I “cheated” by putting three fields in the record
for the months in this quarter.

d thisMonth s 2 0
d quarter s 1 0
D month s 2 0 dim(3)

C eval thisMonth = %subdt(%date():*m )
C thisMonath chain calendar
C if %found(calendar)
C eval quarter = caqtr
C eval month(1) = camo1
C eval month(2) = camo2
C eval month(3) = cam03
C else
C ————- error !!!
C endif

— here is an alternative without a file.

d monthDs
d
d thisMonth s 2 0
d quarter s 1 0
D month s 2 0 dim(3)
C eval thisMonth = %subdt(%date():*m )

C select
C when thisMonth = 3 or
C thisMonth = 4 or
C thisMonth = 5
C eval quarter = 1
C eval month(1) = 3
C eval month(2) = 4
C eval month(3) = 5

C when thisMonth = 6 or
C thisMonth = 7 or
C thisMonth = 8

C when thisMonth = 9 or
C thisMonth = 10 or
C thisMonth = 11
C eval quarter = 3
C eval month(1) = 9
C eval month(2) = 10
C eval month(3) = 11

C when thisMonth = 12 or
C thisMonth = 01 or
C thisMonth = 02
C eval quarter = 4
C eval month(1) = 12
C eval month(2) = 01
C eval month(3) = 02

C endsl

Phil

**************
To just get your fiscal quarter in which a month falls, you could also do a calculation similar to this:

D Month S 2S 0
D Quarter S 1S 0

Month = %SubDt( %Date( ): *Months);
Quarter = %Int(Month) / 3;
IF Quarter <= 0;
Quarter = 4;
ENDIF;

CWC
****************

## Discuss This Question: 8 Replies

Thanks. We'll let you know when a new response is added.
• We had the same requirement and chose the file option. This eliminated coding the same routine over and over in many programs. Of course, in the ILE environment a single service program could take care of it. There were some other benefits from the file method. One is that we can join a detail file to the calendar file in queries and have all the dates we need. It also works in SQL statements where you need to select all transactions for 2008, quarter 2. Our RPG program to generate the file is about 100 lines. Just code the date requirements of your company into this one program and let it generate all the date records you need.
report
• I've always thought the file answer to this question is deeply suspect. Someone says ' it's 2 file accesses' - yet if you're processing 5 million records its a loong time. - so you would create an array in the program - that's a routine to preload the array and look up the answers, and you need a routine to get the date if it isn't in the array, or for when its an interactive one off access. Surely it's not beyond the wit of man to produce an algorithm which will return the answer from any given date. It becomes an ILE service, or an RPG/400 /copy member. SQL - the Stupid Query Language, struggles unless it has a file, so the file route is attractive because it makes a query simple - but it costs in DB i/o - that 10 million i/os will be happening, but where you can't see it. Take the pain now, make the algorithm, wrap it with a procedure interface and build a stored procedure for date values in queries. You'll feel better for doing it.
report
• I agree that preventing unnecessary disk I/O is important. I have a GetQuarter procedure in a service program, which returns a calendar quarter. I was intrigued when I ran across this question, thought about how my method could be modified to return a fiscal quarter, and arrived at the snippet below. But I couldn't think of a calculation to determine which months make up their fiscal quarter, as was also needed. Other than hard coding the month ranges that belong to each quarter, does anyone have a better way? P GetQuarter B D PI 1S 0 D Date 8S 0 D Error N D Month S 2S 0 D Quarter S 1S 0 D DateTimeStamp C CONST(0112) D DecimalData C CONST(0907) /Free MONITOR; Month = %SubDt( %Date(Date): *Months); Quarter = %Int(Month) / 3; IF Quarter <= 0; Quarter = 4; ENDIF; ON-ERROR DateTimeStamp : DecimalData; Error = *On; ENDMON; RETURN Quarter; /End-Free P GetQuarter E
report
• Nicely done. You've raised the trickiest part of the solution - to provide the base date. Every organisation has its own calendar. At it's simplest, its the financial year start date - January 1st, April 1st , April 6th, September, blah blah.. and whilst unusual, its nevertheless possible for this to change - a takeover makes a subsidiary fall in line with the new owner etc. So, how to provide an 'almost constant' at nil CPU /DB cost? A data area would be the simplest start point - but wait - that means a rtv for evey iteration. Not good. well - do the rtv, populate the variable, and only rtv if not populated. There's a good chance the function will remain resident for a long time or - make the caller tell you - add to the parameters a field for 'basis' and provide some deafaults in the function - if no incoming value, use (pick one) Financial year / calendar year - I think this could be acceptable, as any future change would involve only the one change to the one function. If the user wants to use another date, they can do so, and the function will cope
report
• Looks like I  had it  easy.
Accounts  told us to run the job quarterly on Month 1, 4, 7 and 10 . I ran the job every month ( on the 1st of the month as accounts required) , then in the CL

RTVSYSVAL  SYSVAL(QMONTH) RTNVAR(&SYSMONTH)

IF         COND(&SYSMONTH = '1' *OR &SYSMONTH = '4' *OR +
&SYSMONTH = '7' *OR &SYSMONTH = '10') +
THEN(GOTO CMDLBL(RUNIT))
ELSE GOTO end

;)
report
• Place I used to work had 4 and 5 week months that never corresponded to the 1st of the month. Always started on a Monday. While it was normal if a month was 5 weeks in one year, it was most years, but not every year.  We had a calendar with every date of the year and which fiscal week (of month, quarter and year), fiscal month, fiscal quarter and fiscal year (Year end was typically the Monday before Christmas).  Never know what you might run into when it comes to fiscal dates. I know some companies run a 13 period fiscal year (not sure how that works into quarters).