ramsey/uuid · error · UnsupportedOperationException
Not a time-based UUID
Error message
Not a time-based UUID
What it means
Deprecated Uuid::getDateTime() (removed in ramsey/uuid 5.0; replaced by UuidV1::getDateTime()) converts the 60-bit timestamp of a time-based UUID into a DateTimeImmutable. If the UUID's version nibble is not 1 it throws UnsupportedOperationException, because only v1 UUIDs carry an extractable Gregorian timestamp.
Source
Thrown at src/DeprecatedUuidMethodsTrait.php:120
* @deprecated This method will be removed in 5.0.0. There is no alternative recommendation, so plan accordingly.
*/
public function getNumberConverter(): NumberConverterInterface
{
return $this->numberConverter;
}
/**
* @deprecated In ramsey/uuid version 5.0.0, this will be removed. It is available at {@see UuidV1::getDateTime()}.
*
* @return DateTimeImmutable An immutable instance of DateTimeInterface
*
* @throws UnsupportedOperationException if UUID is not time-based
* @throws DateTimeException if DateTime throws an exception/error
*/
public function getDateTime(): DateTimeInterface
{
if ($this->fields->getVersion() !== 1) {
throw new UnsupportedOperationException('Not a time-based UUID');
}
$time = $this->timeConverter->convertTime($this->fields->getTimestamp());
try {
return new DateTimeImmutable(
'@'
. $time->getSeconds()->toString()
. '.'
. str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
);
} catch (Throwable $e) {
throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
* @deprecated Use {@see UuidInterface::getFields()} to get a {@see \Ramsey\Uuid\Fields\FieldsInterface} instance.View on GitHub (pinned to da5b521600)
Solutions
- Branch on the concrete class: if ($uuid instanceof \Ramsey\Uuid\Rfc4122\UuidV1) { $uuid->getDateTime(); } and skip/derive otherwise.
- Generate v1 (Uuid::uuid1()) when you need the embedded timestamp - or better, UUIDv7 for time-ordered IDs.
- Stop relying on the UUID for timestamps: store an explicit created_at column.
- Complete the 5.0 migration path now: replace the deprecated trait methods with UuidV1-specific ones.
Example fix
// before
$createdAt = $uuid->getDateTime(); // throws UnsupportedOperationException on v4
// after
$createdAt = $uuid instanceof \Ramsey\Uuid\Rfc4122\UuidV1
? $uuid->getDateTime()
: null; Defensive patterns
Strategy: type-guard
Validate before calling
if ($uuid instanceof \Ramsey\Uuid\Rfc4122\UuidV1) {
$createdAt = $uuid->getDateTime();
} else {
$createdAt = null; // or read the stored created_at column
} Type guard
/** @psalm-assert-if-true \Ramsey\Uuid\Rfc4122\UuidV1 $uuid */
function isTimeBasedUuid(UuidInterface $uuid): bool
{
return $uuid instanceof \Ramsey\Uuid\Rfc4122\UuidV1;
} Try / catch
try {
$dateTime = $uuid->getDateTime();
} catch (\Ramsey\Uuid\Exception\UnsupportedOperationException $e) {
$dateTime = null; // UUID carries no timestamp
} Prevention
- Use instanceof UuidV1 before any timestamp extraction.
- Prefer UuidV1::getDateTime() (non-deprecated) once you have narrowed the type.
- Store real timestamps in a column instead of decoding them from identifiers.
- If you need time-ordered IDs with modern tooling, generate Uuid::uuid7() and read its timestamp via fields.
When it happens
Trigger: Uuid::uuid4()->getDateTime(); any generic UuidInterface handle (e.g. a decoded value or a primary key) where getDateTime() is called but the version is 2/3/4/5/6/7.
Common situations: Codebase migrated from v1 keys to v4 keys while keeping getDateTime() calls for created-at style logic; generic code that assumes every UUID is time-based; upgrading ramsey/uuid versions where the call now throws on non-v1 instances.
Related errors
- Expected version 1 (time-based) UUID
- Length must be a positive integer greater than or equal to 6
- The generated time of '%s' is larger than expected
- Invalid node value
- Fields used to create a UuidV6 must represent a version 6 (r
AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21).
Data as JSON: /api/errors/e7c279d442f01868.
Report an issue: GitHub.