NodaTime `DateInterval` read: an end of 9999-12-30 comes back as 9999-12-31, and unbounded dateranges get invented bounds
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
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 asLocalDate.MaxIsoValue, the same valueinfinityreads 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 defaultLocalDate) 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
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
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de npgsql/npgsql
-
Writing a decimal as numeric allocates a short[9] per valuePeut-être pris @tamasprincz97-dot l’a pris il y a 13 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 89/100
Les mainteneurs répondent en général sous 6 jours
-
Reading a large interval as TimeSpan returns a wrong value instead of throwingPeut-être pris @Mr444-dev l’a pris il y a 7 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 66/100
Les mainteneurs répondent en général sous 6 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
Les mainteneurs répondent en général sous 6 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
npgsql/npgsql#6569 · 2 commentaires ·
Les mainteneurs répondent en général sous 6 jours
-
ReadReplicationSlot returns the slot name as passed, not the one the server readPeut-être pris @Brar l’a pris il y a 8 jours. Ouvertereplication
npgsql/npgsql#6735 · 1 personne assignée ·
Les mainteneurs répondent en général sous 6 jours
Toutes les issues de npgsql/npgsql
Issues similaires
-
Issue-Bug Needs-Triage
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 66/100
JiaFeiMiao-K-Cat/DiscImageStudio#281 ·
Les mainteneurs répondent en général sous 1 jour
-
area/access-management Frontend onboarding candidate :handshake:
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
Altinn/altinn-auth#4941 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
aws/aws-sdk-net#4586 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
Les mainteneurs répondent en général sous 1 jour