Skip to content

Add age calculation API endpoint#14

Open
airyland wants to merge 2 commits into
devfrom
claude/issue-6-20251017-1214
Open

Add age calculation API endpoint#14
airyland wants to merge 2 commits into
devfrom
claude/issue-6-20251017-1214

Conversation

@airyland

Copy link
Copy Markdown
Owner

This PR adds a new REST API endpoint at /api/age that calculates a person's age from their date of birth.

Features

  • Calculate current age or age at a specific date
  • Returns age in multiple formats (readable, decimal, detailed)
  • Proper input validation and error handling
  • RESTful design following existing API patterns
  • Comprehensive API documentation

Fixes #6

Generated with Claude Code

This PR adds a new REST API endpoint at /api/age that calculates
a person's age from their date of birth.

Features:
- Calculate current age or age at a specific date
- Returns age in multiple formats (readable, decimal, detailed)
- Proper input validation and error handling
- RESTful design following existing API patterns

Fixes #6

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Airyland <airyland@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting

Comment thread app/api/age/route.ts Outdated
Comment on lines +21 to +22
// Parse birthdate
const birthDate = new Date(birthDateParam)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Parse birth dates without pinning timezone

The handler builds birthDate with new Date(birthDateParam) and then feeds it into calculateAge, which uses getFullYear()/getMonth()/getDate() and therefore interprets the date in the server’s local timezone. When the runtime is not configured for UTC, a request such as birthdate=2000-01-01 will be parsed as midnight UTC and show up as Dec 31 in UTC−05:00, causing the reported age to be off by a day (and possibly the month). Consider parsing the incoming YYYY-MM-DD string with Date.UTC or appending a T00:00:00 offset so the calendar date is stable regardless of server timezone.

Useful? React with 👍 / 👎.

@claude

claude Bot commented Oct 17, 2025

Copy link
Copy Markdown

Code Review - PR #14: Add age calculation API endpoint

Thank you for this contribution! This is a well-structured PR that adds a clean REST API endpoint. Here is my detailed review:


Strengths

Code Quality

  • Clean structure: The API route follows Next.js 13+ App Router conventions correctly
  • Consistent style: Matches the existing /api/holidays route pattern nicely
  • Good separation of concerns: Business logic properly extracted to lib/age-calculator.ts
  • Comprehensive documentation: The README.md is excellent with clear examples

Error Handling

  • Proper validation of required parameters (app/api/age/route.ts:10-18)
  • Multiple validation checks for date formats (lines 25, 40)
  • Future date validation (line 51)
  • Try-catch with error logging (lines 84-91)

Issues and Recommendations

1. Critical: Date Parsing Timezone Issue

Location: app/api/age/route.ts:22, 37

The current code uses new Date(dateString), which has timezone problems. new Date("2007-01-15") parses as midnight UTC, but then Date methods like .getMonth() and .getDate() use local timezone, causing off-by-one day errors for users in certain timezones.

Example Bug:

  • User inputs: birthdate=2007-01-15
  • In PST (UTC-8), this becomes 2007-01-14 16:00:00 PST
  • .getDate() returns 14, not 15!

Recommended Fix: Create a helper function that parses YYYY-MM-DD strings by splitting and using the Date constructor with individual components: new Date(year, month - 1, day, 0, 0, 0, 0). This ensures dates are interpreted as local midnight, avoiding timezone confusion.


2. Bug: Hours/Minutes/Seconds Calculation

Location: app/api/age/route.ts:66

When targetDateParam is not provided, targetDate is new Date() with the current time. The time component calculations will be inconsistent because birth dates are at midnight but "now" has a time.

Recommendation: Since this is an age API, normalize both dates to midnight for consistency. The README examples show 0:00:00 for time, suggesting midnight normalization is intended.


3. Validation: Better Date Format Check

Location: app/api/age/route.ts:25, 40

Current validation only checks if parsing succeeds, which accepts formats like "2007/01/15" or "Jan 15 2007".

Recommendation: Add explicit YYYY-MM-DD format validation using a regex pattern to ensure consistent input format.


4. Code Duplication: DRY Principle

Location: app/api/age/route.ts:20-47

The date parsing and validation logic is duplicated for birthdate and targetDate. Extract this into a reusable helper function to reduce duplication and improve maintainability.


5. Decimal Age Calculation Precision

Location: lib/age-calculator.ts:56

Using 365.25 for decimal age is reasonable but approximate. The README should clarify that decimalAge uses an average year length (365.25 days) and is not exact for specific date ranges.


6. Security: Consider Rate Limiting

For production, consider adding rate limiting to prevent abuse. Use middleware or a library to limit requests per IP. This is standard practice for public APIs. Not blocking, but good practice for production.


7. Test Coverage - IMPORTANT

Missing: No tests for this new functionality

Recommendation: Add tests for:

  • Unit tests for calculateAge function (leap year handling, month boundary cases, same-day scenarios)
  • API route tests (valid requests, missing parameters, invalid date formats, future birthdates, edge cases)

This is important for ensuring correctness and preventing regressions.


8. Minor: Response Consistency

Location: app/api/age/route.ts:76

The formatted.readable field is computed inline in the route handler, while other formats come from age.formatted. Move all formatting to calculateAge function for consistency.


9. Documentation: API Response Schema

Location: app/api/age/README.md

Great documentation! Minor suggestions:

  • Add status codes (200, 400, 500)
  • Add CORS info if applicable
  • Clarify decimal age uses 365.25 average
  • Add edge cases (birthdate = targetDate, Feb 29 birthdays)

Performance and Security

Performance: No major concerns. Calculations are O(1), no database queries or external API calls, small response size.

Security: Good security posture overall. No SQL injection, XSS, file system access, or code execution risks. Input validation is present.


Summary and Action Items

Must Fix (Blocking):

  1. Timezone bug in date parsing - Use local date parsing
  2. Add tests - At least basic unit tests for calculateAge

Should Fix (Recommended):

  1. Normalize time components
  2. Strict format validation - Add regex check for YYYY-MM-DD
  3. Reduce duplication - Extract date validation helper

Nice to Have:

  1. Move readable format to age-calculator.ts
  2. Document decimal age precision
  3. Consider rate limiting

Overall Assessment

Rating: 4/5 stars

This is a solid, well-structured PR with good code quality and excellent documentation. The main concern is the timezone bug, which could cause incorrect results for users in certain timezones. Once that is fixed and tests are added, this will be production-ready.

The code follows Next.js best practices and has good error handling. Great work overall!

Let me know if you would like help with any of these items or have questions about the feedback!

@airyland

Copy link
Copy Markdown
Owner Author

@codex

  • Add a UTC offset parameter, defaulting to UTC time
  • Add unit tests
  • Add an API list page
  • Add a details page for this API, which should allow direct testing

@chatgpt-codex-connector

Copy link
Copy Markdown

Summary

Testing

  • npm test
  • npm run validate:translations

View task →

@claude

claude Bot commented Oct 17, 2025

Copy link
Copy Markdown

Pull Request Review: Age Calculation API Endpoint

Thank you for this comprehensive PR! The implementation is well-structured and demonstrates strong attention to detail. Below is my detailed review covering code quality, potential issues, performance, security, and test coverage.

✅ Strengths

1. Excellent Code Organization

  • Clear separation of concerns: route handler, date utilities, and age calculation logic
  • Good modular design with reusable date utility functions
  • Comprehensive error handling with specific error messages

2. Strong Input Validation

  • Robust date format validation using regex
  • UTC offset validation with proper range checking (-12:00 to +14:00)
  • Invalid calendar date detection (e.g., 2024-02-30)
  • Future date validation

3. Good Documentation

  • Comprehensive README with examples
  • Interactive API tester with excellent UX
  • Multi-language support via i18n

4. Test Coverage

  • Custom test suite included with good coverage of edge cases
  • Tests for leap years, timezone handling, and error cases

🐛 Potential Bugs & Issues

Critical: Redundant NaN Check (route.ts:73-80)

After parsing targetDate with parseIsoDateWithOffset, there is an unreachable isNaN check. The function already validates the date and throws errors for invalid dates, so this check will never catch invalid dates.

Location: app/api/age/route.ts:73-80

Recommendation: Remove this redundant check since it is dead code.


Medium: Ambiguous UTC Offset Parsing (date-utils.ts:30-41)

The logic that interprets numeric offsets is potentially confusing. Values ≤14 are treated as hours (e.g., -5 → -300 minutes) while values >14 are treated as minutes (e.g., 45 → 45 minutes).

This creates ambiguity around the value 14. Users might expect 60 to mean 1 hour, but it means 60 minutes.

Location: app/api/age/date-utils.ts:37-40

Recommendation: Document this behavior clearly in the API documentation, consider requiring the ±HH:MM format for clarity, or always treat numeric values as minutes only.


Low: Year/Month Calculation Edge Case (age-calculator.ts:31-36)

When targetDay < birthDay, the month is decremented. However, if this happens in January (month 0), the adjustment wraps to December (month 11) but does not decrement the year. This might be correct depending on the intended behavior, but it is worth verifying.

Location: lib/age-calculator.ts:31-36

Example scenario: Birth 2020-02-29, Target 2021-01-15. Expected: 0 years, 10 months, 17 days (approximately)


🔒 Security Considerations

Good Security Practices:

  • ✅ No SQL injection risk (no database)
  • ✅ Input validation prevents injection attacks
  • ✅ No sensitive data exposure
  • ✅ Proper error messages without stack traces

Minor Concern: Error Logging (route.ts:114)

The API logs errors to console, which is good for debugging but could expose sensitive information in production logs if unexpected errors occur.

Recommendation: Ensure production logging is properly configured to sanitize error messages.

@claude

claude Bot commented Oct 17, 2025

Copy link
Copy Markdown

⚡ Performance Considerations

Excellent Performance:

  • ✅ Pure calculation functions with no I/O operations
  • ✅ No external API calls or database queries
  • ✅ Minimal memory allocation
  • ✅ O(1) time complexity for all operations

Minor Optimization Opportunity:

The formattedCurl() function in api-tester-client.tsx is recalculated on every render. Consider memoizing it with useMemo hook.

Location: app/[locale]/api/age/api-tester-client.tsx:73-83


🧪 Test Coverage

Strong Test Foundation:

  • ✅ Core calculation tests (identical dates, leap years, future dates)
  • ✅ Date utility tests (offset parsing, date formatting)
  • ✅ Error handling tests

Missing Test Cases:

  1. Timezone Edge Cases: Birth and target dates on opposite sides of UTC (e.g., +12:00 vs -12:00), dates near timezone boundaries that could cause day shifts

  2. Age Calculation Edge Cases: Birth on the last day of a month (e.g., Jan 31) with target dates in months with fewer days, ages spanning multiple leap years, very large age spans (e.g., 100+ years)

  3. API Route Tests: Missing tests for the actual HTTP endpoint (app/api/age/route.ts), no integration tests verifying the full request/response cycle

  4. Client Component Tests: No tests for the React components (api-tester-client.tsx, page.tsx)

Recommendation: Add integration tests using Next.js testing utilities or a tool like Vitest/Jest with React Testing Library.


📝 Code Quality & Best Practices

Excellent:

  • ✅ Consistent TypeScript usage with proper types
  • ✅ Clear, descriptive variable and function names
  • ✅ Good use of early returns for error handling
  • ✅ Proper use of UTC methods to avoid timezone bugs
  • ✅ Comprehensive i18n support

Minor Suggestions:

  1. Add JSDoc comments to utility functions (date-utils.ts). The functions are well-named but would benefit from parameter and return value documentation.

  2. Consider adding TypeScript interfaces for API responses (route.ts) to improve type safety and documentation.

  3. Extract magic numbers to constants (age-calculator.ts:54), e.g., const DAYS_PER_YEAR = 365.25


🎨 UI/UX Observations

Excellent UI Implementation:

  • ✅ Clean, responsive design following existing patterns
  • ✅ Loading states and error handling
  • ✅ Copy-to-clipboard functionality
  • ✅ Interactive tester with real-time feedback
  • ✅ Breadcrumb navigation

Minor Enhancement:

Consider adding client-side validation for the input fields (e.g., HTML5 type='date' or pattern validation) to provide immediate feedback before API calls.


📦 Dependencies & Build

  • ✅ No new external dependencies added
  • ✅ Test script properly configured in package.json
  • ✅ TypeScript configuration for tests (tsconfig.test.json)
  • ✅ Proper gitignore updates for test artifacts

@claude

claude Bot commented Oct 17, 2025

Copy link
Copy Markdown

🎯 Summary & Recommendations

Priority Fixes:

  1. ✅ Remove redundant NaN check in route.ts:73-80 (dead code)
  2. ⚠️ Clarify or document UTC offset parsing ambiguity in date-utils.ts and README
  3. ⚠️ Verify month/year edge case handling in age-calculator.ts:31-36

Recommended Enhancements:

  1. Add integration tests for the API route
  2. Add JSDoc comments to utility functions
  3. Create TypeScript interfaces for API responses
  4. Memoize the formattedCurl function
  5. Add more edge case tests (month-end dates, large age spans, timezone boundaries)

Overall Assessment:

This is a high-quality PR with well-structured code, comprehensive documentation, and good test coverage. The implementation is production-ready with minor improvements recommended. The UTC offset handling is particularly well-done, and the interactive API tester is an excellent addition for documentation.

Recommendation: Approve with minor revisions ✅

Great work! 🎉


Code References

Issues identified:

  • Redundant check: app/api/age/route.ts:73
  • UTC offset parsing: app/api/age/date-utils.ts:37-40
  • Month calculation: lib/age-calculator.ts:31-36
  • Error logging: app/api/age/route.ts:114
  • Performance opportunity: app/[locale]/api/age/api-tester-client.tsx:73

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API

1 participant