Version 6: Ordered-Time

Experimental

Version 6, ordered-time UUIDs are an experimental feature based on an Internet-Draft under review at the IETF. While the basic layout is not expected to change, be aware that the draft is a moving target. If there are significant changes to the layout, ramsey/uuid will attempt to maintain backward compatibility but cannot guarantee it.

Version 6 UUIDs solve two problems that have long existed with the use of version 1 UUIDs:

  1. Scattered database records

  2. Inability to sort by an identifier in a meaningful way (i.e., insert order)

To overcome these issues, we need the ability to generate UUIDs that are monotonically increasing while still providing all the benefits of version 1 UUIDs.

Version 6 UUIDs do this by storing the time in standard byte order, instead of breaking it up and rearranging the time bytes, according to the RFC 4122 definition. All other fields remain the same, and the version maintains its position, according to RFC 4122.

In all other ways, version 6 UUIDs function like version 1 UUIDs.

Tip

Prior to version 4.0.0, ramsey/uuid provided a solution for this with the ordered-time codec. Use of the ordered-time codec is still valid and acceptable. However, you may replace UUIDs generated using the ordered-time codec with version 6 UUIDs. Keep reading to find out how.

Generate a version 6, ordered-time UUID
use Ramsey\Uuid\Uuid;

$uuid = Uuid::uuid6();

printf(
    "UUID: %s\nVersion: %d\nDate: %s\nNode: %s\n",
    $uuid->toString(),
    $uuid->getFields()->getVersion(),
    $uuid->getDateTime()->format('r'),
    $uuid->getFields()->getNode()->toString()
);

This will generate a version 6 UUID and print out its string representation, the time the UUID was created, and the node used to create the UUID.

It will look something like this:

UUID: 1ea60f56-b67b-61fc-829a-0242ac130003
Version: 6
Date: Sun, 08 Mar 2020 04:29:37 +0000
Node: 0242ac130003

You may provide custom values for version 6 UUIDs, including node and clock sequence.

Provide custom node and clock sequence to create a version 6, ordered-time UUID
use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Uuid;

$nodeProvider = new StaticNodeProvider(new Hexadecimal('121212121212'));
$clockSequence = 16383;

$uuid = Uuid::uuid6($nodeProvider->getNode(), $clockSequence);

Tip

Version 6 UUIDs generated in ramsey/uuid are instances of UuidV6. Check out the Ramsey\Uuid\Nonstandard\UuidV6 API documentation to learn more about what you can do with a UuidV6 instance.

Custom and Random Nodes

In the example above, we provided a custom node when generating a version 6 UUID. You may also generate random node values.

To learn more, see the Providing a Custom Node and Generating a Random Node sections under Version 1: Time-based.

Clock Sequence

In a version 6 UUID, the clock sequence serves the same purpose as in a version 1 UUID. See What’s a Clock Sequence? to learn more.

Version 1-to-6 Conversion

It is possible to convert back-and-forth between version 6 and version 1 UUIDs.

Convert a version 1 UUID to a version 6 UUID
use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Rfc4122\UuidV1;
use Ramsey\Uuid\Uuid;

$uuid1 = Uuid::fromString('3960c5d8-60f8-11ea-bc55-0242ac130003');

if ($uuid1 instanceof UuidV1) {
    $uuid6 = UuidV6::fromUuidV1($uuid1);
}
Convert a version 6 UUID to a version 1 UUID
use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Uuid;

$uuid6 = Uuid::fromString('1ea60f83-960c-65d8-bc55-0242ac130003');

if ($uuid6 instanceof UuidV6) {
    $uuid1 = $uuid6->toUuidV1();
}

Ordered-time to Version 6 Conversion

You may convert UUIDs previously generated and stored using the ordered-time codec into version 6 UUIDs.

Caution

If you perform this conversion, the bytes and string representation of your UUIDs will change. This will break any software that expects your identifiers to be fixed.

Convert an ordered-time codec encoded UUID to a version 6 UUID
use Ramsey\Uuid\Codec\OrderedTimeCodec;
use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Rfc4122\UuidV1;
use Ramsey\Uuid\UuidFactory;

// The bytes of a version 1 UUID previously stored in some datastore
// after encoding to bytes with the OrderedTimeCodec.
$bytes = hex2bin('11ea60faf17c8af6ad23acde48001122');

$factory = new UuidFactory();
$codec = new OrderedTimeCodec($factory->getUuidBuilder());

$factory->setCodec($codec);

$orderedTimeUuid = $factory->fromBytes($bytes);

if ($orderedTimeUuid instanceof UuidV1) {
    $uuid6 = UuidV6::fromUuidV1($orderedTimeUuid);
}

Privacy Concerns

Like version 1 UUIDs, version 6 UUIDs use a MAC address from a local hardware network interface. This means it is possible to uniquely identify the machine on which a version 6 UUID was created.

If the value provided by the timestamp of a version 6 UUID is important to you, but you do not wish to expose the interface address of any of your local machines, see Custom and Random Nodes.

If you do not need an identifier with a node value embedded in it, but you still need the benefit of a monotonically increasing unique identifier, see Timestamp-first COMB Codec.