npgsql 6 breaks after DateTime migration: "year must be between 1 and 9999"
See original GitHub issueAfter following the date migration guide to change types from “without time zone” to “with time zone”, I’m still having multiple errors. One of them occurs when reading rows from three of our tables:
Out of the range of DateTime (year must be between 1 and 9999)
at Npgsql.Internal.TypeHandlers.DateTimeHandlers.DateTimeUtils.ReadDateTime(NpgsqlReadBuffer buf, DateTimeKind kind)
at Npgsql.Internal.TypeHandlers.DateTimeHandlers.TimestampTzHandler.Read(NpgsqlReadBuffer buf, Int32 len, FieldDescription fieldDescription)
at Npgsql.Internal.TypeHandling.NpgsqlTypeHandler.Read[TAny](NpgsqlReadBuffer buf, Int32 len, FieldDescription fieldDescription)
at Npgsql.NpgsqlDataReader.GetFieldValue[T](Int32 ordinal)
at Npgsql.NpgsqlDataReader.GetDateTime(Int32 ordinal)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at BarreleyeWebTest.BarreleyeIntegrationTestBase.<PrepareTestDatabase>b__17_0(BarreleyeDbContext context) in C:\Dev\BarreleyeServer\BarreleyeWebTest\BarreleyeIntegrationTestBase.cs:line 69
Inner exception:
Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. (Parameter 'ticks')
at System.DateTime.ThrowTicksOutOfRange()
at System.DateTime..ctor(Int64 ticks, DateTimeKind kind)
at Npgsql.Internal.TypeHandlers.DateTimeHandlers.DateTimeUtils.DecodeTimestamp(Int64 value, DateTimeKind kind)
at Npgsql.Internal.TypeHandlers.DateTimeHandlers.DateTimeUtils.ReadDateTime(NpgsqlReadBuffer buf, DateTimeKind kind)
My database contains some dates that I think were set to 0001/01/01 00:00:00, but which BeeKeeper (incorrectly) reports as 0001/12/31… and this breaks npgsql v6. As a workaround I have executed a series of queries like this to fix the problem:
UPDATE table_name
SET last_updated = date '0001-01-02'
WHERE last_updated < date '0001-01-02'
I think the problem can be fixed by changing this function in Npgsql\Internal\TypeHandlers\DateTimeHandlers\DateTimeUtils.cs:
internal static DateTime DecodeTimestamp(long value, DateTimeKind kind)
=> new(value * 10 + PostgresTimestampOffsetTicks, kind);
do instead:
internal static DateTime DecodeTimestamp(long value, DateTimeKind kind)
=> new(Math.Max(0, value * 10 + PostgresTimestampOffsetTicks), kind);
or maybe even:
internal static DateTime DecodeTimestamp(long value, DateTimeKind kind)
=> new(Math.Max(0, Math.Min(DateTime.MaxValue.Ticks, value * 10 + PostgresTimestampOffsetTicks)), kind);
The other error I’m getting occurs when I create a fresh database by calling Migrate()
.
Issue Analytics
- State:
- Created 2 years ago
- Comments:11 (6 by maintainers)
Top Results From Across the Web
Date and Time Handling
.NET types and PostgreSQL types ; time without time zone, 1 microsecond, 0-24 hours, TimeOnly (6.0+), TimeSpan, 100 nanoseconds, -10,675,199 - 10,675,199 days....
Read more >Out of the range of DateTime (year must be between 1 and ...
try to convert timestamp values from the database to DateTimeOffset . it represents wide range value that DataTime. use DateTimeOffset.
Read more >Date, Time, and Time Zone Enhancements in .NET 6
I'm excited to share with you some of the improvements that have been made to .NET that are coming in .NET 6 in...
Read more >How to Get SQL Server Dates and Times Horribly Wrong
One of the times that you need things to go right is when you are doing analysis and reporting. This is generally based...
Read more >Using a PostgreSQL database as an AWS DMS source
With a PostgreSQL database as a source, you can migrate data to either another PostgreSQL database or one of the other supported databases....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@TriHyde your case seems to be the same as @qwertie - please see the discussion above. You have negative timestamp data in your database, and that’s simply not representable with .NET DateTime. I recommend fixing up your data; for example, you could convert those values to
-infinity
with a single UPDATE command; after that, Npgsql will read those values as DateTime.MinValue.If that isn’t suitable, can you please provide more on context on why, and how exactly you’re using those values?
Can I reopen this?
I have old data in my database which causes a crash after upgrading to npgsql 6.
An example of a timestamp in the database (which the pgAdmin can read just fine) is “0001-01-01 00:00:00+01:39:49” (in pgAdmin view). pgAdmin does not crash but npgsql does, since it cannot READ that timestamp without throwing this particular exeption: “year must be between 1 and 9999”, inner: “Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. (Parameter ‘ticks’)”.
Thanks!