System.Formats.Cbor DateTimeOffset 格式變更
自從在 .NET 5 中發行以來,System.Formats.Cbor NuGet 套件包含內建方法,可根據 RFC 7049 序列化和還原序列化 DateTimeOffset 值。 不幸的是,當格式化和剖析 DateTimeOffset 值時,實作不會使用不因文化特性而異。 這會導致電腦上使用非西曆文化特性的不一致或甚至是不正確的日期編碼。
行為已變更,因此剖析和格式化 DateTimeOffset 值時一律會使用不因文化特性而異。 如果您依賴先前的行為,這項變更可能會中斷程式碼。 此外,可能無法讀取以舊版 System.Formats.Cbor NuGet 套件編碼的日期值。
導入的版本
.NET 8
先前的行為
請考慮此程式碼,從字串剖析 DateTimeOffset 值,然後使用 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));
此程式碼以前會產生下列 CBOR 編碼:
C07828D7AAD7A922D7A42DD796272DD79822D7955431343A33313A32312E333533353934312B30313A3030
此編碼會對應至 CBOR 診斷標記法中的 0(תש\"פ-ז'-ט\"וT14:31:21.3535941+01:00)
,這對於 RFC 7049 是無效的日期表示法。
新的行為
從 .NET 8 開始,相同的程式碼會產生下列 CBOR 編碼:
C07821323032302D30342D30395431343A33313A32312E333533353934312B30313A3030
此編碼會對應至 CBOR 診斷標記法中的 0("2020-04-09T14:31:21.3535941+01:00")
。
中斷性變更的類型
此變更為行為變更。
變更原因
先前的行為會產生對於 RFC 7049 無效的日期編碼。
建議的動作
如果您未升級至最新版本的 System.Formats.Cbor NuGet 套件,您可能必須能夠讀取使用舊版 System.Formats.Cbor 保存的 CBOR 日期編碼。
或者,您可以變更程式碼以使用下列擴充方法:
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);
}
}
使用此擴充方法來讀取 CBOR 日期編碼,如下所示:
var reader = new CborReader(cborEncoding);
DateTimeOffset date = reader.ReadDateTimeOffsetReplacement(culture);
Console.WriteLine(date.ToString(CultureInfo.InvariantCulture));