Буферы протокола:Должен ли я использовать int64 или fix64 для представления значения DateTime .NET?

StackOverflow https://stackoverflow.com/questions/837537

Вопрос

Мне нужно сериализовать значение .NET DateTime в сообщении буферов протокола.

Мой план состоит в том, чтобы использовать DateTime.ToBinary(), а затем передать возвращаемое 64-битное значение в сообщении.Но я не уверен, какой тип данных буферов протокола выбрать для этого.

Наверное, я запутался когда следует использовать типы данных фиксированный64 (или sfixed64).

Я предполагаю, что в этом сценарии я бы использовал знаковые типы, поскольку значения, возвращаемые DateTime.ToBinary(), могут быть как отрицательными, так и положительными.

Это было полезно?

Решение

Ну, вы определенно хотите, чтобы int64 или sfixed64 справились со подписываемым значением.

Только что выполнив быстрый тест, DateTime.Now.ToBinary () кодируется в 10 байтов, используя int64 , тогда как sfixed64 всегда будет использовать 8 байт. По сути, кодирование переменной длины отлично подходит для небольших чисел, но становится больше, чем кодирование фиксированной длины для больших чисел. (Это тот же тип компромисса, что и при использовании UTF-8 вместо UTF-16 - символы ASCII можно кодировать в UTF-8 одним байтом, но позже кодовые точки в конечном итоге кодируются как 2, а затем 3 байта, тогда как UTF -16 всегда использует 2 байта для символов в BMP.)

Я предполагаю, что значения DateTime.ToBinary () могут быть достаточно большими (не зная деталей того, что именно они делают), поэтому sfixed64 более уместно.

Это имеет смысл?

Другие советы

В protobuf-net, я использую градуированный подход (и действительно, он сделает все это за вас, если вы просто используете DateTime) — эквивалент .proto выглядит примерно так:

message DateTime {
  optional sint64 value = 1; // the offset (in units of the selected scale)
                             // from 1970/01/01
  optional TimeSpanScale scale = 2 [default = DAYS]; // the scale of the
                                                     // timespan
  enum TimeSpanScale {
    DAYS = 0;
    HOURS = 1;
    MINUTES = 2;
    SECONDS = 3;
    MILLISECONDS = 4;

    MINMAX = 15; // dubious
  }
}

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

Лично я бы не использовал ToBinary() - Я бы явно использовал смещение известного масштаба от известной эпохи (например, эпохи Unix).Это делает его более переносимым между платформами.Но если вы отправляете (например) только миллисекундное смещение, то фиксированный масштаб обычно будет более эффективным, чем масштаб с вариантной длиной.Нужны ли вам подписанные или беззнаковые даты, зависит от того, нужны ли вам даты до вашей эпохи ;-p

Вы должны использовать 64-разрядное число со знаком не потому, что DateTime может быть отрицательным, а потому, что метод ToBinary возвращает Int64 , который является 64-битным числом со знаком.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top