PostgreSQL has infinity in several type families, and this library gives it three different PHP shapes. The shape is not a style choice — it follows from what null already means in that position.
Floats: PHP’s INF and NAN
Items of real[] and double precision[], Cube coordinates and the geometric value objects use PHP’s native constants. PHP has a representation of its own, so nothing needs to be invented.
[\INF,-\INF,\NAN,1.5];// double precision[] -> {Infinity,-Infinity,NaN,1.5}newPoint(\INF,2.0);// point -> (Infinity,2)
Items of numeric[] are the exception: they stay strings so that arbitrary precision survives, and their non-finite values stay strings with them — 'NaN', 'Infinity', '-Infinity', spelled the way PostgreSQL prints them. See Numeric Array Type.
Range bounds: boolean flags
A range bound is marked with isLowerBoundedInfinity() / isUpperBoundedInfinity(), kept distinct from a null bound, because PostgreSQL keeps them distinct too:
null already carries “this end is unbounded”, so a bound of infinity needs a third state next to it — hence the flag. See Range Types, which also covers the NumericRange(0, INF) shorthand.
NaN needs no flag of its own. PostgreSQL orders it above every numeric value rather than leaving the end open, so it is a bound like any other and travels as NAN in the bound itself — the float shape above, inside a range. See NaN Bounds.
Array elements: an enum sentinel
Items of date[], timestamp[] and timestamptz[] read back as \DateTimeImmutable, which cannot hold infinity, and null is already taken by SQL NULL. They map to the DateTimeInfinity enum instead:
Forcing the three into one shape would make two of them worse: floats would carry a wrapper they do not need, and ranges and arrays would both lose the distinction between infinity and null.
Spellings differ by type family
The input grammar is not the same across families, which is why the library recognizes several sets of tokens rather than one:
Input
date, timestamp
float8
numeric
infinity, -infinity
accepted
accepted
accepted
inf, -inf
rejected
accepted
accepted
nan
rejected
accepted
accepted
-nan, +nan
rejected
accepted
rejected
On output the datetime types print infinity in lowercase, while the numeric ones print Infinity and NaN capitalized. Each family is parsed with the grammar it actually uses, down to numeric reading a narrower NaN than float8 does.