rybakit / msgpack.php

A pure PHP implementation of the MessagePack serialization format / msgpack.org[PHP]
MIT License
388 stars 18 forks source link

Add support for the timestamp extension #17

Closed rybakit closed 2 years ago

rybakit commented 7 years ago

Ref: https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type

doc987 commented 6 years ago

Looks like this is still outstanding. I tried sending a serialized Date object from Javascript, and it was deserialized to the object shown below. I was hoping to get a DateTime object instead.

MessagePack\Ext Object
(
    [type] => -1
    [data] => some binary data
)

I wasn't able to get a type transformer to work either. The unpack method in the compressed example below fails.

class DateTimeTransformer implements \MessagePack\TypeTransformer\Unpackable
{
    private $type;

    public function __construct(int $type)
    {
        $this->type = $type;
    }

    public function getType() : int
    {
        return $this->type;
    }

    public function unpack(\MessagePack\BufferUnpacker $unpacker, int $extLength)
    {
        //how does one unpack a timestamp?
        return new \DateTimeImmutable($unpacker->unpack???());
    }
}

$transformer = new DateTimeTransformer(-1);
$unpacker = new \MessagePack\BufferUnpacker();
$unpacker->registerTransformer($transformer);
$data = $unpacker->reset($packed)->unpack();
rybakit commented 6 years ago

@doc987 I took msgpack-lite library as an example from your other issue (https://github.com/msgpack/msgpack-php/issues/127). As you noticed, it has native support for Date objects (ext type 0x0D). So, to be able to deserialize these dates into PHP DateTime(Immutable) objects you can create the following transformer:

namespace App\MessagePack;

use MessagePack\BufferUnpacker;
use MessagePack\TypeTransformer\Unpackable;

final class MsgpackLiteJsDateTransformer implements Unpackable
{
    public function getType() : int
    {
        return 0x0d;
    }

    public function unpack(BufferUnpacker $unpacker, int $extLength) : \DateTimeImmutable
    {
        return \DateTimeImmutable::createFromFormat('U.u', $unpacker->unpackFloat() / 1000);
    }
}

Test:

namespace App\MessagePack;

use MessagePack\BufferUnpacker;

// msgpack.encode(new Date('2018-08-07T22:21:45.580Z')) = c7090dcb42765167b52ec000
$packedJsDate = hex2bin('c7090dcb42765167b52ec000');

$unpacker = new BufferUnpacker($packedJsDate);
$unpacker->registerTransformer(new MsgpackLiteJsDateTransformer());

var_dump($unpacker->unpack());

/*
class DateTimeImmutable#4 (3) {
  public $date =>
  string(26) "2018-08-07 22:21:45.580000"
  public $timezone_type =>
  int(1)
  public $timezone =>
  string(6) "+00:00"
}
*/