Aws-sdk-net: DateTime не поддерживает сериализацию в оба конца с помощью DocumentModel.

Созданный на 2 июл. 2014  ·  3Комментарии  ·  Источник: aws/aws-sdk-net

Примитив DocumentModel неправильно поддерживает сериализацию в оба конца. Он должен использовать спецификатор формата «o» при сериализации DateTime, чтобы гарантировать правильное сохранение часового пояса и миллисекунд.

Я создал IPropertyConverter ниже, чтобы проиллюстрировать правильную сериализацию для DateTime и NullableDateTime.

using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using System.Globalization;

/// <summary>
/// The <see cref="IPropertyConverter"/> to properly support round-trip serialization of <see cref="DateTime"/>.
/// </summary>
public class RoundTripNullableDateTimeTypeConverter : IPropertyConverter
{
    /// <summary>
    /// Converts the <c>value</c> to a <see cref="Primitive"/>.
    /// </summary>
    /// <param name="value">The value to convert.</param>
    /// <returns>The primitive of the <c>value</c>.</returns>
    public DynamoDBEntry ToEntry(object value)
    {
        var date = value as DateTime?;
        return new Primitive 
        {
            Value = date.HasValue ? date.Value.ToString("o", CultureInfo.InvariantCulture) : null
        };
    }

    /// <summary>
    /// Converts the <c>entry</c> to <see cref="DateTime"/>.
    /// </summary>
    /// <param name="entry">The entry to convert.</param>
    /// <returns>The date time of the entry.</returns>
    public object FromEntry(DynamoDBEntry entry)
    {
        var entryString = entry.AsString();
        if (string.IsNullOrEmpty(entryString))
            return null;
        else
            return DateTime.ParseExact(entryString, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
    }
}

/// <summary>
/// The <see cref="IPropertyConverter"/> to properly support round-trip serialization of <see cref="DateTime"/>.
/// </summary>
public class RoundTripDateTimeTypeConverter : IPropertyConverter
{
    /// <summary>
    /// Converts the <c>value</c> to a <see cref="Primitive"/>.
    /// </summary>
    /// <param name="value">The value to convert.</param>
    /// <returns>The primitive of the <c>value</c>.</returns>
    public DynamoDBEntry ToEntry(object value)
    {
        return new Primitive
        {
            Value = ((DateTime)value).ToString("o", CultureInfo.InvariantCulture)
        };
    }

    /// <summary>
    /// Converts the <c>entry</c> to <see cref="DateTime"/>.
    /// </summary>
    /// <param name="entry">The entry to convert.</param>
    /// <returns>The date time of the entry.</returns>
    public object FromEntry(DynamoDBEntry entry)
    {
        return DateTime.ParseExact(entry.AsString(), "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
    }
}

Некоторые важные ссылки:

Все 3 Комментарий

Спасибо, что подняли этот вопрос. Как вы указали, текущая реализация использует формат ISO 8601 UTC, который не хранит часовой пояс и имеет более низкую точность, чем это возможно с форматом «o».

Первоначальное решение использовать этот формат было принято во всех SDK AWS, которые реализуют высокоуровневый API DynamoDB (таблица и DynamoDBContext в .NET, DynamoDBMapper в Java и т. Д.). Хранение дат в формате ISO 8601 UTC обеспечивает согласованный поиск и сортировку, что невозможно, если указаны часовые пояса: большие строковые значения не обязательно означают «большие» значения даты, и можно иметь несколько представлений для одной «уникальной» даты. Последнее может вызвать проблемы со всеми операциями, а не только с поиском (запрос и сканирование): если элемент с DateTime в качестве ключа хранится с определенным часовым поясом, его можно получить только в том случае, если используется тот же самый точный часовой пояс. Таким образом, в зависимости от структуры приложения изменение часового пояса может привести к сбою всех вызовов данных, поскольку ключ не будет совпадать.

Внесение вышеуказанного изменения в .NET SDK станет критическим изменением для пользователей, которые могут использовать несколько SDK или разные версии .NET SDK, поскольку необновленные клиенты не смогут анализировать новые форматы. Но предоставленные конвертеры являются отличным подходом к хранению дат с более высокой точностью с часовыми поясами, если данные последовательно считываются и записываются с использованием одного и того же форматирования и при этом учитываются некоторые из упомянутых соображений.

@PavelSafronov , спасибо за ответ!

Причина, по которой я поднял его, заключалась в неожиданном поведении при сохранении даты в формате UTC, а затем при получении элемента она возвращалась в местном часовом поясе. Это неожиданно для тех из нас, кто использует API для правильного хранения и извлечения данных с использованием UTC. API предполагает, что входящие DateTime НЕ являются UTC, поэтому он предполагает, что они должны быть местным временем при десериализации. Таким образом, это противоречивое предположение.

Я собрал пакет Nuget под названием AWSSDK.DynamoDBv2.Converters, чтобы помочь другим пользователям, которым требуется согласованное поведение сериализации дат. (Источник находится на GitHub .)

Надеюсь, эта информация поможет команде.

Преобразователи, указанные выше, следует использовать, если у вас есть вариант использования, аналогичный @radleta. Для основного SDK мы не будем обновлять преобразования, так как это приведет к критическим изменениям.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги