Skip to content

CBOR breaking change #37881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions docs/core/compatibility/8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,17 @@ If you're migrating an app to .NET 8, the breaking changes listed here might aff

## Extensions

| Title | Type of change | Introduced |
|-----------------------------------------------------------------------------------------------------------------------------------|-------------------|------------|
| [ActivatorUtilities.CreateInstance behaves consistently](extensions/8.0/activatorutilities-createinstance-behavior.md) | Behavioral change | Preview 1 |
| [ActivatorUtilities.CreateInstance requires non-null provider](extensions/8.0/activatorutilities-createinstance-null-provider.md) | Behavioral change | Preview 1 |
| [ConfigurationBinder throws for mismatched value](extensions/8.0/configurationbinder-exceptions.md) | Behavioral change | Preview 1 |
| [ConfigurationManager package no longer references System.Security.Permissions](extensions/8.0/configurationmanager-package.md) | Source incompatible | Preview 3 |
| [DirectoryServices package no longer references System.Security.Permissions](extensions/8.0/directoryservices-package.md) | Source incompatible | Preview 3 |
| [Empty keys added to dictionary by configuration binder](extensions/8.0/dictionary-configuration-binding.md) | Behavioral change | Preview 5 |
| [HostApplicationBuilderSettings.Args respected by HostApplicationBuilder ctor](extensions/8.0/hostapplicationbuilder-ctor.md) | Behavioral change | Preview 2 |
| [ManagementDateTimeConverter.ToDateTime returns a local time](extensions/8.0/dmtf-todatetime.md) | Behavioral change | RC 1 |
| Title | Type of change |
|-----------------------------------------------------------------------------------------------------------------------------------|-------------------|
| [ActivatorUtilities.CreateInstance behaves consistently](extensions/8.0/activatorutilities-createinstance-behavior.md) | Behavioral change |
| [ActivatorUtilities.CreateInstance requires non-null provider](extensions/8.0/activatorutilities-createinstance-null-provider.md) | Behavioral change |
| [ConfigurationBinder throws for mismatched value](extensions/8.0/configurationbinder-exceptions.md) | Behavioral change |
| [ConfigurationManager package no longer references System.Security.Permissions](extensions/8.0/configurationmanager-package.md) | Source incompatible |
| [DirectoryServices package no longer references System.Security.Permissions](extensions/8.0/directoryservices-package.md) | Source incompatible |
| [Empty keys added to dictionary by configuration binder](extensions/8.0/dictionary-configuration-binding.md) | Behavioral change |
| [HostApplicationBuilderSettings.Args respected by HostApplicationBuilder ctor](extensions/8.0/hostapplicationbuilder-ctor.md) | Behavioral change |
| [ManagementDateTimeConverter.ToDateTime returns a local time](extensions/8.0/dmtf-todatetime.md) | Behavioral change |
| [System.Formats.Cbor DateTimeOffset formatting change](extensions/8.0/cbor-datetime.md) | Behavioral change |

## Globalization

Expand Down
94 changes: 94 additions & 0 deletions docs/core/compatibility/extensions/8.0/cbor-datetime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: "Breaking change: System.Formats.Cbor DateTimeOffset formatting change"
description: Learn about the .NET 8 breaking change in .NET extensions where System.Formats.Cbor always formats and parses DateTimeOffset values using the invariant culture.
ms.date: 11/02/2023
---
# System.Formats.Cbor DateTimeOffset formatting change

Since it was released in .NET 5, the System.Formats.Cbor NuGet package included built-in methods for serializing and deserializing DateTimeOffset values according to RFC 7049. Unfortunately, the implementations didn't use invariant culture when formatting and parsing DateTimeOffset values. This resulted in inconsistent or even incorrect date encodings on machines with cultures that use non-Gregorian calendars.

The behavior has been changed so that invariant culture is always used when parsing and formatting DateTimeOffset values. This change might break your code if you relied on the previous behavior. Also, it might be impossible to read date values that were encoded with earlier versions of the System.Formats.Cbor NuGet package.

## Version introduced

.NET 8

## Previous behavior

Consider this code that parses a DateTimeOffset value from a string and then encodes it using CBOR:

```csharp
// 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));
```

Previously, this code produced the following CBOR encoding:

`C07828D7AAD7A922D7A42DD796272DD79822D7955431343A33313A32312E333533353934312B30313A3030`

This encoding corresponds to `0(תש\"פ-ז'-ט\"וT14:31:21.3535941+01:00)` in CBOR diagnostic notation, which is an invalid date representation per RFC 7049.

## New behavior

Starting in .NET 8, the same code produces the following CBOR encoding:

`C07821323032302D30342D30395431343A33313A32312E333533353934312B30313A3030`

This encoding corresponds to `0("2020-04-09T14:31:21.3535941+01:00")` in CBOR diagnostic notation.

## Type of breaking change

This change is a [behavioral change](../../categories.md#behavioral-change).

## Reason for change

The previous behavior produced invalid date encodings per RFC 7049.

## Recommended action

You might have to be able to read CBOR date encodings that were persisted using earlier versions of System.Formats.Cbor if you don't upgrade to the latest version of the System.Formats.Cbor NuGet package.

Alternatively, you can change your code to use the following extension method:

```csharp
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);
}
}
```

Use this extension method to read a CBOR date encoding as follows:

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

## Affected APIs

- <xref:System.Formats.Cbor.CborWriter.WriteDateTimeOffset(System.DateTimeOffset)?displayProperty=fullName>
- <xref:System.Formats.Cbor.CborReader.ReadDateTimeOffset?displayProperty=fullName>
4 changes: 4 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ items:
href: extensions/8.0/hostapplicationbuilder-ctor.md
- name: ManagementDateTimeConverter.ToDateTime returns a local time
href: extensions/8.0/dmtf-todatetime.md
- name: System.Formats.Cbor DateTimeOffset formatting change
href: extensions/8.0/cbor-datetime.md
- name: Globalization
items:
- name: Date and time converters honor culture argument
Expand Down Expand Up @@ -1354,6 +1356,8 @@ items:
href: extensions/8.0/hostapplicationbuilder-ctor.md
- name: ManagementDateTimeConverter.ToDateTime returns a local time
href: extensions/8.0/dmtf-todatetime.md
- name: System.Formats.Cbor DateTimeOffset formatting change
href: extensions/8.0/cbor-datetime.md
- name: .NET 7
items:
- name: Binding config to dictionary extends values
Expand Down