How to create a MongoDB ObjectID from a timestamp using PHP
This is a useful tidbit of code to have until PHP adds this feature into their MongoDB extension. I stumbled on an example on Stack Overflow illustration showing how to do this and rewrote it in what I think is a slightly more modern way that does the same thing.
ObjectId’s are constructed using a 4-byte timestamp value, 3-byte machine identifier, 2-byte process id, and a 3-byte counter which create a 12-byte BSON type:
--------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---------------|-----------|-------|--------------|
| time | machine | pid | counter |
--------------------------------------------------
Knowing that makes this PHP code easy to understand:
MongoUtil:
/**
* Class MongoUtil.
*/
class MongoUtil {
/**
* This is needed to keep documents unique that have the same timestamp.
* @var integer
* @see $timestamp
*/
public static $_mongoIdFromTimestampCounter = 0;
/**
* Mongo Id From Timestamp
* @param integer $timestamp
* @return MongoID
* @see http://docs.mongodb.org/manual/reference/object-id/
*/
public static function mongoIdFromTimestamp( $timestamp ) {
// Build Binary Id
$binaryTimestamp = pack('N', $timestamp); // unsigned long
$machineId = substr(md5(gethostname()), 0, 3); // 3 bit machine identifier
$binaryPID = pack('n', posix_getpid()); // unsigned short
$counter = substr(pack('N', self::$_mongoIdFromTimestampCounter++), 1, 3); // Counter
$binaryId = "{$binaryTimestamp}{$machineId}{$binaryPID}{$counter}";
// Convert to ASCII
$id = '';
for ($i = 0; $i < 12; $i++) {
$id .= sprintf("%02X", ord($binaryId[$i]));
}
// Return Mongo ID
return new MongoID($id);
}
}
Example of usage:
$date = strtotime('today');
$mongoId = MongoUtil::mongoIdFromTimestamp($date);
// Do more stuff.