Aws-sdk-net: DateTime não oferece suporte à serialização de ida e volta com o DocumentModel

Criado em 2 jul. 2014  ·  3Comentários  ·  Fonte: aws/aws-sdk-net

O DocumentModel Primitive não oferece suporte adequado à serialização de ida e volta. Ele deve usar o especificador de formato "o" ao serializar DateTime para garantir que o fuso horário e os milissegundos sejam preservados corretamente.

Criei um IPropertyConverter abaixo para ilustrar a serialização correta para DateTime e 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);
    }
}

Algumas referências importantes:

Todos 3 comentários

Obrigado por trazer isso. Como você apontou, a implementação atual usa o formato ISO 8601 UTC, que não armazena o fuso horário e tem uma precisão menor do que a possível com o formato "o".

A decisão original de usar este formato foi feita em todos os SDKs da AWS que implementam uma API DynamoDB de alto nível (Tabela e DynamoDBContext em .NET, DynamoDBMapper em Java, etc.) O armazenamento de datas no formato UTC ISO 8601 permite uma pesquisa e classificação consistentes, o que não é possível se os fusos horários forem especificados: valores de string maiores não significam necessariamente valores de data "maiores" e é possível ter várias representações para uma única data "única". O último pode causar problemas com todas as operações, não apenas pesquisas (Consulta e Scan): se um item com DateTime como uma chave for armazenado com um fuso horário específico, ele só pode ser recuperado se o mesmo fuso horário exato for usado. Portanto, dependendo de como um aplicativo está estruturado, uma alteração no fuso horário pode fazer com que todas as chamadas de dados falhem, pois a chave não corresponderá.

Fazer a alteração acima no .NET SDK será uma mudança importante para os usuários que podem estar usando vários SDKs ou versões diferentes do .NET SDK, uma vez que os clientes não atualizados não conseguirão analisar os novos formatos. Mas os conversores fornecidos são uma abordagem excelente para armazenar datas de alta precisão com fusos horários, desde que os dados sejam lidos e gravados de forma consistente usando a mesma formatação e algumas das considerações mencionadas sejam levadas em consideração.

@PavelSafronov , obrigado pela resposta!

O motivo pelo qual mencionei isso foi um comportamento inesperado de salvar uma data UTC e, ao buscar o item, ele voltou no fuso horário local. Isso é inesperado para aqueles de nós que usam a API para armazenar e recuperar dados adequadamente usando UTC. A API presume que o DateTime de entrada NÃO é UTC, portanto, presume que deve ser o horário local na desserialização. Portanto, faz uma suposição inconsistente.

Eu montei um pacote Nuget chamado GitHub .)

Espero que esta informação ajude a equipe.

Os conversores vinculados acima devem ser usados ​​se você tiver um caso de uso semelhante ao @radleta. Para o SDK principal, não atualizaremos as conversões, pois isso introduzirá uma alteração significativa.

Esta página foi útil?
0 / 5 - 0 avaliações