# Change Log
All notable changes to this project will be documented in this file.

## [2.1.0] - 2026-10-31
### Added
- PHP bindings (PHP 8.0 and newer): `dateblock('0 0 9', ref: $tokyo)`
  returns a `DateTimeImmutable`, reading the cron in the timezone of `$ref`.
  Install with `pie install caronc/dateblock` or the `php-dateblock`
  package.
- Node.js bindings (Node.js 20 and newer): `await dateblock('0 0 9',
  { timeZone: 'Asia/Tokyo' })` waits without blocking, and `next()` only
  works the time out.  Install with `npm install @caronc/dateblock`.
- Python: `await dateblock.wait('0 0 9')` waits with asyncio, without
  blocking other tasks; it takes the same `cron`, `ref` and `isc` as
  `dateblock()`.
- Month and weekday names, as crontab allows: `0 0 9 * * Mon-Fri`,
  `-m Jan,Jul`.  A backwards range of names (`Sat-Sun`) is refused, since
  it would mean every day.
- A day of the week of 7 means Sunday, as in crontab (`Fri-7`).
- crontab's shortcuts: `@hourly`, `@daily` (`@midnight`), `@weekly`,
  `@monthly` and `@yearly` (`@annually`), optionally followed by a drift
  (`@daily +30`).
- List the next few times without waiting, to check a schedule:
  `dateblock -C 5 -i -c '0 9 * * Mon-Fri'`, and in the bindings
  `dateblock.upcoming()` (Python), `dateblock_upcoming()` (PHP) and
  `upcoming()` (Node.js).  Up to 1000; just the next one unless told
  otherwise.

### Changed
- Node.js: the add-on now comes ready built for Linux (x64 and arm64, glibc
  and musl/Alpine), macOS (Intel and Apple silicon) and Windows (x64 and
  arm64), so `npm install @caronc/dateblock` compiles nothing and has no
  install step to approve on npm 12.  On any other computer, build it once
  with `npm explore @caronc/dateblock -- npm run build`.
- macOS and Windows wait with the system's own timer, set to the exact
  moment, instead of waking every second: it still fires on time if the
  computer sleeps or the clock is changed.  As a safety net the clock is
  also checked once an hour, a minute before the moment, and every second
  over the final minute.  Linux is unchanged (it already slept until the
  exact time).

### Fixed
- Node.js on Windows: a syntax error's message could come out garbled (or
  empty), since the add-on read it after it had been freed.
- Error messages write every byte of the input that isn't plain printable
  text as `\xNN` (not just control characters), so nothing in a bad cron
  can upset a terminal or a log.
- The Python, PHP and Node.js bindings only copy the start of a huge cron
  string before refusing it, instead of all of it.
- Python: when the clocks go back and a time happens twice, the second one
  comes back with `fold=1`, so its `timestamp()` is right.
- Node.js: a wait that spans the computer sleeping (or the clock being
  changed) now ends within a minute of the right moment, instead of late
  by however long the computer slept.

## [2.0.0] - 2026-10-26
The project is now called **dateblock** (it used to be datetools).

### Added
- Read a schedule in another timezone: `--timezone` (`-z`) on the command
  line, or a timezone-aware `datetime` in Python.
- Run a command once the time is reached, ie:
  `dateblock -n /15 -- ./backup.sh`; dateblock exits with the command's
  own exit code.
- Range steps such as `1-10/3` (1, 4, 7 and 10).
- Error messages that say what is wrong, ie: `minute '99': 99 is outside of
  0-59`.
- The `libdateblock` shared library, with headers and a pkg-config file.
- Packages for Fedora, RHEL 9 and 10, Debian 13, Arch Linux and Homebrew,
  and Python wheels for Linux, macOS and Windows (Python 3.9 to 3.14).
- A complete man page.

### Changed
- `--isc` reads an entry exactly as crontab(5) does: the day of the month
  OR the day of the week may match, and `*/5` days are the 1st, 6th, 11th...
- Fields left out only reset to their lowest value when they are smaller
  than the smallest field given: `/5 * 3,4` is every 5th second during
  hours 3 and 4.
- Unclear entries such as `5-`, `5,,6` and `*,5` are now errors instead of
  quietly matching something else.
- Much faster: long lists such as `0-59 0-59 0-23` cost the same as single
  values.
- Blocking wakes up exactly on the second, and Ctrl-C interrupts it.
- Boost is no longer needed.
- Python: Python 3 only (`from dateblock import dateblock` still works).
  A bad schedule raises `SyntaxError`, one that never happens raises
  `ValueError`, and an unsupported `ref` raises `TypeError`.

### Removed
- The datemath tool; `date -d` (ie: `date -d '+3 days -2 hours'`) does the
  same job.

### Fixed
- A schedule that never happens (ie: February 31st) is reported as an
  error, while lists that only partly exist (ie: the 30th and 31st of
  February and March) find the dates that do.
- Rare dates such as February 29th on a given weekday are found.
- Times around daylight saving changes and month ends are correct (ie: the
  31st no longer rolls into the next month).
- A month-only schedule (ie: `-m 3`) starts on the 1st.
- Date formats such as %I, %j, %P, %U, %x, %X and %h print correctly.
- Very large drift values no longer loop forever.
- Python: errors no longer end the Python interpreter.

## [1.0.3] - 2018-05-31
### Changed
- Fixed the padding of dates (padding with a zero).
- PyPI support.

## [1.0.0] - 2017-04-21
### Added
- The drift can be given inline in the cron with a plus (+): `0 /5 +4` is
  the same as `0 /5 * * * * 4` (every 5 minutes, plus 4 seconds), and
  several drifts work too (`0 /5 +15,45`).
- Regular crontab entries (Internet Systems Consortium format) with
  `--isc`.

## [0.8.1] - 2015-08-17
### Changed
- Fixed the month missing from the printed time.

## [0.8.0] - 2013-10-26
### Added
- Initial release on GitHub.
