Installation
Install the package via Composer:
composer require asorasoft/chhankitek
The only runtime dependency is nesbot/carbon, so the package works in any PHP project — Laravel is optional. Inside a Laravel application it automatically registers its service provider, so no additional configuration is needed.
Basic Usage
Using the Trait
In your Laravel controller, use the HasChhankitek trait:
use Asorasoft\Chhankitek\Traits\HasChhankitek;
use Carbon\CarbonImmutable;
class YourController extends Controller
{
use HasChhankitek;
public function index()
{
$lunarDate = $this->chhankitek(
CarbonImmutable::now()->setTimezone('Asia/Phnom_Penh')
);
echo $lunarDate->toString();
// ថ្ងៃច័ន្ទ ៤ រោច ខែបឋមាសាឍ ឆ្នាំឆ្លូវ ត្រីស័ក ពុទ្ធសករាជ ២៥៦៥
}
}
Using the Helper Function
Alternatively, use the global toLunarDate helper:
use Carbon\CarbonImmutable;
$lunarDate = toLunarDate(
CarbonImmutable::now()->setTimezone('Asia/Phnom_Penh')
);
echo $lunarDate->toString();
Important
Always use CarbonImmutable (not Carbon) and set the timezone to 'Asia/Phnom_Penh'.
Pure PHP Usage (without Laravel)
Laravel is not required. Instantiate Chhankitek directly and read the lunar date from the formatKhmerDate property:
require 'vendor/autoload.php';
use Asorasoft\Chhankitek\Chhankitek;
use Carbon\CarbonImmutable;
$target = CarbonImmutable::now()->setTimezone('Asia/Phnom_Penh');
$lunarDate = (new Chhankitek($target))->formatKhmerDate;
echo $lunarDate->toString();
// ថ្ងៃច័ន្ទ ៤ រោច ខែបឋមាសាឍ ឆ្នាំឆ្លូវ ត្រីស័ក ពុទ្ធសករាជ ២៥៦៥
The toLunarDate() helper is also available outside Laravel:
$lunarDate = toLunarDate(
CarbonImmutable::now()->setTimezone('Asia/Phnom_Penh')
);
Without a Laravel application, conversions automatically use a framework-free in-memory cache. See Caching to plug in your own cache store.
Available Methods
The KhmerLunarDate object provides the following methods:
getDayOfWeek()
Returns the Khmer day of the week.
$lunarDate->getDayOfWeek(); // អាទិត្យ, ច័ន្ទ, អង្គារ, ពុធ, ព្រហស្បតិ៍, សុក្រ, សៅរ៍
getLunarDay()
Returns the lunar day with moon status (កើត waxing, រោច waning).
$lunarDate->getLunarDay(); // ១កើត, ២កើត, ១៤រោច, etc.
getLunarMonth()
Returns the Khmer lunar month name.
$lunarDate->getLunarMonth(); // ចេត្រ, ពិសាខ, ជេស្ឋ, អាសាឍ, etc.
getLunarZodiac()
Returns the animal year (Khmer zodiac).
$lunarDate->getLunarZodiac(); // ជូត, ឆ្លូវ, ខាល, ថោះ, រោង, ម្សាញ់, ...
getLunarEra()
Returns the era year (10-year cycle).
$lunarDate->getLunarEra(); // ត្រីស័ក, ចត្វាស័ក, បញ្ចស័ក, etc.
getLunarYear()
Returns the Buddhist Era year in Khmer numerals.
$lunarDate->getLunarYear(); // ២៥៦៥, ២៥៦៦, etc.
toString()
Returns the complete lunar date as a formatted string.
$lunarDate->toString();
// ថ្ងៃច័ន្ទ ៤ រោច ខែបឋមាសាឍ ឆ្នាំឆ្លូវ ត្រីស័ក ពុទ្ធសករាជ ២៥៦៥
Caching
Converted dates are cached for 365 days to minimize computational overhead. The cache is swappable via the CacheRepository interface, so it works the same with or without Laravel:
- — Inside Laravel — automatically uses Laravel's cache system (
LaravelCache), respecting your configured driver (Redis, Memcached, file, etc.). No setup required. - — Pure PHP — falls back to an in-memory cache (
ArrayCache) that de-duplicates lookups within a single request or script run.
Providing your own cache
Pass any implementation of Asorasoft\Chhankitek\Cache\CacheRepository as the second constructor argument:
use Asorasoft\Chhankitek\Cache\ArrayCache;
use Asorasoft\Chhankitek\Cache\CacheRepository;
use Asorasoft\Chhankitek\Chhankitek;
// Use the bundled in-memory cache explicitly
$lunarDate = (new Chhankitek($target, new ArrayCache))->formatKhmerDate;
// Or wire up your own (e.g. a PSR-16 adapter)
final class Psr16Cache implements CacheRepository
{
public function __construct(private \Psr\SimpleCache\CacheInterface $cache) {}
public function remember(string $key, int $ttl, callable $callback): mixed
{
if ($this->cache->has($key)) {
return $this->cache->get($key);
}
$value = $callback();
$this->cache->set($key, $value, $ttl);
return $value;
}
}
Requirements
Examples
Example 1 — Convert current date
$today = toLunarDate(
CarbonImmutable::now()->setTimezone('Asia/Phnom_Penh')
);
echo "Day: " . $today->getDayOfWeek();
echo "Lunar Day: " . $today->getLunarDay();
echo "Month: " . $today->getLunarMonth();
echo "Year: " . $today->getLunarYear();
Example 2 — Convert specific date
$date = CarbonImmutable::createFromFormat(
'Y-m-d',
'2024-04-14'
)->setTimezone('Asia/Phnom_Penh');
$lunarDate = toLunarDate($date);
echo $lunarDate->toString();
Example 3 — Display in a Blade template
// In Controller
public function index()
{
$lunarDate = toLunarDate(
CarbonImmutable::now()->setTimezone('Asia/Phnom_Penh')
);
return view('welcome', compact('lunarDate'));
}
// In Blade (welcome.blade.php)
<div>
<h1>{{ $lunarDate->toString() }}</h1>
<p>Animal Year: {{ $lunarDate->getLunarZodiac() }}</p>
</div>
Example 4 — Using in an API
Route::get('/api/lunar-date', function (Request $request) {
$date = $request->input('date')
? CarbonImmutable::parse($request->input('date'))
: CarbonImmutable::now();
$date = $date->setTimezone('Asia/Phnom_Penh');
$lunarDate = toLunarDate($date);
return response()->json([
'gregorian' => $date->format('Y-m-d'),
'lunar' => [
'full' => $lunarDate->toString(),
'day_of_week' => $lunarDate->getDayOfWeek(),
'lunar_day' => $lunarDate->getLunarDay(),
'month' => $lunarDate->getLunarMonth(),
'zodiac' => $lunarDate->getLunarZodiac(),
'era' => $lunarDate->getLunarEra(),
'year' => $lunarDate->getLunarYear(),
],
]);
});
Understanding the Khmer Calendar
Lunar Months
The Khmer lunar calendar has 12 standard months. In leap years, an additional month (បឋមាសាឍ) is added:
Lunar Days
Each lunar month is divided into two phases:
- — កើត (Kaet): Waxing moon (days 1–15)
- — រោច (Roch): Waning moon (days 1–15)
Zodiac Animals (12-year cycle)
Leap Years
The Khmer calendar has two types of leap years:
- — Leap Month Year (Adhikameas): An extra 13th month (បឋមាសាឍ) is added, making the year 384 days long.
- — Leap Day Year: An extra day is added to the month of ជេស្ឋ, making the year 355 days long.
- — Regular Year: 354 days with 12 months.
Learn more: Visit Khmer Calendar for detailed information about the system.
API Reference
Chhankitek Class
new Chhankitek(CarbonImmutable $target, ?CacheRepository $cache = null)
Framework-free entry point. The resulting lunar date is on the formatKhmerDate property. The optional CacheRepository defaults to Laravel's cache when an application is bound, otherwise an in-memory cache.
HasChhankitek Trait
chhankitek(CarbonImmutable $target, ?CacheRepository $cache = null): KhmerLunarDate
Converts a Gregorian date to Khmer lunar date format.
Helper Function
toLunarDate(CarbonImmutable $target, ?CacheRepository $cache = null): KhmerLunarDate
Global helper function for date conversion.
KhmerLunarDate Methods
| Method | Returns | Description |
|---|---|---|
| getDayOfWeek() | string | Khmer day of week |
| getLunarDay() | string | Lunar day with moon status |
| getLunarMonth() | string | Khmer lunar month name |
| getLunarZodiac() | string | Animal year (zodiac) |
| getLunarEra() | string | Era year (10-year cycle) |
| getLunarYear() | string | Buddhist Era year (Khmer numerals) |
| toString() | string | Complete formatted date string |
Contributing
Contributions are welcome. Please see the CONTRIBUTING.md file for details.
Found a security issue? Please email mabhelitc@gmail.com instead of using the issue tracker.