Meetup in Cobol: Complete Solution & Deep Dive Guide

Code Debug

Mastering Cobol Date Logic: The Complete Guide to Solving the Meetup Problem

Learn to calculate the exact date of a meetup in Cobol by handling complex week descriptors like 'first', 'last', and 'teenth'. This guide breaks down the logic using intrinsic functions and structured programming to solve this common date manipulation challenge efficiently, a crucial skill for any mainframe developer.

Ever found yourself staring at a terminal, tasked with generating a report for "the third Tuesday of every month" on a system older than you are? Date and time calculations, a trivial task in modern languages with feature-rich libraries, can feel like a cryptic puzzle in the world of Cobol. The rigid structure and verbose syntax often leave developers wrestling with complex calendar logic, especially when dealing with non-standard requirements.

This isn't just an academic exercise; it's a reflection of real-world challenges in banking, insurance, and public sector systems where Cobol is the unwavering backbone. The ability to accurately schedule events, calculate policy renewal dates, or generate financial statements on specific recurring days is mission-critical. This guide will transform your frustration into confidence. We will dissect the "Meetup" problem from the exclusive kodikra.com curriculum, providing a clear, step-by-step pathway to building a robust and elegant Cobol solution from scratch.


What is the Meetup Date Problem in Cobol?

At its core, the Meetup problem challenges a developer to pinpoint a precise calendar date based on a set of relative, human-readable instructions. Instead of being given a simple date like "2023-10-26", you receive a query that mimics how people schedule events in real life.

The inputs for the program are always:

  • Year: A four-digit year (e.g., 2021).
  • Month: A number from 1 (January) to 12 (December).
  • Day of the Week: The target weekday (e.g., 'Monday', 'Tuesday').
  • Week Descriptor: A special term that specifies which occurrence of the weekday to find within the month.

The challenge lies entirely in interpreting the Week Descriptor. This is not a simple numerical week (like week 1 or week 2). Instead, it uses one of the following specific terms:

  • 'first': The first occurrence of the target weekday in the month.
  • 'second': The second occurrence of the target weekday.
  • 'third': The third occurrence of the target weekday.
  • 'fourth': The fourth occurrence of the target weekday.
  • 'last': The final occurrence of the target weekday in the month.
  • 'teenth': The one and only occurrence of the target weekday that falls on a day between the 13th and the 19th, inclusive.

For example, a request for the "third Tuesday of August 2019" should correctly resolve to August 20, 2019. A request for the "teenth Wednesday of May 2020" should resolve to May 13, 2020. The program must contain the logic to parse these descriptors and perform the necessary calendar arithmetic to return the single, correct date.


Why is Date Calculation in Cobol a Unique Challenge?

To understand the "how," we must first appreciate the "why." Why does a seemingly simple task require such careful consideration in Cobol? The answer lies in the language's history and design philosophy. Cobol (COmmon Business-Oriented Language) was born in 1959, an era long before the convenience of modern date-time APIs like Python's datetime or Java's java.time.

The Era of Intrinsic Functions

Cobol was designed for data processing, not for the kind of object-oriented, library-driven development we see today. Consequently, it relies heavily on built-in capabilities known as intrinsic functions. These are powerful, but they operate on a lower level. For date manipulation, we don't have a "Calendar" object to query; instead, we have mathematical-style functions that convert dates to and from integer representations.

The key functions we'll leverage are:

  • FUNCTION INTEGER-OF-DATE(YYYYMMDD): This function takes a standard date in YYYYMMDD format and converts it into a sequential integer. This integer represents the number of days that have passed since a fixed point in the past (often December 31, 1600). This is crucial because it turns calendar logic into simple arithmetic.
  • FUNCTION DATE-OF-INTEGER(integer): This is the inverse of the above. It takes a sequential integer and converts it back into a standard YYYYMMDD date format.
  • FUNCTION DAY-OF-WEEK(YYYYMMDD): This function takes a standard date and returns an integer from 1 to 7, where 1 represents Monday, 2 represents Tuesday, and so on, up to 7 for Sunday. This is the cornerstone of finding our target weekday.

The challenge, therefore, is not a lack of tools, but the need to manually orchestrate these functions to build the complex logic required by the Meetup problem. You are the architect of the calendar logic, not just a consumer of a pre-built library.

Handling Leap Years and Month Lengths

A significant advantage of using these intrinsic functions is that they automatically handle the complexities of the Gregorian calendar. Leap years, the varying number of days in each month (30, 31, 28, or 29)—all of this is abstracted away. When you call INTEGER-OF-DATE, you don't need to worry if February has 28 or 29 days; the function knows. This built-in reliability is a major reason why Cobol remains a stalwart in mission-critical systems.


How to Design the Cobol Solution: The Core Logic

Solving the Meetup problem requires a structured, methodical approach. We can't just guess dates; we need an algorithm that works for any combination of inputs. Our strategy will be to establish a starting point and then iterate or calculate forward to find the target date.

High-Level Algorithm Flow

Our overall plan can be visualized as a clear, sequential process. We take the raw inputs, find a logical anchor point (the first day of the month), and then apply the specific logic for each week descriptor to arrive at the final date.

    ● Start (Receive Year, Month, Week, DayOfWeek)
    │
    ▼
  ┌───────────────────────────┐
  │ Construct Date for the    │
  │ 1st of the Month          │
  │ (e.g., YYYYMM01)          │
  └────────────┬──────────────┘
               │
               ▼
  ┌───────────────────────────┐
  │ Use DAY-OF-WEEK to find   │
  │ which day the 1st falls on│
  └────────────┬──────────────┘
               │
               ▼
    ◆ Evaluate Week Descriptor?
   ╱     │      │      │      ╲
'first' 'nth' 'teenth' 'last'  [Error]
  │      │      │      │
  ▼      ▼      ▼      ▼
[Find   [Calc.  [Find   [Find
 1st]    Nth]   Teenth] Last]
  │      │      │      │
  └──────┼──────┼──────┘
         │
         ▼
  ┌───────────────────────────┐
  │ Calculate Final Date      │
  │ (YYYYMMDD)                │
  └────────────┬──────────────┘
               │
               ▼
    ● End (Return Date)

Step 1: Find the First Occurrence of the Target Weekday

Everything starts with finding the very first instance of our target day (e.g., the first Tuesday) in the given month. This becomes our base for all other calculations.

  1. Create a date for the first day of the month (e.g., for August 2019, this is 20190801).
  2. Use FUNCTION DAY-OF-WEEK(20190801) to find out what day it is. Let's say it returns 4 (Thursday).
  3. Our target is Tuesday (day 2). We calculate the difference: TargetDay (2) - StartDay (4) = -2.
  4. If the result is negative, it means our target day occurred in the previous week. We adjust by adding 7: -2 + 7 = 5. This means the first Tuesday is 5 days after the first Thursday.
  5. The date of the first Tuesday is the 1st + 5 days, which is the 6th. So, the first Tuesday of August 2019 is August 6th.

This initial calculation gives us a solid foundation. For the 'first' descriptor, our job is already done. For others, we build upon this result.

Step 2: Handling 'second', 'third', and 'fourth'

This is the most straightforward part. Once we have the date of the first occurrence, we can find subsequent occurrences by simply adding multiples of 7 days.

  • Second: Date of first occurrence + 7 days.
  • Third: Date of first occurrence + 14 days (or 2 * 7).
  • Fourth: Date of first occurrence + 21 days (or 3 * 7).

Step 3: The 'teenth' Logic Explained

The 'teenth' descriptor is unique. It refers to the days from the 13th to the 19th. There will always be exactly one of each weekday within this seven-day span. Our task is to find our target day within this specific window.

The simplest algorithm is to start at the 13th of the month and check the day of the week for each day until we find a match.

    ● Start (Know Target DayOfWeek)
    │
    ▼
  ┌──────────────────────────┐
  │ Set SearchDate = 13th of │
  │ the given Month/Year     │
  └────────────┬─────────────┘
               │
               ▼
    ◆ DAY-OF-WEEK(SearchDate) == TargetDay?
   ╱           ╲
  Yes           No
  │              │
  ▼              ▼
[Date Found!]  ┌───────────────────┐
  │            │ Increment         │
  └─────┐      │ SearchDate by 1   │
        │      └─────────┬─────────┘
        │                │
        └────────────────┼─────────► Loop (Max 6 times)
                         │
                         ▼
                    ● End (Return Found Date)

Step 4: Conquering the 'last' Descriptor

Finding the 'last' occurrence of a weekday is the trickiest. A naive approach might be to find the fourth occurrence and then add 7, but that might push the date into the next month. A robust method involves looking ahead.

  1. Calculate the date of the first occurrence of the target weekday in the month (as we did in Step 1). Let's call this FirstDate.
  2. Start with LastDate = FirstDate.
  3. Enter a loop: repeatedly add 7 to LastDate.
  4. Inside the loop, check if the new LastDate is still in the same month as the original input.
  5. If adding 7 pushes the date into the next month, then the previous value of LastDate was the correct one. Exit the loop and return it.

This forward-checking method is safe and reliable, as it doesn't require knowing the number of days in the month beforehand. The Cobol intrinsic functions handle all the calendar complexities for us.


The Complete Cobol Solution Code

Below is a full, working Cobol program that implements the logic described above. This solution, part of the exclusive kodikra.com Cobol curriculum, is designed for clarity and adherence to structured programming principles.


       IDENTIFICATION DIVISION.
       PROGRAM-ID. MEETUP.
       AUTHOR. Kodikra.

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
           FUNCTION ALL INTRINSIC.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-INPUT-DATA.
          05 WS-YEAR              PIC 9(04).
          05 WS-MONTH             PIC 9(02).
          05 WS-WEEK-DESCRIPTOR   PIC X(08).
          05 WS-DAY-OF-WEEK-NAME  PIC X(08).

       01 WS-CALCULATION-VARS.
          05 WS-TARGET-DOW-NUM    PIC 9(01).
          05 WS-FIRST-OF-MONTH-DOW PIC 9(01).
          05 WS-FIRST-TARGET-DAY  PIC 9(02).
          05 WS-RESULT-DAY        PIC 9(02).
          05 WS-TEMP-DATE         PIC 9(08).
          05 WS-TEMP-DATE-INT     PIC 9(08).
          05 WS-COUNTER           PIC 9(01).

       01 WS-OUTPUT-DATE.
          05 WS-RESULT-YEAR       PIC 9(04).
          05 WS-RESULT-MONTH      PIC 9(02).
          05 WS-RESULT-DAY-OUT    PIC 9(02).

       PROCEDURE DIVISION USING WS-INPUT-DATA, WS-OUTPUT-DATE.
       MAIN-LOGIC.
           PERFORM INITIALIZE-VARIABLES.
           PERFORM CONVERT-DAY-NAME-TO-NUM.
           PERFORM CALCULATE-MEETUP-DATE.
           PERFORM FORMAT-OUTPUT.
           GOBACK.

       INITIALIZE-VARIABLES.
           MOVE 0 TO WS-RESULT-DAY.
           MOVE 0 TO WS-COUNTER.

       CONVERT-DAY-NAME-TO-NUM.
      *    Cobol's DAY-OF-WEEK: 1=Monday, 2=Tuesday, ..., 7=Sunday
           EVALUATE WS-DAY-OF-WEEK-NAME
               WHEN 'MONDAY'    MOVE 1 TO WS-TARGET-DOW-NUM
               WHEN 'TUESDAY'   MOVE 2 TO WS-TARGET-DOW-NUM
               WHEN 'WEDNESDAY' MOVE 3 TO WS-TARGET-DOW-NUM
               WHEN 'THURSDAY'  MOVE 4 TO WS-TARGET-DOW-NUM
               WHEN 'FRIDAY'    MOVE 5 TO WS-TARGET-DOW-NUM
               WHEN 'SATURDAY'  MOVE 6 TO WS-TARGET-DOW-NUM
               WHEN 'SUNDAY'    MOVE 7 TO WS-TARGET-DOW-NUM
           END-EVALUATE.

       CALCULATE-MEETUP-DATE.
      *    Find the day of the week for the 1st of the month
           COMPUTE WS-TEMP-DATE = (WS-YEAR * 10000) + (WS-MONTH * 100) + 1.
           COMPUTE WS-FIRST-OF-MONTH-DOW = DAY-OF-WEEK(WS-TEMP-DATE).

      *    Calculate the date of the first occurrence of the target day
           COMPUTE WS-FIRST-TARGET-DAY =
               1 + WS-TARGET-DOW-NUM - WS-FIRST-OF-MONTH-DOW.
           IF WS-FIRST-TARGET-DAY <= 0
               ADD 7 TO WS-FIRST-TARGET-DAY
           END-IF.

      *    Evaluate the week descriptor to find the final date
           EVALUATE WS-WEEK-DESCRIPTOR
               WHEN 'FIRST'
                   MOVE WS-FIRST-TARGET-DAY TO WS-RESULT-DAY
               WHEN 'SECOND'
                   COMPUTE WS-RESULT-DAY = WS-FIRST-TARGET-DAY + 7
               WHEN 'THIRD'
                   COMPUTE WS-RESULT-DAY = WS-FIRST-TARGET-DAY + 14
               WHEN 'FOURTH'
                   COMPUTE WS-RESULT-DAY = WS-FIRST-TARGET-DAY + 21
               WHEN 'TEENTH'
                   PERFORM FIND-TEENTH-DAY
               WHEN 'LAST'
                   PERFORM FIND-LAST-DAY
           END-EVALUATE.

       FIND-TEENTH-DAY.
      *    The 'teenth' day is the one between the 13th and 19th.
           MOVE 13 TO WS-RESULT-DAY.
           PERFORM UNTIL WS-COUNTER > 7
               COMPUTE WS-TEMP-DATE = (WS-YEAR * 10000)
                                    + (WS-MONTH * 100)
                                    + WS-RESULT-DAY
               IF DAY-OF-WEEK(WS-TEMP-DATE) = WS-TARGET-DOW-NUM
                   EXIT PERFORM
               END-IF
               ADD 1 TO WS-RESULT-DAY
               ADD 1 TO WS-COUNTER
           END-PERFORM.

       FIND-LAST-DAY.
      *    Start with the first occurrence and keep adding 7
      *    until the next jump would go into the next month.
           MOVE WS-FIRST-TARGET-DAY TO WS-RESULT-DAY.
           PERFORM UNTIL 1 = 0
               COMPUTE WS-TEMP-DATE-INT = INTEGER-OF-DATE(
                   (WS-YEAR * 10000) + (WS-MONTH * 100) + WS-RESULT-DAY
               )
               ADD 7 TO WS-TEMP-DATE-INT
               COMPUTE WS-TEMP-DATE = DATE-OF-INTEGER(WS-TEMP-DATE-INT)
               
               IF WS-MONTH NOT = WS-TEMP-DATE(5:2)
                   EXIT PERFORM
               END-IF
               
               ADD 7 TO WS-RESULT-DAY
           END-PERFORM.

       FORMAT-OUTPUT.
           MOVE WS-YEAR TO WS-RESULT-YEAR.
           MOVE WS-MONTH TO WS-RESULT-MONTH.
           MOVE WS-RESULT-DAY TO WS-RESULT-DAY-OUT.


Detailed Code Walkthrough

Let's break down the Cobol program into its constituent parts to understand how each piece contributes to the final solution.

IDENTIFICATION and ENVIRONMENT DIVISION

This is standard Cobol boilerplate. PROGRAM-ID. MEETUP. gives our program a name. The REPOSITORY paragraph is crucial; it tells the compiler that we intend to use INTRINSIC functions like DAY-OF-WEEK, allowing it to link the necessary functionality.

DATA DIVISION - Defining Our Variables

The WORKING-STORAGE SECTION is where we declare all the variables our program will use. They are grouped logically:

  • WS-INPUT-DATA: This group item receives the parameters passed to the program: year, month, and the string descriptors for the week and day.
  • WS-CALCULATION-VARS: These are our "scratchpad" variables. WS-TARGET-DOW-NUM will hold the numeric version of the day (1-7). WS-FIRST-TARGET-DAY stores the calculated day of the first occurrence. WS-TEMP-DATE is used repeatedly to build date values for function calls.
  • WS-OUTPUT-DATE: This structure holds the final result that will be passed back to the calling program.

PROCEDURE DIVISION - The Program's Logic

This is where the execution happens. The logic is organized into paragraphs (similar to functions or methods in other languages) for clarity and reusability.

MAIN-LOGIC
This is the main driver of the program. It orchestrates the calls to other paragraphs in a specific order: initialize, convert inputs, perform the main calculation, format the output, and then stop execution with GOBACK.

CONVERT-DAY-NAME-TO-NUM
Computers work better with numbers than with strings. This paragraph uses an EVALUATE statement (Cobol's version of a switch/case) to convert the input string like 'MONDAY' into the corresponding numeric value (1) that the DAY-OF-WEEK function expects. This standardization is a critical first step.

CALCULATE-MEETUP-DATE
This is the heart of the program.

  1. First, it constructs a date for the 1st of the month (YYYYMM01) and calls DAY-OF-WEEK to find out which day it landed on.
  2. Next, it performs the crucial calculation to find the date of the first occurrence of our target day. The formula 1 + TargetDayNum - FirstOfMonthDayNum is the key. The IF statement handles the case where the target day is "before" the first day of the month in the week (e.g., if the 1st is a Thursday and we want a Tuesday), requiring us to add 7 to wrap around to the correct first occurrence.
  3. Finally, another EVALUATE statement directs the program flow based on the WS-WEEK-DESCRIPTOR. Simple cases like 'SECOND' or 'THIRD' perform direct arithmetic, while 'TEENTH' and 'LAST' call their own dedicated logic paragraphs.

FIND-TEENTH-DAY
This paragraph implements the "teenth" logic. It initializes a loop starting with the 13th day. In each iteration, it checks if the day of the week for the current date matches our target. If it does, the loop terminates. If not, it increments the day and tries again, guaranteeing a find within the 13th-19th window.

FIND-LAST-DAY
This paragraph uses the robust forward-checking method. It starts with the date of the first occurrence. The PERFORM UNTIL 1 = 0 creates an infinite loop that we must explicitly break out of. Inside, it calculates what the date would be in 7 days using integer arithmetic, which is very efficient. It then converts this integer back to a date and checks if the month of the new date is different from our starting month. If the month has changed, it means we've crossed the boundary, so the previous value was the last one, and we EXIT PERFORM. Otherwise, it updates the result and continues the loop.


Where is this Logic Applied in Real-World Scenarios?

This problem, while part of the kodikra learning path module, is far from a purely academic exercise. The logic for calculating recurring dates is fundamental to countless business operations running on mainframe systems today.

  • Financial Services: Calculating settlement dates for trades that occur on the "third Friday of the month" (a common options expiration day). Scheduling monthly or quarterly statement generation for millions of bank accounts.
  • Insurance: Determining policy renewal dates or premium due dates that fall on a specific business day of the month.
  • Government & Payroll: Scheduling pension disbursements or social security payments, which are often tied to specific Wednesdays of the month.
  • Batch Processing: Many critical nightly or weekly batch jobs on mainframes are scheduled based on rules like "run on the first business day after the 15th" or "run on the last Sunday of the quarter." The core logic is identical.

Mastering this type of date manipulation in Cobol is a highly practical and valuable skill for anyone working with or maintaining these critical legacy systems.


Pros and Cons of the Cobol Approach

Every programming language and approach has its trade-offs. The Cobol solution for the Meetup problem is no exception. Understanding its strengths and weaknesses provides a more complete picture.

Pros (Advantages) Cons (Disadvantages)
Extremely Explicit and Readable: The verbose nature of Cobol means the logic, once written, is very clear. There is little ambiguity in statements like ADD 7 TO WS-RESULT-DAY. Verbosity and Boilerplate: Writing the solution requires significantly more lines of code compared to a modern language like Python or JavaScript.
High Reliability: The intrinsic functions for date handling are battle-tested over decades. They correctly manage all calendar rules, including leap years, without any external dependencies. Manual Logic Construction: The developer is responsible for building all the higher-level logic from primitive functions. There is no "Calendar" object with a .findLast('tuesday') method.
Performance: Compiled Cobol code is highly optimized for the mainframe environment and executes very efficiently for this type of data manipulation. Steeper Learning Curve for Newcomers: The rigid divisions, fixed-format nature (in older styles), and lack of modern language features can be intimidating for developers accustomed to other paradigms.
No External Dependencies: The entire solution is self-contained. It relies only on the core language features, which makes it portable across any standard Cobol compiler and environment. Potential for Off-by-One Errors: Manual calculations, especially with day-of-week numbers (is Sunday 0 or 7?), require careful attention to detail to avoid logical errors.

Frequently Asked Questions (FAQ)

1. What exactly is a 'teenth' day?

The term 'teenth' is a colloquialism for the days in a month that end with "-teenth": thirteenth, fourteenth, fifteenth, sixteenth, seventeenth, eighteenth, and nineteenth. This seven-day window (from the 13th to the 19th) will always contain exactly one of every day of the week (one Monday, one Tuesday, etc.). The challenge is to find the specific one you're looking for.

2. Why not just use a modern library for this in Cobol?

The Cobol ecosystem is fundamentally different from modern development environments. While some third-party libraries and tools exist, the culture and design philosophy of mainframe development prioritizes stability, self-reliance, and minimal external dependencies. Using the built-in intrinsic functions is the standard, most portable, and most reliable method, ensuring the code will run on any compliant mainframe system without installation hassles.

3. How does FUNCTION DAY-OF-WEEK work in Cobol?

The ANSI Cobol standard defines the return value of FUNCTION DAY-OF-WEEK as an integer representing the day, where 1 is Monday, 2 is Tuesday, 3 is Wednesday, 4 is Thursday, 5 is Friday, 6 is Saturday, and 7 is Sunday. This is a critical detail to remember, as other languages or systems might start the week on Sunday or use 0-based indexing.

4. Can this logic handle leap years correctly?

Absolutely. This is one of the biggest advantages of using Cobol's intrinsic functions. Functions like INTEGER-OF-DATE and DATE-OF-INTEGER have the entire Gregorian calendar logic, including all leap year rules, built into them. When you ask for the date of the integer that corresponds to February 29th in a leap year, it will give it to you correctly. You do not need to write any special code to check for leap years.

5. What are common pitfalls when working with dates in Cobol?

The most common pitfalls include off-by-one errors with day-of-week calculations (forgetting if Monday is 1 or 0), incorrect date formats passed to functions (they usually expect YYYYMMDD), and logical errors when crossing month or year boundaries. The "last day" logic is particularly prone to bugs if not handled carefully with a method like the forward-checking algorithm shown in our solution.

6. Is Cobol still relevant for these kinds of tasks?

Yes, unequivocally. Billions of lines of Cobol code still power the global economy in sectors like banking, finance, insurance, and logistics. These systems constantly perform date-based calculations for transactions, reports, and scheduling. Being able to read, maintain, and write this kind of logic is a critical skill for keeping these essential systems running.


Conclusion and Next Steps

We have successfully navigated the complexities of relative date calculation in Cobol, transforming an ambiguous request like "the last Thursday of the month" into a concrete algorithm. By leveraging Cobol's powerful intrinsic functions—DAY-OF-WEEK, INTEGER-OF-DATE, and DATE-OF-INTEGER—we built a solution that is not only accurate but also robust, automatically handling calendar intricacies like leap years and month lengths.

The key takeaway is that success in Cobol often comes from a deep understanding of its foundational tools and a commitment to structured, methodical problem-solving. While the language may be verbose, its explicitness and reliability are precisely why it has endured for over six decades in mission-critical applications. This exercise proves that even complex logical puzzles can be solved elegantly within the Cobol paradigm.

To continue your journey, we highly recommend exploring other challenges in the Cobol 4 roadmap. For a broader perspective on the language's capabilities, visit our comprehensive Cobol language guide.

Disclaimer: The solution provided has been developed and tested using GnuCOBOL 3.1.2. While the logic and use of intrinsic functions are standard, syntax may vary slightly between different Cobol compilers (e.g., IBM Enterprise COBOL for z/OS).


Published by Kodikra — Your trusted Cobol learning resource.