GNU findutils 4.10.0 re-dressed for the
BrightDate
time system. bfind, blocate,
bupdatedb, and bxargs — with
-after/-before predicates, a
%Wt printf format, and a -daystart
that floors to the BrightDate boundary. One sortable, timezone-free
scalar — everywhere.
find's time predicates — -mtime,
-newer, -newermt — are a perennial source of
confusion: -mtime -1 means "within the last 24 hours,
rounded down to integer days," -newermt needs an ISO 8601
string with the right timezone, and the results differ on Linux vs
macOS because stat's timestamp resolution and epoch
handling differ subtly between the two. Every script that filters
files by recency carries this invisible complexity.
BSH (BrightShell)
showed that the fix is not a better date-parsing library — it's a
better time representation. BrightDate is a single Float64:
decimal days since the astronomical epoch J2000.0, on a TAI substrate.
No timezone. No leap-second jumps. b − a = elapsed days,
always.
This fork carries that same fix into the findutils layer. If your
shell prints BrightDate (BSH, or any shell using
$BRIGHTEPOCH), and your file-search tool speaks
BrightDate, there is no translation step anywhere in the pipeline. The
number in your prompt is the number you pass to -after,
which is the number printed by -printf '%Wt'.
In one sentence:
BrightDate is a timezone-free SI-day count since J2000.0
(2000-01-01T11:58:55.816 UTC). BD 0.0 = the standard astronomical
epoch. BD 9628 ≈ May 2026. b − a = elapsed days, no
date library required.
find pain| Problem | What goes wrong |
|---|---|
| -mtime -1 | Rounds to integer days from "now", not a clean boundary |
| -newermt "2026-01-01" | Needs TZ; differs on macOS vs Linux |
| -printf "%T+" | Locale-dependent, not sortable as-is |
| Duration math |
Requires date -d, gdate, or Python
|
| Daystart | Midnight in local timezone — silently wrong in UTC+N |
| Feature | What it does |
|---|---|
| -after 9600 | Files whose mtime > BD 9600 — universal, exact |
| -before 9628 | Files whose mtime < BD 9628 — same scalar |
| %Wt / %Wa / %Wc / %WB | Print mtime/atime/ctime/btime as BrightDate decimal |
| -daystart | Floors to BD integer — same on every machine |
| -newerXY 9600 | All -newer variants accept BD literals |
Every time-sensitive surface in findutils now speaks the same float.
The changes are surgical: all four binaries are renamed (b
prefix) so they coexist with system
find/locate/xargs.
-after / -before
New predicates that accept a BrightDate scalar directly — no
string parsing, no timezone argument. Both compare against
mtime by default.
# files touched after BD 9600
bfind . -after 9600 -name '*.py'
# files older than BD 9000
bfind . -before 9000 -name '*.log' -delete
%Wt / %Wa / %Wc /
%WB
A new %W printf family prints file timestamps as
BrightDate decimals. t = mtime, a =
atime, c = ctime, B = birth time. Output
is plain float — sort with sort -n, diff with
awk.
bfind . -printf '%Wt %p\n' | sort -rn | head -5
# 9628.197104 ./src/pred.c
# 9628.195697 ./src/parser.c
# …
-daystart redefined
Standard -daystart floors to local midnight — a
timezone-dependent boundary. In bfind,
-daystart floors to the BrightDate integer boundary
(the same on every machine). Pair with -mtime for
"since BD boundary" queries.
# files changed since the start of BD 9628
bfind . -daystart -mtime -1
-newer* accepts BD
All -newerXY variants now try to parse the reference
value as a BrightDate literal first. If it looks like a BD float
(DDDDD.ddddd), it's used directly. Otherwise the
original ISO/file-path logic applies, so old scripts continue to
work unchanged.
bfind . -newermt 9628.0 -name '*.c'
bfind . -newerat 9600 -newer 9610
blocate — BD database stats
blocate shows the database modification time as a
BrightDate value in the statistics header, so you can instantly
compare "how stale is my locate database" against
$BRIGHTEPOCH with plain subtraction.
$ blocate --statistics
Database: /var/db/locate.database
Created: BD 9628.12 (5.32 h ago)
Entries: 6 423 144
The BrightDate conversion lives in a single
find/brightdate.c / brightdate.h with a
28-entry leap-second table. The same TAI/J2000 math as the
Rust crate
and the
npm package
— one formula, every platform.
brew tap digital-defiance/tap
brew install digital-defiance/tap/findutils-brightdate
This installs bfind, blocate,
bupdatedb, and bxargs into
$(brew --prefix)/bin. They coexist with system
find/locate/xargs without
shadowing them.
bfind ~ -maxdepth 2 -type f -printf '%Wt %p\n' | sort -rn | head -5
Build from source
A C compiler (clang or gcc),
autoconf, automake ≥ 1.16, and
gettext. macOS, Linux, and *BSD all work.
git clone https://github.com/Digital-Defiance/findutils-brightdate.git
cd findutils-brightdate
autoreconf -fi
./configure --prefix=/usr/local --disable-nls
make -C gl && make -C lib
make -C find bfind
make -C locate blocate bupdatedb
make -C xargs bxargs
sudo cp find/bfind locate/blocate locate/bupdatedb xargs/bxargs /usr/local/bin/
Want BrightDate throughout your whole shell? Install
BSH (BrightShell)
— a zsh-compatible shell where date, ls -l,
stat, history -d, and
$BRIGHTEPOCH all speak the same float.
bfind fits right in.
A zsh-compatible shell with BrightDate woven into every
time-related surface: date, ls -l,
stat, history -d, sched,
and $BRIGHTEPOCH. The natural home for
bfind pipelines.
brightdate
The Rust crate powering BSH internally. Also ships standalone CLI
tools (bdate, btime,
buptime, bcal, bwatch) via
the Homebrew tap.
@brightchain/brightdateTypeScript/JavaScript library. Same J2000.0 / TAI semantics, same epoch. Works in Node.js, Deno, and the browser.
All Digital Defiance BrightDate tools in one tap. Install
bfind, the Rust CLI tools, and BSH itself from a
single tap.
brew tap digital-defiance/tap
brew install findutils-brightdate
brew install bdate btime buptime bcal bwatch bsh