Udostępnij za pośrednictwem


System.Formats.Cbor DateTimeOffset, zmiana formatowania

Ponieważ został wydany na platformie .NET 5, pakiet NuGet System.Formats.Cbor zawierał wbudowane metody serializacji i deserializacji wartości DateTimeOffset zgodnie z RFC 7049. Niestety implementacje nie używały niezmiennej kultury podczas formatowania i analizowania wartości DateTimeOffset. Spowodowało to niespójne lub nawet niepoprawne kodowanie dat na maszynach z kulturami, które używają kalendarzy innych niż gregoriański.

Zachowanie zostało zmienione tak, aby niezmienna kultura była zawsze używana podczas analizowania i formatowania wartości DateTimeOffset. Ta zmiana może spowodować przerwanie kodu, jeśli oparliśmy się na poprzednim zachowaniu. Ponadto odczytywanie wartości daty zakodowanych we wcześniejszych wersjach pakietu NuGet System.Formats.Cbor może być niemożliwe.

Wprowadzona wersja

.NET 8

Poprzednie zachowanie

Rozważmy ten kod, który analizuje wartość DateTimeOffset z ciągu, a następnie koduje go przy użyciu CBOR:

// Install a culture with a non-Gregorian calendar
var culture = new CultureInfo("he-IL");
culture.DateTimeFormat.Calendar = new HebrewCalendar();
Thread.CurrentThread.CurrentCulture = culture;

DateTimeOffset value = DateTimeOffset.Parse("2020-04-09T14:31:21.3535941+01:00", CultureInfo.InvariantCulture);

var writer = new CborWriter();
writer.WriteDateTimeOffset(value);
byte[] cborEncoding = writer.Encode();

Console.WriteLine(Convert.ToHexString(cborEncoding));

Wcześniej ten kod wygenerował następujące kodowanie CBOR:

C07828D7AAD7A922D7A42DD796272DD79822D7955431343A33313A32312E333533353934312B30313A3030

To kodowanie odpowiada 0(תש\"פ-ז'-ט\"וT14:31:21.3535941+01:00) notacji diagnostycznej CBOR, która jest nieprawidłową reprezentacją daty na RFC 7049.

Nowe zachowanie

Począwszy od platformy .NET 8, ten sam kod tworzy następujące kodowanie CBOR:

C07821323032302D30342D30395431343A33313A32312E333533353934312B30313A3030

To kodowanie odpowiada 0("2020-04-09T14:31:21.3535941+01:00") notacji diagnostycznej CBOR.

Typ zmiany powodującej niezgodność

Ta zmiana jest zmianą behawioralną.

Przyczyna wprowadzenia zmiany

Poprzednie zachowanie wygenerowało nieprawidłowe kodowanie dat na RFC 7049.

Może być konieczne odczytywanie kodowań dat CBOR, które były utrwalane przy użyciu wcześniejszych wersji pliku System.Formats.Cbor, jeśli nie uaktualniasz do najnowszej wersji pakietu NuGet System.Formats.Cbor.

Możesz też zmienić kod, aby użyć następującej metody rozszerzenia:

public static class CborReaderExtensions
{
    private const string Rfc3339FormatString = "yyyy-MM-ddTHH:mm:ss.FFFFFFFK";

    public static DateTimeOffset ReadDateTimeOffsetReplacement(this CborReader reader, CultureInfo? cultureInfo = null)
    {
        CborTag tag = reader.PeekTag();
        if (tag != CborTag.DateTimeString)
        {
            throw new InvalidOperationException($"Expected CborTag {(int)CborTag.DateTimeString}");
        }

        reader.ReadTag();
        string dateString = reader.ReadTextString();
        return DateTimeOffset.ParseExact(dateString, Rfc3339FormatString, cultureInfo, DateTimeStyles.    RoundtripKind);
    }
}

Użyj tej metody rozszerzenia, aby odczytać kodowanie dat CBOR w następujący sposób:

var reader = new CborReader(cborEncoding);
DateTimeOffset date = reader.ReadDateTimeOffsetReplacement(culture);
Console.WriteLine(date.ToString(CultureInfo.InvariantCulture));

Dotyczy interfejsów API