Java - конвертировать метку времени MessagePack в дату - PullRequest
0 голосов
/ 16 ноября 2018

Я декодирую сообщение MessagePack из конвейера Apache Beam в проекте Java.Я использую Maven для импорта библиотеки MessagePack как зависимости:

<dependency>
  <groupId>org.msgpack</groupId>
  <artifactId>msgpack-core</artifactId>
  <version>0.8.16</version>
</dependency>

Я могу использовать это для анализа сообщения MessagePack на пары ключ / значение в Map, например:

    @ProcessElement
    public void processElement(ProcessContext c) 
    {
        try 
        {           
            Map<Value, Value> map = MessagePack.newDefaultUnpacker(c.element().getPayload()).unpackValue().asMapValue().map();

Карта содержит пару ключ / значение для типа расширения «Timestamp» MessagePack, который выглядит следующим образом и представляет дату / время (см. «Примечание» внизу, для объяснения MessagePackтипы расширения):

UTC=(-1,0x5b-161d46)

Я могу получить это значение 'timestamp', получив значение с помощью ключа UTC из карты.Я извлекаю его как MessagePack ExtensionValue, например:

 Value date = map.get(ValueFactory.newString("UTC")).asExtensionValue();

date - это объект, который имеет 2 свойства:

`type` = 1
`data` = `0x5b-161d46`

Как преобразовать data взначимое представление даты?«Данные» должны переводиться на «текущую» дату, где-то около 16 ноября 2018 года. Это не так просто, как преобразование шестнадцатеричного значения в десятичное.Нужно ли как-то отдельно распаковывать этот data как-нибудь?Я подозреваю, что 5b-161d46, вероятно, нужно обрабатывать как байтовый массив, а затем каким-то образом преобразовывать.

Я могу сделать это, чтобы получить data часть типа расширения в виде байтового массива:

byte[] date = map.get(ValueFactory.newString("UTC")).asExtensionValue().getData();

, что дает мне [91, -22, 29, 70]

... и я могу попытаться распаковать его так:

MessagePack.newDefaultUnpacker(date).unpackValue()

... однако это просто дает мне первый байт(5b) конвертируется в long, т.е. 91

И если я попробую любой из них, я получу org.msgpack.core.MessageTypeCastException, вероятно, потому что unpackValue просто дает мне одно long число

MessagePack.newDefaultUnpacker(date).unpackValue().asIntegerValue();
MessagePack.newDefaultUnpacker(date).unpackValue().asMapValue();
MessagePack.newDefaultUnpacker(date).unpackValue().asRawValue();

Я также попробовал следующее:

MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(date);
    while(unpacker.hasNext()) {
        MessageFormat f = unpacker.getNextFormat();
            switch(f) {
                case POSFIXINT:
                case NEGFIXINT: {
                    int v = unpacker.unpackInt();
                    break;
                }
             }
    }

Значения в массиве распознаются как POSFIXINT или NEGFIXINT, поэтому я могу использовать это для извлечения десятичного целого числазначения для каждого байта в массиве, однако это позволяет мне извлекать элементы в массиве date как целые числа, и я до сих пор не знаю, как перевести это в дату.

Как мненужно интерпретировать / распаковать эти даты?


Примечание - значение расширения - особый тип MesЗначение sagePack, представленное в виде кортежа, где -1 определяет тип расширения.-1 является зарезервированным расширением для MessagePack timestamp, а остаток дает шестнадцатеричное значение (0x5b-161d46):

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

1 Ответ

0 голосов
/ 19 ноября 2018

Я понял это!Во-первых, короткая версия (как преобразовать значение метки времени MessagePack в значащее число в Java):

import java.nio.ByteBuffer

byte[] timestampValues = myTimestampExtensionValue.asExtensionValue().getData();                            
ByteBuffer wrapped = ByteBuffer.wrap(timestampValues);
Long dateValue = wrapped.getLong();

В моем собственном случае я получал дату как значение расширения метки времени как частьпары ключ / значение на карте, например:

UTC=(-1,0x5b-e28-35)

Это может быть в различных форматах, что очень запутанно, например:

(-1,0x5b-1b6f-24)
(-1,0x5b-1b7056)
(-1,0x5b-1b58-4)

Я обнаружил, чтоесли я делаю это:

byte[] date = map.get(ValueFactory.newString("UTC")).asExtensionValue().getData();

... это всегда дает мне 32-битный байтовый массив.Для моего примера UTC=(-1,0x5b-e28-35) я получаю:

[91, -14, 40, -53]

Это также смутило меня - я не мог понять, как это может быть целым числом.Следует признать, что это байтов со знаком , где отрицательные значения - это значение, которое необходимо вычесть из максимального значения этого байта, то есть 255 .

I 'Я не уверен, почему это происходит (возможно, для экономии памяти, требуя меньше места в каждом байте).В любом случае, приведенный выше пример переводится в следующее в десятичном виде:

[91, 241, 40, 202]

Хотя в Java есть простой способ преобразовать исходный байтовый массив [91, -14, 40, -53] в целое число, импортировав java.nio.ByteBuffer и используя:

ByteBuffer wrapped = ByteBuffer.wrap(date);
Integer num = wrapped.getInt();

Для моего примера это дает нам 1542596811, что составляет секунды с начала эпохи Unix .Итак, если мы преобразуем это в миллисекунды, у нас теперь будет 1542596811000 или дата Mon 19 November 2018, 14:06:51.Простой!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...