Chrono is a PHP natural language date parser inspired by wanasit/chrono.
It parses text like tomorrow at 4pm, next Friday, 10 August - 12 September, and mañana into immutable Carbon instances.
Install Chrono with Composer:
composer require directorytree/chronoParse the first date from a string:
use DirectoryTree\Chrono\Chrono;
$date = Chrono::date('tomorrow at 4pm', '2026-06-23 09:00');
$date->toDateTimeString(); // 2026-06-24 16:00:00Parse all dates from a string:
$dates = Chrono::dates('Review from Monday to Friday', '2026-06-23');
$dates[0]->toDateString(); // 2026-06-22Parse detailed results from a string:
$results = Chrono::parse('Review from Monday to Friday', '2026-06-23');
$results[0]->text; // Monday to Friday
$results[0]->start->date()->toDateString(); // 2026-06-22
$results[0]->end?->date()->toDateString(); // 2026-06-26Create a parser when you want to reuse a locale or configuration:
$chrono = Chrono::english();
$chrono->date('next Friday', '2026-06-23');
$chrono->parse('today, tomorrow, and Friday', '2026-06-23');Chrono also includes casual and strict English variants:
Chrono::casual()->date('tomorrow');
Chrono::strict()->parse('tomorrow'); // []Chrono includes parser factories for supported locales:
Chrono::spanish()->date('mañana');
Chrono::french()->date('demain');
Chrono::german()->date('morgen');
Chrono::italian()->date('domani');
Chrono::russian()->date('завтра');
Chrono::ukrainian()->date('завтра');
Chrono::japanese()->date('明日');
Chrono::chinese()->date('明天');Locale aliases are also available:
Chrono::es();
Chrono::fr();
Chrono::de();
Chrono::it();
Chrono::nl();
Chrono::fi();
Chrono::sv();
Chrono::pt();
Chrono::ru();
Chrono::uk();
Chrono::ja();
Chrono::vi();
Chrono::zh();Use Chrono::british(), Chrono::gb(), or Chrono::enGb() for British English slash dates:
Chrono::gb()->date('6/10/2018', '2018-01-01');Relative expressions are resolved against the reference date you provide:
Chrono::date('next week', '2026-06-23');You may pass a CarbonInterface, a date string, or a reference array with a timezone:
Chrono::date('tomorrow at 9am', [
'instant' => '2026-06-23 12:00:00',
'timezone' => 'America/Toronto',
]);parse() returns parsed result objects with the original text, start components, and optional end components:
$result = Chrono::parse('10am - 11am tomorrow', '2026-06-23')[0];
$result->text; // 10am - 11am tomorrow
$result->start->date()->toDateTimeString(); // 2026-06-24 10:00:00
$result->end?->date()->toDateTimeString(); // 2026-06-24 11:00:00Parsed components expose known and implied date parts for cases where you need more detail than the final Carbon instance:
$result->start->isCertain('day');
$result->start->get('hour');
$result->start->date();Chrono follows a parser and refiner pipeline. Parsers extract possible dates from text, and refiners clean up, merge, filter, or adjust those results.
Add custom parsers or refiners to an existing parser instance:
$chrono = Chrono::casual()
->withParser(new CompanyHolidayParser)
->withRefiner(new BusinessHoursRefiner);Remove a parser or refiner by class name:
$chrono = $chrono
->withoutParser(CompanyHolidayParser::class)
->withoutRefiner(BusinessHoursRefiner::class);Parser instances are immutable. Each customization method returns a new instance:
$default = Chrono::english();
$custom = $default->withParser(new CompanyHolidayParser);Run the test suite:
./vendor/bin/pestRun the style checker:
./vendor/bin/pint --testChrono is open-sourced software licensed under the MIT license.