Convert uniqid() to a timestamp

Main Thread 2 min read

I came across an interesting question on StackOverflow. Unfortunately the question was closed before I could answer. I'd like to answer it.

Can I convert uniqid() to a timestamp?

Sort of.

From the PHP documentation on uniqid():

without being passed any additional parameters the return value is little different from microtime()

The comments note that uniqid() outputs a hexadecimal string. So let's convert microtime() to a hexadecimal string and compare it to uniqid().

1$microtime = microtime(true);
2$id = uniqid();
3 
4echo dechex($microtime); // 5228cee5
5echo $id; // 5228cee5564a0

We see both share the same prefix (5228cee5). So what are the remaining characters of uniqid()?

Turns out the answer is pretty obvious. It's the microseconds. But uniqid() does not simply multiply $microtome by 1,000,000. Instead it appends the microseconds as a hexidecimal string.

Let's take another look:

1$microtime = microtime();
2$id = uniqid();
3 
4list($microseconds, $timestamp) = explode(' ', $microtime);
5$suffix = str_replace(dechex($timestamp), '', $id);
6 
7echo $microseconds; // 0.23929900
8echo '0.', hexdec($suffix); // 0.239327

Pretty close. The few nanosecond difference is the runtime between executing line 1 and 2.

So using microtime() we've proven uniqid(), without parameters, is the concatenation of a timestamp and microseconds as hexadecimal strings.

Why then did I say sort of?

The suffix. If you run the last script enough you'll notice an inconsistency for low microsecond values.

0.00997400
0.9984

Notice the leading zeroes are missing. So you can't get a timestamp with microsecond precision from uniqid().

However, given this inconsistency, can we trust the suffix is a specific number of hexadecimal characters (i.e. 5)?

The documentation states, without parameters, uniqid() returns 13 characters. That said, the simplest code to get the timestamp from uniqid() is to extract the prefix:

1$timestamp = substr(uniqid(), 0, -5);
2echo date('r', hexdec($timestamp)); // Thu, 05 Sep 2013 15:55:04 -0400

Why the negative anchor? Consider the Unix timestamp 4294967296. You don't want to start Y2.1K!

After this exercise I reviewed the source code for uniqid() to confirm using a negative anchor (-5) is indeed safe.

So yes, you can convert uniqid() to a timestamp (without microsecond precision).

Find this interesting? Let's continue the conversation on Twitter.