NodaTime `DateInterval` read: an end of 9999-12-30 comes back as 9999-12-31, and unbounded dateranges get invented bounds

Ouverte
#6,688 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 6 jours

@mohsinaliwork686-rgb y travaille déjà.

Depuis le 2/11/2026.

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
82/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
csharp, postgresql
Domaine
database

Piste de recherche

Read src/Npgsql.NodaTime/Internal/DateIntervalConverter.cs, focusing on the Read method lines 29-34. Check NpgsqlRange's LowerBoundInfinite/UpperBoundInfinite flags and whether the upper bound was 'infinity' before conversion. Done means [2026-01-01,9999-12-30] round-trips unchanged and unbounded ranges throw or are rejected.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Environment
PostgreSQL 18.6 (postgres:18)
Packages Npgsql 10.0.3 and Npgsql.NodaTime 10.0.3, used through Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime 10.0.3 (.NET 10.0.11) and 11.0.0-rc.2 (.NET 11.0.0-rc.2)
Also NodaTime 3.2.2, macOS arm64

Both print the same output. main at 54053259 has the same code.

Repro (through EF, which was where it showed up)
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NodaTime;

await using var context = new TestContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();

var written = new DateInterval(new LocalDate(2026, 1, 1), new LocalDate(9999, 12, 30));
context.Rows.Add(new Row { Period = written });
await context.SaveChangesAsync();
await context.Database.ExecuteSqlRawAsync("""INSERT INTO "Rows" ("Period") VALUES ('(,2026-01-10)')""");

await using var fresh = new TestContext();
var rows = await fresh.Rows.OrderBy(r => r.Id).ToListAsync();
Console.WriteLine($"written {written}, read back {rows[0].Period}");
Console.WriteLine($"stored '(,2026-01-10)', read back {rows[1].Period}");

public class TestContext : DbContext
{
    public DbSet<Row> Rows => Set<Row>();

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseNpgsql(Environment.GetEnvironmentVariable("Test__Npgsql__DefaultConnection"), o => o.UseNodaTime())
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();
}

public class Row
{
    public int Id { get; set; }
    public DateInterval Period { get; set; } = null!;
}

Output, the same on both lines:

written [2026-01-01, 9999-12-30], read back [2026-01-01, 9999-12-31]
stored '(,2026-01-10)', read back [0001-01-01, 2026-01-09]

The cause is DateIntervalConverter.Read (DateIntervalConverter.cs#L29-L34):

  • Ending at 9999-12-30. [2026-01-01, 9999-12-30] is stored as [2026-01-01,9999-12-31). The finite date 9999-12-31 reads as LocalDate.MaxIsoValue, the same value infinity reads as. So the special case added for #4715 skips the minus-one-day step, and the interval grows by a day on every round trip.
  • Unbounded ranges. The infinite-bound flags aren't checked, so (,2026-01-10) becomes [0001-01-01, 2026-01-09] (a default LocalDate) instead of failing.

Checking LowerBoundInfinite/UpperBoundInfinite, and throwing for an unbounded range (a DateInterval can't represent one), would fix the second case. The first needs to know whether the upper bound was infinity before it's converted.

Langage dominant
C#
Étoiles
3.7k
Forks
890
Merge moyen
4 j 11 h
PR mergées (30 j)
19

Préparer son environnement

Ouvrir dans Codespaces

Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.

  • Aucun Dockerfile ni fichier Docker Compose
  • Aucun modèle de pull request
  • Aucun guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de npgsql/npgsql

Toutes les issues de npgsql/npgsql

Issues similaires

Plus d'issues C#

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.