Skip to content

Commit

Permalink
cbor breaking change (#37881)
Browse files Browse the repository at this point in the history
  • Loading branch information
gewarren authored Nov 3, 2023
1 parent 50258b5 commit b3331a4
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 10 deletions.
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

0 comments on commit b3331a4

Please sign in to comment.