PHPackages                             hnesk/todate - 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. hnesk/todate

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

hnesk/todate
============

An easy to use DSL for date expression

v1.0.2(5y ago)2181GPL-3.0PHPPHP &gt;=7.0.0

Since Nov 1Pushed 5y ago1 watchersCompare

[ Source](https://github.com/hnesk/ToDate)[ Packagist](https://packagist.org/packages/hnesk/todate)[ Docs](https://github.com/hnesk/ToDate)[ RSS](/packages/hnesk-todate/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (4)Used By (0)

ToDate
======

[](#todate)

A PHP date expression library with a corresponding domain specific language (DSL)

Describing DateConditions as strings (DSL)
------------------------------------------

[](#describing-dateconditions-as-strings-dsl)

This library contains a DSL (domain specific language) to describe complex date scenarios as simple strings. This DSL expressions get parsed to a tree of expressions, that can be evaluated for any given date.

Sounds complicated? No it isn't.

Imagine your garbage gets picked up, every first monday each month. How would communicate that fact to a machine?

```
use ToDate\ToDate;
$garbageTime = 'DayOfWeekOfMonth=1MON';
foreach (ToDate::conditionalIterator('2021-01-01', '2021-12-31', $garbageTime) as $garbageDay) {
    echo $garbageDay->format('d.m.Y, l') . PHP_EOL;
}
```

What about every first and third monday each month?

```
$garbageTime = 'DayOfWeekOfMonth=1,3MON';
```

What about every second and last monday each month? (using pythons notion of negative numbers as counting from the end).

```
$garbageTime = 'DayOfWeekOfMonth=2,-1MON';
```

Ok, let's say every monday, but not if its Easter monday (constant `Easter` means Easter sunday)

```
$garbageTime = 'DayOfWeek=MON AND(NOT(Date=Easter+1)';
```

Or whit monday (50 days after Easter sunday), independence day, or christmas?

```
$garbageTime = 'DayOfWeek=MON AND NOT(Date=Easter+1 OR Date=Easter+50 OR DayAndMonth=04/07 OR DayAndMonth=25/12 OR DayAndMonth=26/12)';
```

All date conditions in the [ToDate/Condition](src/ToDate/Condition) namespace can be created with the corresponding DSL string syntax

### DSL Building Blocks

[](#dsl-building-blocks)

All of these conditions are mapped to single `\ToDate\Condition\AbstractDateCondition` instance.

#### Date

[](#date)

Just one fixed date, example only on Independence Day 2021

```
\ToDate\ToDate::condition('Date=2021-07-04') == new \ToDate\Condition\DateCondition(new DateTime('2021-07-04'));
```

#### Easter based date conditions

[](#easter-based-date-conditions)

Every whit sunday

```
\ToDate\ToDate::condition('Date=Easter+49') == new \ToDate\Condition\EasterBasedCondition(\ToDate\Condition\EasterBasedCondition::WHIT_SUNDAY /* or 49 */);
```

#### DateModulo

[](#datemodulo)

Every 2 weeks (14 days) starting from 2021-03-12

```
\ToDate\ToDate::condition('DateModule=2021-03-12%14') == new \ToDate\Condition\DateModuloOffsetCondition(new DateTime('2021-03-12'), 14);
```

#### DayAndMonth

[](#dayandmonth)

Every independence day

```
\ToDate\ToDate::condition('DayAndMonth=4/7') == new \ToDate\Condition\DayAndMonthCondition(4,7);
```

#### DayOfMonth

[](#dayofmonth)

Every 1st and 15th each month

```
\ToDate\ToDate::condition('DayOfMonth=1,15') == new \ToDate\Condition\DayOfMonthCondition([1,15]);
```

or every 1st till 9th each month

```
\ToDate\ToDate::condition('DayOfMonth=1-9') == new \ToDate\Condition\DayOfMonthCondition([1,2,3,4,5,6,7,8,9]);
```

#### DayOfWeek

[](#dayofweek)

Every saturday and sunday

```
\ToDate\ToDate::condition('DayOfWeek=SAT,SUN') == new \ToDate\Condition\DayOfWeekCondition([\ToDate\Condition\DayOfWeekCondition::SAT, \ToDate\Condition\DayOfWeekCondition::SUN]);
```

#### DayOfWeekMonth

[](#dayofweekmonth)

Every 1st and 3rd monday

```
\ToDate\ToDate::condition('DayOfWeekOfMonth=1,3MON') == new \ToDate\Condition\DayOfWeekOfMonthCondition([1,3], \ToDate\Condition\DayOfWeekCondition::MON);
```

Every 2nd and last (=-1 like in python) monday

```
\ToDate\ToDate::condition('DayOfWeekOfMonth=2,-1MON') == new \ToDate\Condition\DayOfWeekOfMonthCondition([1,3], \ToDate\Condition\DayOfWeekCondition::MON);
```

#### Month

[](#month)

In the summertime

```
\ToDate\ToDate::condition('Month=3-10') == new \ToDate\Condition\MonthCondition([3,4,5,6,7,8,9,10]);
```

#### Year

[](#year)

The corona years

```
\ToDate\ToDate::condition('Year=2020,2021') == new \ToDate\Condition\YearCondition([2020,2021]);
```

### Combinig Conditions with logical operators

[](#combinig-conditions-with-logical-operators)

All conditions can be combined with `AND`, `OR` and `NOT` to form complex date conditions.

```
\ToDate\ToDate::condition('DayOfWeek=MON AND NOT(Date=Easter+1)') == new \ToDate\Condition\IntersectionCondition(
    new \ToDate\Condition\DayOfWeekCondition(\ToDate\Condition\DayOfWeekCondition::MON),
    new \ToDate\Condition\NotCondition(new \ToDate\Condition\EasterBasedCondition(1))
);
```

Examples
--------

[](#examples)

see also the [executable examples](examples)

```
use ToDate\ToDate;

$secondOrLastSaturday = ToDate::condition('DayOfWeekOfMonth = 2,-1SAT');
var_dump($secondOrLastSaturday->contains(new \DateTime('2014-11-29')));
# bool(true)

var_dump($secondOrLastSaturday->contains(new \DateTime('2014-11-09')));
# bool(false)

$everySecondAndLastSaturydayIn2021 = ToDate::conditionalIterator('2021-01-01', '2021-12-31', $secondOrLastSaturday);
foreach ($everySecondAndLastSaturydayIn2021 as $saturday) {
    echo $saturday->format('d.m.Y, l') . PHP_EOL;
}
# 09.01.2021, Saturday
# 30.01.2021, Saturday
# 13.02.2021, Saturday
# ...
# 11.12.2021, Saturday
# 25.12.2021, Saturday

/* All german holidays 2021 in one simple string! */
$germanHolidays = 'DayAndMonth = 1/1 OR Date = Easter-2 OR Date = Easter+1 OR DayAndMonth = 1/5 OR Date = Easter+39 OR Date = Easter+50 OR Date = Easter+60 OR DayAndMonth = 3/10 OR DayAndMonth = 1/11 OR DayAndMonth = 25/12 OR DayAndMonth = 26/12';

$holidays = ToDate::conditionalIterator('2021-01-01', '2021-12-31' ,$germanHolidays);
foreach ($holidays as $holiday) {
    echo $holiday->format('d.m.Y, l') . PHP_EOL;
}

# 01.01.2021, Friday
# 02.04.2021, Friday
# 05.04.2021, Monday
# 01.05.2021, Saturday
# 13.05.2021, Thursday
# 24.05.2021, Monday
# 03.06.2021, Thursday
# 03.10.2021, Sunday
# 01.11.2021, Monday
# 25.12.2021, Saturday
# 26.12.2021, Sunday
```

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 100% 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

Every ~1162 days

Total

3

Last Release

1885d ago

PHP version history (2 changes)1.0.0PHP &gt;=5.3.0

v1.0.1PHP &gt;=7.0.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/6d0d0855186216bf09d14f950de078217113198311a9685c2601667088ca39db?d=identicon)[hnesk](/maintainers/hnesk)

---

Top Contributors

[![hnesk](https://avatars.githubusercontent.com/u/186821?v=4)](https://github.com/hnesk "hnesk (22 commits)")

---

Tags

dateDSLholidays

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/hnesk-todate/health.svg)

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

###  Alternatives

[rlanvin/php-rrule

Lightweight and fast recurrence rules for PHP (RFC 5545)

69810.6M39](/packages/rlanvin-php-rrule)[knplabs/knp-time-bundle

Making your dates and durations look sensible and descriptive

6308.9M39](/packages/knplabs-knp-time-bundle)[league/period

Time range API for PHP

7335.4M21](/packages/league-period)[brick/date-time

Date and time library

3623.3M60](/packages/brick-date-time)[aeon-php/calendar

PHP type safe, immutable calendar library

2079.7M16](/packages/aeon-php-calendar)[kartik-v/yii2-widget-datepicker

Enhanced Yii2 wrapper for the bootstrap datepicker plugin (sub repo split from yii2-widgets).

1097.0M60](/packages/kartik-v-yii2-widget-datepicker)

PHPackages © 2026

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