PHPackages                             codryn/phpcalendar - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. codryn/phpcalendar

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

codryn/phpcalendar
==================

Configurable calendar system supporting real-world and fantasy calendars with date parsing, formatting, and temporal arithmetic

0.1.0(4mo ago)00[2 issues](https://github.com/codryn/phpcalendar/issues)MITPHPPHP ^8.1

Since Jan 12Pushed 4mo agoCompare

[ Source](https://github.com/codryn/phpcalendar)[ Packagist](https://packagist.org/packages/codryn/phpcalendar)[ RSS](/packages/codryn-phpcalendar/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (4)Versions (3)Used By (0)

PHPCalendar
===========

[](#phpcalendar)

[![PHP Version](https://camo.githubusercontent.com/27d7b4f926939f3cbfbdec4ee0bf45e33457aa351e1ceb3551eddc96c195e19d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312d2d382e352d626c75652e737667)](https://www.php.net/)[![PHPStan Level 10](https://camo.githubusercontent.com/d18b9a987aa81e64470a11caecf72caa66597c9ebd6b307bd1c2cb7a752b0dff/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c25323031302d627269676874677265656e2e737667)](https://phpstan.org/)[![CI](https://github.com/codryn/phpcalendar/workflows/CI/badge.svg)](https://github.com/codryn/phpcalendar/actions)[![Latest Stable Version](https://camo.githubusercontent.com/1069bedb6b7ebb1690183eb6016d8cd59d7ed1063c85133b20cc661ddb72c233/68747470733a2f2f706f7365722e707567782e6f72672f636f6472796e2f70687063616c656e6461722f762f737461626c65)](https://packagist.org/packages/codryn/phpcalendar)[![License](https://camo.githubusercontent.com/e7e3bfc3be35f8ef7d39c846a06058d3e8c300106e0441e6850237d3f09a1c93/68747470733a2f2f706f7365722e707567782e6f72672f636f6472796e2f70687063616c656e6461722f6c6963656e7365)](https://packagist.org/packages/codryn/phpcalendar)

> RPG Calendar System for PHP - Gregorian &amp; Fantasy Calendars with Internationalization

**PHPCalendar** is a powerful, type-safe calendar system for PHP supporting both real-world (Gregorian) and fantasy setting calendars. Perfect for RPG applications, game development, and custom calendar implementations.

Features
--------

[](#features)

- **🗓️ Built-in Calendar Profiles**: Gregorian + fantasy RPG calendars (Faerûn, Golarion, DSA, Eberron, Dragonlance, Greyhawk, ...)
- **🔄 Calendar Mapping**: Convert dates between different calendar systems with correlation dates and optional valid ranges
- **🌍 Internationalization**: Support for different languages (English, German, French, Spanish, Italian, ...) for month names, epochs, and calendar names
- **📅 Flexible Date Parsing**: Parse dates from natural language and various formats
- **🎨 Customizable Formatting**: Format dates with custom patterns
- **⏱️ Date Arithmetic**: Add/subtract time spans, calculate differences between dates
- **🎯 Custom Calendar Support**: Create your own calendars with custom months, days, and leap year rules
- **❗ Error Handling**: Clear, specific error messages with location information
- **🔒 Type Safe**: Full PHP 8.1+ type declarations and strict mode
- **⚡ Zero Dependencies**: Pure PHP 8.1+ implementation using only stdlib
- **🧪 Well Tested**: Unit tests with comprehensive coverage
- **📦 PSR-12 Compliant**: Modern PHP coding standards

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- No additional PHP extensions required

Installation
------------

[](#installation)

```
composer require codryn/phpcalendar
```

Quick Start and Usage
---------------------

[](#quick-start-and-usage)

```
use Codryn\PHPCalendar\Calendar\Calendar;

// Create a calendar from built-in profile
$calendar = Calendar::fromProfile('gregorian');

// Parse a date
$date = $calendar->parse('December 25, 2024');

// Format the date
echo $calendar->format($date, 'F d, Y'); // December 25, 2024

// Add 7 days
use Codryn\PHPCalendar\Calendar\TimeSpan;
$future = $date->add(TimeSpan::fromSeconds(86400 * 7));
echo $calendar->format($future, 'F d, Y'); // January 1, 2025

// Calculate difference
$start = $calendar->parse('2024-01-01');
$end = $calendar->parse('2024-12-31');
$span = $calendar->diff($start, $end);
echo $span->getTotalDays(); // 365
```

### Calendar Mapping and Conversion

[](#calendar-mapping-and-conversion)

Convert dates between different calendar systems:

```
use Codryn\PHPCalendar\Calendar\CalendarMapping;
use Codryn\PHPCalendar\Calendar\CalendarMappingConfiguration;
use Codryn\PHPCalendar\Calendar\TimePoint;

// Setup calendars
$gregorian = Calendar::fromProfile('gregorian');
$faerun = Calendar::fromProfile('faerun');

// Define correlation: Jan 1, 2024 = 1 Hammer 1492 DR
$config = new CalendarMappingConfiguration(
    sourceCalendarName: 'gregorian',
    targetCalendarName: 'faerun',
    correlationDate: [
        'source' => ['year' => 2024, 'month' => 1, 'day' => 1],
        'target' => ['year' => 1492, 'month' => 1, 'day' => 1],
    ]
);

$mapping = new CalendarMapping($config, $gregorian, $faerun);

// Convert dates between calendars
$gregorianDate = new TimePoint($gregorian, 2024, 12, 25);
$faerunDate = $mapping->convert($gregorianDate);
echo $faerun->format($faerunDate); // Nightal 24, 1492

// Convert back
$backToGregorian = $mapping->reverseConvert($faerunDate);
echo $gregorian->format($backToGregorian); // December 25, 2024
```

Internationalization
--------------------

[](#internationalization)

PHPCalendar supports internationalization for all built-in calendar profiles. Calendar names, month names, epoch notations, and nameless day names can be displayed in 5 languages:

- **en-us** (English - default)
- **de** (German)
- **fr** (French)
- **es** (Spanish)
- **it** (Italian)

### Usage

[](#usage)

```
use Codryn\PHPCalendar\Calendar\Calendar;

// Create calendar with German locale
$calendar = Calendar::fromProfile('gregorian', 'de');
echo $calendar->getDisplayName(); // "Gregorianischer Kalender"

// Create calendar with French locale
$calendar = Calendar::fromProfile('gregorian', 'fr');
echo $calendar->getDisplayName(); // "Calendrier Grégorien"

// Get localized month names
$profile = new \Codryn\PHPCalendar\Profile\GregorianProfile();
$profile->setLocale('es');
$months = $profile->getMonthNames();
echo $months[1]; // "Enero" (January in Spanish)

// Get localized epoch notation
$epoch = $profile->getEpochNotation();
echo $epoch['after']; // "d.C." (Spanish for AD/CE)
```

### Supported Translations

[](#supported-translations)

CalendarMonth NamesDisplay NameEpoch NotationNameless DaysGregorian✅ All 5✅ All 5✅ All 5N/AFaerûnProper nouns\*✅ All 5✅ All 5✅ All 5DSAProper nouns\*✅ All 5✅ All 5✅ All 5Dragonlance✅ All 5✅ All 5✅ All 5N/AEberronProper nouns\*✅ All 5✅ All 5N/AGolarionProper nouns\*✅ All 5✅ All 5N/AGreyhawk✅ All 5✅ All 5✅ All 5N/A\*Proper nouns (fantasy deity names, dragonmarks, etc.) remain untranslated across all languages.

### Locale Fallback

[](#locale-fallback)

If an unsupported or invalid locale is provided, the system automatically falls back to English (en-us):

```
$calendar = Calendar::fromProfile('gregorian', 'unsupported-locale');
echo $calendar->getDisplayName(); // "Gregorian Calendar" (English fallback)
```

Calendar Profiles
-----------------

[](#calendar-profiles)

### Gregorian Calendar

[](#gregorian-calendar)

Standard international calendar with proper leap year rules.

```
$calendar = Calendar::fromProfile('gregorian');

$christmas = $calendar->parse('2024-12-25');
echo $calendar->format($christmas, 'l, F j, Y');
// Wednesday, December 25, 2024

echo $calendar->isLeapYear(2024) ? 'Leap' : 'Normal'; // Leap
```

**Specifications:**

- 12 months with varying days (28-31)
- Leap year: Divisible by 4, except centuries unless divisible by 400
- Epoch: BCE/CE

### Faerûn (Forgotten Realms)

[](#faerûn-forgotten-realms)

Harptos calendar from D&amp;D's Forgotten Realms setting.

```
$calendar = Calendar::fromProfile('faerun');

$date = $calendar->parse('1 Hammer 1492 DR');
echo $calendar->format($date, 'd F Y'); // 1 Hammer 1492

// 12 months of 30 days + 5 festival days
echo $calendar->getMonthCount(); // 17
```

**Specifications:**

- 12 regular months (30 days each) + 5 festival days
- Leap year: Every 4 years (Shieldmeet)
- Epoch: DR (Dale Reckoning)
- Total: 365 days (366 with Shieldmeet)

### Golarion (Pathfinder)

[](#golarion-pathfinder)

Absalom Reckoning calendar from Pathfinder RPG.

```
$calendar = Calendar::fromProfile('golarion');

$date = $calendar->parse('15 Rova 4724 AR');
echo $calendar->format($date, 'd F Y'); // 15 Rova 4724

echo $calendar->isLeapYear(4720) ? 'Leap' : 'Normal'; // Leap
```

**Specifications:**

- 12 months with varying days (28-31)
- Leap year: Every 8 years
- Epoch: AR (Absalom Reckoning)
- Total: 365 days (366 in leap years)

### Das Schwarze Auge

[](#das-schwarze-auge)

Aventurian calendar from The Dark Eye RPG.

```
$calendar = Calendar::fromProfile('dsa');

$date = $calendar->parse('12 Praios 1045 BF');
echo $calendar->format($date, 'd F Y'); // 12 Praios 1045

// Always 365 days - no leap years
echo $calendar->isLeapYear(1045) ? 'Leap' : 'Normal'; // Normal
```

**Specifications:**

- 12 months (30 days each) + 5 nameless days
- No leap years
- Epoch: BF (Bosparans Fall)
- Total: 365 days always

### Eberron

[](#eberron)

Galifar Calendar from D&amp;D's Eberron setting.

```
$calendar = Calendar::fromProfile('eberron');

$date = $calendar->parse('10 Olarune 998 YK');
echo $calendar->format($date, 'd F Y'); // 10 Olarune 998

// Perfect 28-day months
echo $calendar->getDaysInMonth(1, 998); // 28 (always)
```

**Specifications:**

- 12 months of exactly 28 days each
- No leap years
- Epoch: YK (Years of Kingdom)
- Total: 336 days

### Dragonlance

[](#dragonlance)

Krynn calendar from D&amp;D's Dragonlance setting.

```
$calendar = Calendar::fromProfile('dragonlance');

$preCataclysm = $calendar->parse('100 Phoenix 0 PC');
$postCataclysm = $calendar->parse('1 Phoenix 1 AC');

echo $calendar->format($preCataclysm, 'd F Y'); // 100 Phoenix 0
echo $calendar->format($postCataclysm, 'd F Y'); // 1 Phoenix 1
```

**Specifications:**

- 12 months with varying days (28-31)
- Leap year: Gregorian rules
- Epoch: PC/AC (Pre/After Cataclysm)
- Total: 365 days (366 in leap years)

### Greyhawk

[](#greyhawk)

Common Year calendar from D&amp;D's World of Greyhawk.

```
$calendar = Calendar::fromProfile('greyhawk');

$date = $calendar->parse('1 Needfest 591 CY');
echo $calendar->format($date, 'd F Y'); // 1 Needfest 591

// 12 regular months + 4 festival weeks
echo $calendar->getMonthCount(); // 16
```

**Specifications:**

- 12 months (28 days each) + 4 festival weeks (7 days each)
- No leap years
- Epoch: CY (Common Year)
- Total: 364 days

Custom Calendars
----------------

[](#custom-calendars)

Create your own calendar with custom configuration:

```
use Codryn\PHPCalendar\Calendar\Calendar;
use Codryn\PHPCalendar\Calendar\CalendarConfiguration;

$config = new CalendarConfiguration(
    name: 'mars-sol',
    displayName: 'Martian Solar Calendar',
    monthNames: [
        1 => 'Ares', 2 => 'Phobos', 3 => 'Deimos',
        4 => 'Olympus', 5 => 'Valles', 6 => 'Mariner',
        7 => 'Viking', 8 => 'Sojourner', 9 => 'Spirit',
        10 => 'Opportunity', 11 => 'Curiosity', 12 => 'Perseverance'
    ],
    daysPerMonth: [
        1 => 31, 2 => 31, 3 => 31, 4 => 31,
        5 => 31, 6 => 31, 7 => 31, 8 => 31,
        9 => 31, 10 => 31, 11 => 31, 12 => 36
    ],
    leapYearRule: fn(int $year) => $year % 10 === 0,
    epochNotation: ['before' => 'BL', 'after' => 'AL'], // Before/After Landing
    formatPatterns: ['d F Y AL', 'Y-m-d']
);

$marsCalendar = Calendar::fromConfiguration($config);
$landingDay = $marsCalendar->parse('1 Ares 1 AL');
echo $marsCalendar->format($landingDay); // 1 Ares 1 AL
```

API Reference
-------------

[](#api-reference)

PHPCalendar provides a clean, fluent API for calendar operations:

```
// Create calendar
$calendar = Calendar::fromProfile('gregorian');
$calendar = Calendar::fromProfile('gregorian', 'de'); // With locale
$calendar = Calendar::fromConfiguration($config);

// Set locale on profile directly
$profile = new GregorianProfile();
$profile->setLocale('fr');
$locale = $profile->getLocale(); // 'fr'

// Parse dates
$date = $calendar->parse('December 25, 2024');
$date = $calendar->parse('2024-12-25');

// Format dates
$formatted = $calendar->format($date, 'F d, Y');
$formatted = $calendar->format($date, 'Y-m-d H:i:s');

// Date arithmetic
$future = $date->add(TimeSpan::fromSeconds(86400 * 7)); // +7 days
$past = $date->subtract(TimeSpan::fromSeconds(3600));   // -1 hour

// Calculate differences
$span = $calendar->diff($startDate, $endDate);
$days = $span->getTotalDays();
$hours = $span->getTotalHours();

// Calendar metadata
$calendar->getName();              // 'gregorian'
$calendar->getDisplayName();       // 'Gregorian Calendar'
$calendar->getMonthNames();        // [1 => 'January', ...]
$calendar->getDaysInMonth(2, 2024); // 29
$calendar->isLeapYear(2024);       // true
```

Documentation
-------------

[](#documentation)

Comprehensive documentation is available:

- **[API Documentation](docs/API.md)** - Complete class and method reference
- **[Usage Guide](docs/USAGE.md)** - Common patterns and examples
- **[Calendar Profiles](docs/PROFILES.md)** - Details on all 7 built-in profiles
- **[Calendar Mapping](docs/CALENDAR_MAPPING.md)** - Convert dates between calendar systems
- **[Custom Calendars](docs/CUSTOM_CALENDARS.md)** - Guide to creating custom calendars
- **[Contributing Guide](CONTRIBUTING.md)** - Development workflow and standards

Development
-----------

[](#development)

See [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.

Architecture
------------

[](#architecture)

PHPCalendar is structured around key components:

- **Calendar**: Main class for calendar operations
- **CalendarProfile**: Defines calendar rules and metadata
- **TimePoint**: Represents specific dates in a calendar
- **TimeSpan**: Represents time intervals for date arithmetic

Performance
-----------

[](#performance)

TODO: Add performance benchmarks and optimizations.

Quality Standards
-----------------

[](#quality-standards)

- ✅ **PHPStan Level 10**: Strictest static analysis level from PHPSTan 2.1
- ✅ **PSR-12**: PHP coding standards compliance
- ✅ **Strict Types**: `declare(strict_types=1)` in all files
- ✅ **TDD**: Test-driven development methodology
- ✅ **Type Hints**: Full type declarations on all methods
- ✅ **PHPDoc**: Complete documentation blocks

Contributing
------------

[](#contributing)

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for:

- Development workflow
- Coding standards
- Testing requirements
- Pull request process

License
-------

[](#license)

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for version history and updates.

Support
-------

[](#support)

- 📖 [Documentation](docs/)
- 🐛 [Issue Tracker](https://github.com/codryn/phpcalendar/issues)
- 💬 [Discussions](https://github.com/codryn/phpcalendar/discussions)
- 📧 [Email](mailto:info@codryn.com)

Credits
-------

[](#credits)

Created and maintained by Marco for [Codryn](https://codryn.com).

Special thanks to:

- The PHP community
- Contributors to fantasy RPG calendar systems
- PHPUnit, PHPStan, and PHP-CS-Fixer maintainers

### Game Systems Copyright

[](#game-systems-copyright)

This library implements calendars from various tabletop RPG systems for non-commercial use. All game system names, mechanics, and related intellectual property remain the property of their respective copyright holders. See [GAME\_SYSTEMS\_COPYRIGHT.md](GAME_SYSTEMS_COPYRIGHT.md) for detailed copyright notices and attributions.

---

Built for the tabletop RPG community 🎲

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance77

Regular maintenance activity

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 61.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

126d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/672c6ebccd9bbdd03fda087928aa8d8f9bf64eea76423116ee328c216430003f?d=identicon)[marcowuelser](/maintainers/marcowuelser)

---

Top Contributors

[![marcowuelser](https://avatars.githubusercontent.com/u/10141843?v=4)](https://github.com/marcowuelser "marcowuelser (32 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (20 commits)")

---

Tags

timedatecalendarfantasytemporalgregorianrpgfaerun

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/codryn-phpcalendar/health.svg)

```
[![Health](https://phpackages.com/badges/codryn-phpcalendar/health.svg)](https://phpackages.com/packages/codryn-phpcalendar)
```

###  Alternatives

[league/period

Time range API for PHP

7335.4M21](/packages/league-period)[aeon-php/calendar

PHP type safe, immutable calendar library

2079.7M16](/packages/aeon-php-calendar)[benhall14/php-calendar

A simple PHP class to generate calendars.

9822.6k](/packages/benhall14-php-calendar)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
