Aws-sdk-net: DateTime tidak mendukung serialisasi perjalanan pulang pergi dengan DocumentModel

Dibuat pada 2 Jul 2014  ·  3Komentar  ·  Sumber: aws/aws-sdk-net

DocumentModel Primitive tidak mendukung serialisasi perjalanan pulang pergi dengan benar. Itu harus menggunakan penentu format "o" saat membuat serial DateTime untuk memastikan zona waktu dan milidetik dipertahankan dengan benar.

Saya membuat IPropertyConverter di bawah ini untuk mengilustrasikan serialisasi yang benar untuk DateTime dan 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);
    }
}

Beberapa referensi penting:

Semua 3 komentar

Terima kasih telah mengangkat ini. Seperti yang Anda tunjukkan, implementasi saat ini menggunakan format ISO 8601 UTC, yang tidak menyimpan zona waktu dan memiliki presisi yang lebih rendah daripada yang dimungkinkan dengan format "o".

Keputusan awal untuk menggunakan format ini dibuat di semua AWS SDK yang menerapkan API DynamoDB tingkat tinggi (Tabel dan DynamoDBContext di .NET, DynamoDBMapper di Java, dll.) Menyimpan tanggal dalam format ISO 8601 UTC memungkinkan pencarian dan penyortiran yang konsisten, yang tidak mungkin jika zona waktu ditentukan: nilai string yang lebih besar tidak selalu berarti nilai tanggal "lebih besar", dan dimungkinkan untuk memiliki beberapa representasi untuk satu tanggal "unik". Yang terakhir dapat menyebabkan masalah dengan semua operasi, bukan hanya pencarian (Kueri dan Pemindaian): jika item dengan DateTime sebagai kunci disimpan dengan zona waktu tertentu, itu hanya dapat diambil jika zona waktu yang sama persis digunakan. Jadi, bergantung pada struktur aplikasi, perubahan zona waktu dapat menyebabkan semua panggilan data gagal, karena kuncinya tidak cocok.

Membuat perubahan di atas ke .NET SDK akan menjadi perubahan besar bagi pengguna yang mungkin menggunakan beberapa SDK atau versi berbeda dari .NET SDK, karena klien yang tidak diperbarui tidak akan dapat mengurai format baru. Tetapi konverter yang disediakan adalah pendekatan yang sangat baik untuk menyimpan tanggal presisi tinggi dengan zona waktu, selama data dibaca dan ditulis secara konsisten menggunakan format yang sama dan beberapa pertimbangan yang disebutkan diperhitungkan.

@PavelSafronov , terima kasih atas tanggapannya!

Alasan saya mengangkatnya adalah perilaku yang tidak terduga dalam menyimpan tanggal UTC kemudian setelah mengambil item itu kembali di zona waktu lokal. Ini tidak terduga bagi kita yang menggunakan API untuk menyimpan dan mengambil data dengan benar menggunakan UTC. API mengasumsikan DateTime yang masuk BUKAN UTC jadi oleh karena itu, ia menganggap mereka harus waktu lokal pada deserialisasi. Jadi itu membuat asumsi yang tidak konsisten.

Saya menyusun paket Nuget bernama AWSSDK.DynamoDBv2.Converters untuk membantu orang lain yang membutuhkan perilaku serialisasi tanggal yang konsisten. (Sumbernya ada di GitHub .)

Semoga informasi ini membantu tim.

Konverter yang ditautkan di atas harus digunakan jika Anda memiliki kasus penggunaan yang serupa dengan @radleta. Untuk SDK utama, kami tidak akan memperbarui konversi karena hal itu akan menyebabkan perubahan yang mengganggu.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat