Skip to content

pphatdev/lunar-date

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

32 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Lunar Date - PHP Khmer Calendar Library

CI License: MIT PHP Version Latest Stable Version Total Downloads

A comprehensive PHP library for converting between Gregorian and Khmer (Cambodian) calendar dates. This is a faithful port of the popular JavaScript momentkh library by ThyrithSor, enhanced with modern PHP best practices and comprehensive testing.

Features

Core Calendar Functions

  • βœ… Gregorian to Khmer Lunar Date Conversion - Full bidirectional date conversion with lunar calendar support
  • βœ… Buddhist Era (BE) Year Support - Accurate BE year calculations and conversion utilities
  • βœ… Khmer New Year Calculations - Precise calculation of Khmer New Year moments using advanced algorithms
  • βœ… Animal Year System - Complete 12-year animal cycle (αž†αŸ’αž“αžΆαŸ†αžŸαžαŸ’αžœ) support
  • βœ… Era Year System - 10-year era cycle (αžŸαŸαž€) calculations
  • βœ… Leap Year Support - Accurate lunar calendar leap year handling

Formatting & Localization

  • βœ… Flexible Date Formatting - Customizable output with Khmer formatting tokens
  • βœ… Number Conversion - Bidirectional Arabic ↔ Khmer numeral conversion
  • βœ… Khmer Text Support - Full Unicode Khmer character support and validation
  • βœ… Multiple Calendar Systems - Solar and lunar month name support

Developer Experience

  • βœ… Modern PHP (7.4+) - Strict types, comprehensive type hints, and modern syntax
  • βœ… Comprehensive Testing - Full PHPUnit test suite with edge case coverage
  • βœ… Static Analysis - PHPStan ready with high code quality standards
  • βœ… PSR-12 Standards - Follows PHP coding standards and best practices
  • βœ… Rich Documentation - Detailed PHPDoc annotations and usage examples

Requirements

  • PHP 7.4 or higher
  • ext-json (usually included)

Installation

Install via Composer:

composer require pphatdev/lunar-date

Quick Start

<?php
require_once 'vendor/autoload.php';

use PPhatDev\LunarDate\KhmerDate;

// Create Khmer date from current time
$today = new KhmerDate();
echo $today->toLunarDate();
// Output: αžαŸ’αž„αŸƒαž’αžΆαž‘αž·αžαŸ’αž™ αŸ¨αž€αžΎαž αžαŸ‚αž˜αž·αž‚αžŸαž·αžš αž†αŸ’αž“αžΆαŸ†αž‡αžΌαž αžŸαŸ†αžšαžΉαž‘αŸ’αž’αž·αžŸαŸαž€ αž–αž»αž‘αŸ’αž’αžŸαž€αžšαžΆαž‡ ្αŸ₯៦៧

// Convert specific Gregorian date
$date = new KhmerDate('1996-09-24');
echo $date->toLunarDate();
// Output: αžαŸ’αž„αŸƒαž’αž„αŸ’αž‚αžΆαžš αŸ‘αŸ’αž€αžΎαž αžαŸ‚αž’αžŸαŸ’αžŸαž»αž‡ αž†αŸ’αž“αžΆαŸ†αž… αžŸαŸ†αžšαžΉαž‘αŸ’αž’αž·αžŸαŸαž€ αž–αž»αž‘αŸ’αž’αžŸαž€αžšαžΆαž‡ ្αŸ₯៣៩

// Custom formatting
echo $date->toLunarDate('dN αžαŸ’αž„αŸƒW αžαŸ‚m αž–.ស. b');
// Output: αŸ‘αŸ’αž€αžΎαž αžαŸ’αž„αŸƒαž’αž„αŸ’αž‚αžΆαžš αžαŸ‚αž’αžŸαŸ’αžŸαž»αž‡ αž–.ស. ្αŸ₯៣៩

// Khmer Gregorian date
echo $date->toKhmerDate();
// Output: ្ៀ αžαŸ‚αž€αž‰αŸ’αž‰αžΆ αž†αŸ’αž“αžΆαŸ†αŸ‘αŸ©αŸ©αŸ¦

API Reference

KhmerDate Class

The main class for working with Khmer calendar dates.

Creating KhmerDate Objects

// Current date and time
$now = new KhmerDate();

// From DateTime object
$dateTime = new DateTime('2024-01-15');
$khmerDate = new KhmerDate($dateTime);

// From string (various formats supported)
$khmerDate = new KhmerDate('2024-01-15');
$khmerDate = new KhmerDate('2024-01-15 14:30:00');

// From timestamp
$khmerDate = new KhmerDate(1705315800);

// Static factory methods
$khmerDate = KhmerDate::create('2024-01-15');
$khmerDate = KhmerDate::createFromDateTime($dateTime);

Core Methods

$date = new KhmerDate('2024-01-15');

// Lunar date conversion
echo $date->toLunarDate();                    // Full Khmer lunar date
echo $date->toLunarDate('dN αžαŸ‚m αž–.ស. b');     // Custom format

// Khmer Gregorian date
echo $date->toKhmerDate();                    // Khmer numerals with Gregorian calendar

// Calendar components
echo $date->khDay();      // Lunar day (0-29): 8
echo $date->khMonth();    // Lunar month index: 2  
echo $date->khYear();     // Buddhist Era year: 2567

// Standard DateTime operations
echo $date->format('Y-m-d H:i:s');           // Standard formatting
echo $date->getTimestamp();                  // Unix timestamp
$copy = $date->copy();                       // Create copy

Date Arithmetic

$date = new KhmerDate('2024-01-15');

// Add/subtract time intervals
$futureDate = $date->add('P1M');      // Add 1 month
$pastDate = $date->subtract('P7D');   // Subtract 7 days

// The original date object is modified, use copy() if needed
$newDate = $date->copy()->add('P1Y'); // Add 1 year to copy

Core Methods

$date = new KhmerDate('2024-01-15');

// Lunar date conversion
echo $date->toLunarDate();                    // Full Khmer lunar date
echo $date->toLunarDate('dN αžαŸ‚m αž–.ស. b');     // Custom format

// Khmer Gregorian date
echo $date->toKhmerDate();                    // Khmer numerals with Gregorian calendar

// Calendar components
echo $date->khDay();      // Lunar day (0-29): 8
echo $date->khMonth();    // Lunar month index: 2  
echo $date->khYear();     // Buddhist Era year: 2567

// Standard DateTime operations
echo $date->format('Y-m-d H:i:s');           // Standard formatting
echo $date->getTimestamp();                  // Unix timestamp
$copy = $date->copy();                       // Create copy

Date Arithmetic

$date = new KhmerDate('2024-01-15');

// Add/subtract time intervals
$futureDate = $date->add('P1M');      // Add 1 month
$pastDate = $date->subtract('P7D');   // Subtract 7 days

// The original date object is modified, use copy() if needed
$newDate = $date->copy()->add('P1Y'); // Add 1 year to copy

Static Methods & Utilities

Khmer New Year Calculation

// Get exact Khmer New Year moment for any year
$newYear2024 = KhmerDate::getKhNewYearMoment(2024);
echo $newYear2024->format('Y-m-d H:i:s');  // 2024-04-14 06:46:00

// Calculate for multiple years
foreach (range(2020, 2030) as $year) {
    $newYear = KhmerDate::getKhNewYearMoment($year);
    echo "Khmer New Year $year: " . $newYear->format('Y-m-d H:i') . "\n";
}

Number Conversion

// Arabic to Khmer numerals
echo KhmerDate::arabicToKhmerNumber('2024');   // ្០្ៀ
echo KhmerDate::arabicToKhmerNumber('15');     // ៑αŸ₯

// Khmer to Arabic numerals  
echo KhmerDate::khmerToArabicNumber('្០្ៀ');  // 2024
echo KhmerDate::khmerToArabicNumber('៑αŸ₯');     // 15

// Helper method
echo KhmerDate::getKhmerNumber(2024);          // ្០្ៀ

Calendar Information

// Get month names
$lunarMonths = KhmerDate::getKhmerMonthNames();
// ['αž˜αž·αž‚αžŸαž·αžš', 'αž”αž»αžŸαŸ’αžŸ', 'αž˜αžΆαžƒ', 'αž•αž›αŸ’αž‚αž»αž“', 'αž…αŸαžαŸ’αžš', 'αž–αž·αžŸαžΆαž', 'αž‡αŸαžŸαŸ’αž‹', 'ធអសអឍ', 'αžŸαŸ’αžšαžΆαž–αžŽαŸ', 'αž—αž‘αŸ’αžšαž”αž‘', 'αž’αžŸαŸ’αžŸαž»αž‡', 'αž€αžαŸ’αžŠαž·αž€', 'αž”αž‹αž˜αžΆαžŸαžΆαž', 'αž‘αž»αžαž·αž™αžΆαžŸαžΆαž']

// Get animal year names (12-year cycle)
$animalYears = KhmerDate::getAnimalYearNames();
// ['αž‡αžΌαž', 'αž†αŸ’αž›αžΌαžœ', 'αžαžΆαž›', 'αžαŸ„αŸ‡', 'αžšαŸ„αž„', 'αž˜αŸ’αžŸαžΆαž‰αŸ‹', 'មមី', 'αž˜αž˜αŸ‚', 'αžœαž€', 'αžšαž€αžΆ', 'αž…', 'αž€αž»αžš']

// Get era year names (10-year cycle)
$eraYears = KhmerDate::getEraYearNames();
// ['αžŸαŸ†αžšαžΉαž‘αŸ’αž’αž·αžŸαŸαž€', 'αž―αž€αžŸαŸαž€', 'αž‘αŸ„αžŸαŸαž€', 'αžαŸ’αžšαžΈαžŸαŸαž€', 'αž…αžαŸ’αžœαžΆαžŸαŸαž€', 'αž”αž‰αŸ’αž…αžŸαŸαž€', 'αž†αžŸαŸαž€', 'αžŸαž”αŸ’αžαžŸαŸαž€', 'αž’αžŠαŸ’αž‹αžŸαŸαž€', 'αž“αž–αŸ’αžœαžŸαŸαž€']

Utility Functions (Utils Class)

use PPhatDev\LunarDate\Utils;

// Parse Khmer date string
$parsed = Utils::parseKhmerDate('αŸ‘αŸ’αž€αžΎαž αžαŸ‚αž’αžŸαŸ’αžŸαž»αž‡ αž–.ស. ្αŸ₯៦៧');
var_dump($parsed); // Returns parsed date components

// Get Khmer month date range
$monthRange = Utils::getKhmerMonthRange(5, 2567); // αž–αž·αžŸαžΆαž month in BE 2567
foreach ($monthRange as $day) {
    echo "Day {$day['day']}: {$day['lunar']} - {$day['gregorian']}\n";
}

// Find specific lunar days in a year
$fullMoons = Utils::findLunarDayOccurrences(15, 0, 2024); // All 15αž€αžΎαž in 2024
$newMoons = Utils::findLunarDayOccurrences(15, 1, 2024);  // All 15αžšαŸ„αž… in 2024

// Date difference in Khmer terms
$date1 = new KhmerDate('2024-01-01');
$date2 = new KhmerDate('2024-12-31');
$diff = Utils::diffInKhmer($date1, $date2);
echo "Difference: {$diff['days']} days, {$diff['months']} months";

// Buddhist holidays for a specific year
$holidays = Utils::getBuddhistHolidays(2024);
foreach ($holidays as $holiday) {
    echo "{$holiday['name']}: {$holiday['date']}\n";
}

// Era conversion utilities
$beYear = Utils::convertEra(2024, 'AD', 'BE');    // 2567
$adYear = Utils::convertEra(2567, 'BE', 'AD');    // 2024
$jsYear = Utils::convertEra(2024, 'AD', 'JS');    // 1385

// Date validation
$isValid = Utils::isValidKhmerDate(15, 5, 2567); // true
$isValid = Utils::isValidKhmerDate(31, 5, 2567); // false (invalid lunar day)

// Season information based on lunar calendar
$date = new KhmerDate('2024-07-15');
$season = Utils::getSeason($date);
echo $season['name'];        // αžšαžŠαžΌαžœαžœαžŸαŸ’αžŸαžΆ (Rainy Season)
echo $season['name_en'];     // Rainy Season

Formatting System

The library supports extensive formatting tokens inspired by momentkh:

Formatting Tokens

Token Description Example Output
W αžαŸ’αž„αŸƒαž“αŸƒαžŸαž”αŸ’αžŠαžΆαž αŸ (Day of week full) αž’αž„αŸ’αž‚αžΆαžš
w αžαŸ’αž„αŸƒαž“αŸƒαžŸαž”αŸ’αžŠαžΆαž αŸαž€αžΆαžαŸ‹ (Day of week short) ធ
d αžαŸ’αž„αŸƒαž‘αžΈ (Lunar day count) ៑្
D αžαŸ’αž„αŸƒαž‘αžΈ ០៑-៑αŸ₯ (Lunar day with leading zero) ០៨
n αž€αžΎαž ឬ αžšαŸ„αž… (Moon status short) αž€
N αž€αžΎαž ឬ αžšαŸ„αž… (Moon status full) αž€αžΎαž
m αžαŸ‚αž…αž“αŸ’αž‘αž‚αžαž· (Lunar month) αž˜αž·αž‚αžŸαž·αžš
M αžαŸ‚αžŸαž»αžšαž·αž™αž‚αžαž· (Solar month) αž˜αž€αžšαžΆ
a αž†αŸ’αž“αžΆαŸ†αžŸαžαŸ’αžœ (Animal year) αž‡αžΌαž
e αžŸαŸαž€ (Era year) αžŸαŸ†αžšαžΉαž‘αŸ’αž’αž·αžŸαŸαž€
b αž†αŸ’αž“αžΆαŸ†αž–αž»αž‘αŸ’αž’αžŸαž€αžšαžΆαž‡ (Buddhist Era year) ្αŸ₯៦៧
c αž†αŸ’αž“αžΆαŸ†αž‚αŸ’αžšαž·αžŸαŸ’αžαžŸαž€αžšαžΆαž‡ (Gregorian year) ្០្ៀ
j αž†αŸ’αž“αžΆαŸ†αž…αž»αž›αŸ’αž›αžŸαž€αžšαžΆαž‡ (Jolak Sakaraj year) ៑៣៨αŸ₯

Advanced Formatting Examples

$date = new KhmerDate('2024-01-15');

// Basic formats
echo $date->toLunarDate('W');                           // αž’αžΆαž‘αž·αžαŸ’αž™
echo $date->toLunarDate('dN');                          // αŸ¨αž€αžΎαž  
echo $date->toLunarDate('dN αžαŸ‚m');                      // αŸ¨αž€αžΎαž αžαŸ‚αž˜αž·αž‚αžŸαž·αžš

// Complete formats
echo $date->toLunarDate('αžαŸ’αž„αŸƒW dN αžαŸ‚m αž†αŸ’αž“αžΆαŸ†a e');          // αžαŸ’αž„αŸƒαž’αžΆαž‘αž·αžαŸ’αž™ αŸ¨αž€αžΎαž αžαŸ‚αž˜αž·αž‚αžŸαž·αžš αž†αŸ’αž“αžΆαŸ†αž‡αžΌαž αžŸαŸ†αžšαžΉαž‘αŸ’αž’αž·αžŸαŸαž€
echo $date->toLunarDate('dN αžαŸ’αž„αŸƒW αžαŸ‚m αž–.ស. b');           // αŸ¨αž€αžΎαž αžαŸ’αž„αŸƒαž’αžΆαž‘αž·αžαŸ’αž™ αžαŸ‚αž˜αž·αž‚αžŸαž·αžš αž–.ស. ្αŸ₯៦៧

// Mixed calendar formats
echo $date->toLunarDate('αžαŸ’αž„αŸƒW αž‘αžΈ d αžαŸ‚M αž†αŸ’αž“αžΆαŸ† c');          // Mixed lunar/solar format
echo $date->toLunarDate('αž–.ស. b (αž‚.ស. c)');              // αž–.ស. ្αŸ₯៦៧ (αž‚.ស. ្០្ៀ)

KhmerFormatter Class

For advanced formatting needs, use the KhmerFormatter class directly:

use PPhatDev\LunarDate\KhmerFormatter;

$formatter = new KhmerFormatter();

// Number formatting
echo $formatter->toKhmerNumber('2024');           // ្០្ៀ
echo $formatter->fromKhmerNumber('្០្ៀ');        // 2024
echo $formatter->formatNumber(1234.56, 2);       // ៑,្៣ៀ.αŸ₯៦

// Date formatting
$date = new DateTime('2024-01-15');
echo $formatter->formatDate($date, 'full');      // Full Khmer Gregorian date
echo $formatter->getDayName($date);              // αž’αžΆαž‘αž·αžαŸ’αž™
echo $formatter->getMonthName($date);            // αž˜αž€αžšαžΆ
echo $formatter->getLunarMonthName(5);           // αž–αž·αžŸαžΆαž

// Currency and time formatting
echo $formatter->formatCurrency(1500.50);       // ៑,αŸ₯០០.αŸ₯០ αžšαŸ€αž›
echo $formatter->formatTime($date, true);       // 24-hour format
echo $formatter->formatTime($date, false);      // 12-hour format

// Text validation and utilities
$isKhmer = $formatter->isKhmerText('αž—αžΆαžŸαžΆαžαŸ’αž˜αŸ‚αžš');  // true
$isKhmer = $formatter->isKhmerText('English');   // false
echo $formatter->formatOrdinal(21);             // ្៑

// Format lunar date data
$lunarData = KhmerDate::findLunarDate(new DateTime('2024-01-15'));
echo $formatter->formatLunarDate($lunarData, 'full');

Comparison with Original MomentKH

This library is a faithful port of the JavaScript momentkh library. Here's how the APIs compare:

JavaScript (momentkh)

const moment = require('moment');
require('@thyrith/momentkh')(moment);

let today = moment();
console.log(today.toLunarDate());

let birthday = moment('1996-09-24');
console.log(birthday.toLunarDate('dN αžαŸ’αž„αŸƒW αžαŸ‚m αž–.ស. b'));

console.log(moment.getKhNewYearMoment(2024));

PHP (lunar-date)

use PPhatDev\LunarDate\KhmerDate;

$today = new KhmerDate();
echo $today->toLunarDate();

$birthday = new KhmerDate('1996-09-24');
echo $birthday->toLunarDate('dN αžαŸ’αž„αŸƒW αžαŸ‚m αž–.ស. b');

echo KhmerDate::getKhNewYearMoment(2024)->format('Y-m-d H:i');

Understanding the Khmer Calendar System

The Khmer calendar is a sophisticated lunisolar system that combines lunar phases with solar year calculations:

Calendar Structure

Months (αžαŸ‚)

The Khmer calendar has 14 possible months per year:

Regular Months (12 months):

  • αž˜αž·αž‚αžŸαž·αžš, αž”αž»αžŸαŸ’αžŸ, αž˜αžΆαžƒ, αž•αž›αŸ’αž‚αž»αž“, αž…αŸαžαŸ’αžš, αž–αž·αžŸαžΆαž, αž‡αŸαžŸαŸ’αž‹, ធអសអឍ, αžŸαŸ’αžšαžΆαž–αžŽαŸ, αž—αž‘αŸ’αžšαž”αž‘, αž’αžŸαŸ’αžŸαž»αž‡, αž€αžαŸ’αžŠαž·αž€

Leap Months (occur in leap years):

  • αž”αž‹αž˜αžΆαžŸαžΆαž (first ធអសអឍ)
  • αž‘αž»αžαž·αž™αžΆαžŸαžΆαž (second ធអសអឍ)

Days (αžαŸ’αž„αŸƒ)

Each lunar month follows the moon phases:

  • Waxing Moon (αž€αžΎαž): αŸ‘αž€αžΎαž, αŸ’αž€αžΎαž, ... ៑αŸ₯αž€αžΎαž (15 days)
  • Waning Moon (αžšαŸ„αž…): αŸ‘αžšαŸ„αž…, αŸ’αžšαŸ„αž…, ... αŸ‘αŸ€αžšαŸ„αž… or ៑αŸ₯αžšαŸ„αž… (14-15 days)

Year Systems (αž†αŸ’αž“αžΆαŸ†)

Animal Years (12-year cycle): αž‡αžΌαž, αž†αŸ’αž›αžΌαžœ, αžαžΆαž›, αžαŸ„αŸ‡, αžšαŸ„αž„, αž˜αŸ’αžŸαžΆαž‰αŸ‹, មមី, αž˜αž˜αŸ‚, αžœαž€, αžšαž€αžΆ, αž…, αž€αž»αžš

Era Years (10-year cycle): αžŸαŸ†αžšαžΉαž‘αŸ’αž’αž·αžŸαŸαž€, αž―αž€αžŸαŸαž€, αž‘αŸ„αžŸαŸαž€, αžαŸ’αžšαžΈαžŸαŸαž€, αž…αžαŸ’αžœαžΆαžŸαŸαž€, αž”αž‰αŸ’αž…αžŸαŸαž€, αž†αžŸαŸαž€, αžŸαž”αŸ’αžαžŸαŸαž€, αž’αžŠαŸ’αž‹αžŸαŸαž€, αž“αž–αŸ’αžœαžŸαŸαž€

Buddhist Era (BE): Gregorian year + 543/544 (depending on the time of year)

Leap Year Types

The Khmer calendar has three types of years:

  1. Regular Year (354 days): 12 months, normal lunar cycle
  2. Leap Month Year (αž’αž’αž·αž€αž˜αžΆαžŸ): 13 months (384 days) - adds αž”αž‹αž˜αžΆαžŸαžΆαž/αž‘αž»αžαž·αž™αžΆαžŸαžΆαž
  3. Leap Day Year (αž…αž“αŸ’αž‘αŸ’αžšαžΆαž’αž·αž˜αžΆαžŸ): Extra day added to αž‡αŸαžŸαŸ’αž‹ month (355 days)

Key Calculations

The library implements complex calculations including:

  • Bodithey (αž”αžΌαžαž·αžαžΈ): Lunar calendar adjustments
  • Avoman (αž’αžœαž˜αžΆαž“): Leap month calculations
  • Ahargun (αž’αž αžšαž‚αž»αžŽ): Leap day determinations
  • Soriyatra Lerng Sak: New Year timing calculations

Advanced Usage Examples

Working with Lunar Days

// Find all full moon days (15αž€αžΎαž) in 2024
$fullMoons = Utils::findLunarDayOccurrences(15, 0, 2024);
foreach ($fullMoons as $fullMoon) {
    echo "Full Moon: {$fullMoon['date']} - {$fullMoon['khmer']}\n";
}

// Find all new moon days (15αžšαŸ„αž…) in 2024  
$newMoons = Utils::findLunarDayOccurrences(15, 1, 2024);

Buddhist Holiday Calculations

// Get all Buddhist holidays for 2024
$holidays = Utils::getBuddhistHolidays(2024);
foreach ($holidays as $holiday) {
    echo "{$holiday['name']}: {$holiday['date']} ({$holiday['type']})\n";
}

Season Information

$date = new KhmerDate('2024-07-15');
$season = Utils::getSeason($date);

echo "Season: {$season['name']} ({$season['name_en']})\n";
echo "Description: {$season['description']}\n";

Era Conversion Examples

// Convert between different calendar systems
$currentYear = 2024;

$beYear = Utils::convertEra($currentYear, 'AD', 'BE');    // 2567
$jsYear = Utils::convertEra($currentYear, 'AD', 'JS');    // 1385

// Convert back
$adFromBE = Utils::convertEra($beYear, 'BE', 'AD');       // 2024

echo "Gregorian: $currentYear\n";
echo "Buddhist Era: $beYear\n";
echo "Jolak Sakaraj: $jsYear\n";

Date Range Operations

// Get all days in a specific Khmer month
$monthData = Utils::getKhmerMonthRange(5, 2567); // αž–αž·αžŸαžΆαž month, BE 2567

foreach ($monthData as $day) {
    echo "Day {$day['day']}: {$day['lunar']} - {$day['gregorian']}\n";
}

// Validate Khmer dates
$isValid = Utils::isValidKhmerDate(15, 5, 2567);  // true - valid full moon
$isValid = Utils::isValidKhmerDate(31, 5, 2567);  // false - invalid lunar day

Development & Testing

Development Setup

# Clone the repository
git clone https://github.com/pphatdev/lunar-date.git
cd lunar-date

# Install dependencies
composer install

# Run examples to test functionality
php examples/demo.php
php examples/momentkh_examples.php
php examples/new_year.php
php examples/current_be_year.php

Quality Assurance

This library maintains high code quality standards:

# Run complete test suite
composer test
# or
make test

# Generate code coverage report
composer test:coverage
# or
make coverage

# Run all quality checks
make quality

Testing Coverage

The library includes comprehensive test coverage:

  • Unit Tests: All classes and methods tested with PHPUnit
  • Integration Tests: End-to-end calendar conversion testing
  • Edge Case Testing: Boundary conditions and error scenarios
  • Simple Test: Basic functionality verification with tests/simple_test.php

Code Quality Metrics

  • βœ… CI/CD Pipeline: GitHub Actions with multi-version PHP testing (7.4, 8.0, 8.1, 8.2, 8.3)
  • βœ… PSR-12 Compliance: Modern PHP coding standards
  • βœ… Type Safety: Comprehensive type hints and strict types
  • βœ… Error Handling: Proper exception handling and validation
  • βœ… Documentation: Complete PHPDoc annotations

Project Structure

src/
β”œβ”€β”€ KhmerDate.php           # Main date class with conversion methods
β”œβ”€β”€ KhmerFormatter.php      # Formatting and localization utilities
β”œβ”€β”€ KhmerCalculator.php     # Core calendar calculations and algorithms
β”œβ”€β”€ SoriyatraLerngSak.php   # Khmer New Year calculations
β”œβ”€β”€ Utils.php               # Utility functions and helper methods
└── Constants.php           # Calendar constants and definitions

examples/
β”œβ”€β”€ demo.php               # Basic usage examples and demonstrations
β”œβ”€β”€ momentkh_examples.php  # MomentKH compatibility demos
β”œβ”€β”€ new_year.php          # Khmer New Year calculation examples
└── current_be_year.php   # Buddhist Era year examples

tests/
β”œβ”€β”€ KhmerDateTest.php      # Main class tests
β”œβ”€β”€ KhmerCalculatorTest.php # Calculation tests  
β”œβ”€β”€ ConstantsTest.php      # Constants validation
└── simple_test.php        # Basic functionality test

.github/workflows/
└── ci.yml                 # GitHub Actions CI configuration

Contributing

We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Contribution Guidelines

  1. Fork the repository and create a feature branch
  2. Follow PSR-12 coding standards
  3. Add tests for new functionality
  4. Update documentation as needed
  5. Run quality checks before submitting
# Before submitting PR
make quality     # Run all quality checks
composer test    # Ensure all tests pass

Development Workflow

See CONTRIBUTING.md for detailed contribution guidelines.

Development Priorities

  • Performance Optimization: Improve calculation efficiency
  • Extended Formatting: More formatting options and tokens
  • Historical Accuracy: Enhance historical date accuracy
  • Documentation: Expand examples and use cases

Requirements

  • PHP 7.4+: Modern PHP with type hints support
  • No External Dependencies: Uses only PHP standard library
  • Composer: For autoloading and dependency management

License

This project is licensed under the MIT License - see the LICENSE file for details.

Credits & Acknowledgments

Original Work

  • ThyrithSor - Creator of the original momentkh JavaScript library
  • Moment.js Team - Inspiration for the API design philosophy

Academic References

  • "Pratitin Soryakkatik-Chankatik 1900-1999" by Mr. Roath Kim Soeun
  • cam-cc.org - Cambodian calendar calculations
  • dahlina.com - Historical calendar references

Special Thanks

Special appreciation to ThyrithSor for creating the foundational momentkh library and making Khmer calendar calculations accessible to developers worldwide. This PHP port aims to bring the same functionality to the PHP ecosystem while maintaining compatibility with the original JavaScript API.

Related Projects

Support

  • Documentation: This README and inline PHPDoc comments
  • Examples: Check the examples/ directory for usage patterns
  • Issues: Report bugs and request features via GitHub Issues
  • Discussions: Use GitHub Discussions for questions and community support

Note: This library focuses on historical accuracy and cultural authenticity for Khmer calendar calculations. While extensively tested, please verify critical date calculations for important applications.

About

PHP Luna Conversion πŸ§‘β€πŸ³

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published