# Business Logic — JKKKeiNewCmnLogicUtil.getAge() [33 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.web.webview.commonOneStop.JKKKeiNewCmnLogicUtil` |
| Layer | Utility (Common Component) |
| Module | `commonOneStop` (Package: `eo.web.webview.commonOneStop`) |

## 1. Role

### JKKKeiNewCmnLogicUtil.getAge()

This method calculates a person's age in completed years based on their birth date (year, month, day) and a reference "operation date" (opeDate). It implements a date-diff algorithm that determines whether the birthday has already occurred in the reference year — if the current month is before the birth month, or if the current month matches but the current day is before the birth day, the person has not yet reached their birthday that year and one year is subtracted from the raw year difference. This is a pure utility function with no side effects, serving as a shared calculation service used across multiple screens in the webview application for age-related business rules (e.g., eligibility checks, contract age verification). The method accepts the operation date rather than using the system clock, allowing the age to be calculated as of a specific point in time — important for auditability and for scenarios where operations are batched or backdated. The overloaded 2-parameter variant delegates to this method by parsing a single `yyyyMMdd` birth date string into its components.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["getAge(year, month, day, opeDate)"])

    SUB1["Parse opeDate to sysYmd"]
    NP1["nowYear = substr(sysYmd,0,4)"]
    NP2["nowMonth = substr(sysYmd,4,6)"]
    NP3["nowDay = substr(sysYmd,6,8)"]
    BP1["birthdYear = Integer.parseInt(year)"]
    BP2["birthdMonth = Integer.parseInt(month)"]
    BP3["birthdDay = Integer.parseInt(day)"]

    COND1{nowMonth < birthdMonth?}
    COND2{nowMonth > birthdMonth?}
    COND3{nowMonth == birthdMonth?}
    COND4{nowDay < birthdDay?}

    AGE1["age = nowYear - birthdYear - 1"]
    AGE2["age = nowYear - birthdYear"]
    AGE3["age = nowYear - birthdYear - 1"]
    AGE4["age = nowYear - birthdYear"]
    RET["age = Integer.toString(age)"]
    END(["Return age as String"])

    START --> SUB1
    SUB1 --> NP1
    NP1 --> NP2
    NP2 --> NP3
    NP3 --> BP1
    BP1 --> BP2
    BP2 --> BP3
    BP3 --> COND1
    COND1 -->|"Yes"| AGE1
    COND1 -->|"No"| COND2
    COND2 -->|"Yes"| AGE2
    COND2 -->|"No"| COND3
    COND3 -->|"Yes"| COND4
    COND4 -->|"Yes"| AGE3
    COND4 -->|"No"| AGE4
    AGE1 --> RET
    AGE2 --> RET
    AGE3 --> RET
    AGE4 --> RET
    RET --> END
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `year` | `String` | Birth year in Western calendar (e.g., "1990") — the calendar year the person was born |
| 2 | `month` | `String` | Birth month (e.g., "03") — the month the person was born, 01-12 |
| 3 | `day` | `String` | Birth day (e.g., "15") — the day of the month the person was born, 01-31 |
| 4 | `opeDate` | `String` | Operation date in `yyyyMMdd` format (e.g., "20240728") — the reference date as of which age is calculated, not necessarily today's date. This allows consistent age calculation across batch processing and historical records. |

**External State:** None. This method is a pure function — it reads no instance fields, static state, or external dependencies.

## 4. CRUD Operations / Called Services

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `String.substring(int, int)` | - | - | Extracts year (chars 0-4), month (chars 4-6), day (chars 6-8) from `opeDate` string |
| - | `Integer.parseInt(String)` | - | - | Converts string representations of year/month/day into integer primitives for arithmetic comparison |
| - | `Integer.toString(int)` | - | - | Converts the computed integer age back to a String return value |

**Note:** This method contains no database operations, no SC (Service Component) calls, and no entity interactions. It is a pure calculation utility. All terminal operations are standard JDK string/numeric transformations.

## 5. Dependency Trace

### Pre-computed evidence from code analysis graph:

No screen/batch entry points found within 8 hops. Direct callers found: 1 methods.
Terminal operations from this method: `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-], `substring` [-]

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Utility:JKKKeiNewCmnLogicUtil.getAge(String, String) | `JKKKeiNewCmnLogicUtil.getAge(birthd, opeDate)` -> `JKKKeiNewCmnLogicUtil.getAge(year, month, day, opeDate)` | `substring` [-], `parseInt` [-], `toString` [-] |

**Note:** The only direct caller is the overloaded 2-parameter variant of `getAge` within the same class. No screen, batch, or CBS entry points were found calling this method directly. The method is invoked indirectly through the 2-parameter overload, which parses a single `yyyyMMdd` birth date string into its components and delegates to this 4-parameter method.

## 6. Per-Branch Detail Blocks

**Block 1** — [INITIALIZATION] (L9671)

Parse the operation date string and birth date components into integer primitives.

| # | Type | Code |
|---|------|------|
| 1 | SET | `age = 0` // Initialize age accumulator |
| 2 | SET | `sysYmd = opeDate` // Alias the operation date |
| 3 | SET | `nowYear = Integer.parseInt(sysYmd.substring(0, 4))` // Extract YYYY from yyyyMMdd, e.g., "2024" |
| 4 | SET | `nowMonth = Integer.parseInt(sysYmd.substring(4, 6))` // Extract MM from yyyyMMdd, e.g., "07" |
| 5 | SET | `nowDay = Integer.parseInt(sysYmd.substring(6, 8))` // Extract DD from yyyyMMdd, e.g., "28" |
| 6 | SET | `birthdYear = Integer.parseInt(year)` // Parse birth year string to int |
| 7 | SET | `birthdMonth = Integer.parseInt(month)` // Parse birth month string to int |
| 8 | SET | `birthdDay = Integer.parseInt(day)` // Parse birth day string to int |

**Block 2** — [IF] `nowMonth < birthdMonth` (L9679)

The current month is before the birth month — the person has not had their birthday this year yet.

| # | Type | Code |
|---|------|------|
| 1 | SET | `age = nowYear - birthdYear - 1` // Subtract 1 because birthday hasn't occurred yet |

**Block 3** — [ELSE-IF] `nowMonth > birthdMonth` (L9681)

The current month is after the birth month — the person has already had their birthday this year.

| # | Type | Code |
|---|------|------|
| 1 | SET | `age = nowYear - birthdYear` // Simple year difference, birthday already passed |

**Block 4** — [ELSE-IF] `nowMonth == birthdMonth` (L9685)

The current month matches the birth month — must compare days to determine if birthday has occurred.

**Block 4.1** — [IF] `nowDay < birthdDay` (L9687)

The current day is before the birth day within the same month — birthday has not yet occurred this year.

| # | Type | Code |
|---|------|------|
| 1 | SET | `age = nowYear - birthdYear - 1` // Subtract 1 because birthday hasn't occurred yet in this month |

**Block 4.2** — [ELSE] (L9691)

The current day is on or after the birth day — the person has had their birthday this year.

| # | Type | Code |
|---|------|------|
| 1 | SET | `age = nowYear - birthdYear` // Simple year difference, birthday already passed this month |

**Block 5** — [RETURN] (L9695)

Convert the computed integer age to a String and return.

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return Integer.toString(age)` // Convert int age to String return type |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `opeDate` | Field | Operation date — the reference date used for age calculation, formatted as `yyyyMMdd`. Not necessarily today's date; can be a batch processing date or historical date for audit consistency. |
| `sysYmd` | Field | System date in `yyyyMMdd` string format — internal alias of `opeDate` used for date string parsing |
| `birthdYear` | Field | Birth year — the calendar year in which the subject was born |
| `birthdMonth` | Field | Birth month — the 1-12 month in which the subject was born |
| `birthdDay` | Field | Birth day — the day-of-month (1-31) on which the subject was born |
| `age` | Field | Computed age in completed years — the number of full years between birth date and operation date |
| `Integer.parseInt` | JDK Method | Parses a string representation of an integer into a Java `int` primitive. Throws `NumberFormatException` if the string is not a valid integer. |
| `String.substring` | JDK Method | Extracts a substring from a string between the specified start (inclusive) and end (exclusive) indices. |
| `Integer.toString` | JDK Method | Converts an `int` primitive to its string representation. |
| yyyyMMdd | Format | Date format convention: 4-digit year, 2-digit month (zero-padded), 2-digit day (zero-padded). E.g., "20240728" = July 28, 2024. |
