forked from npgsql/npgsql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIntervalHandler.cs
More file actions
58 lines (49 loc) · 2.33 KB
/
IntervalHandler.cs
File metadata and controls
58 lines (49 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using NodaTime;
using Npgsql.BackendMessages;
using Npgsql.PostgresTypes;
using Npgsql.TypeHandling;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Npgsql.NodaTime
{
public class IntervalHandlerFactory : NpgsqlTypeHandlerFactory<Period>
{
// Check for the legacy floating point timestamps feature
public override NpgsqlTypeHandler<Period> Create(PostgresType postgresType, NpgsqlConnection conn)
=> conn.HasIntegerDateTimes
? new IntervalHandler(postgresType)
: throw new NotSupportedException($"The deprecated floating-point date/time format is not supported by {nameof(Npgsql)}.");
}
class IntervalHandler : NpgsqlSimpleTypeHandler<Period>
{
public IntervalHandler(PostgresType postgresType) : base(postgresType) {}
public override Period Read(NpgsqlReadBuffer buf, int len, FieldDescription? fieldDescription = null)
{
var microsecondsInDay = buf.ReadInt64();
var days = buf.ReadInt32();
var totalMonths = buf.ReadInt32();
// Nodatime will normalize most things (i.e. nanoseconds to milliseconds, seconds...)
// but it will not normalize months to years.
var months = totalMonths % 12;
var years = totalMonths / 12;
return new PeriodBuilder
{
Nanoseconds = microsecondsInDay * 1000,
Days = days,
Months = months,
Years = years
}.Build().Normalize();
}
public override int ValidateAndGetLength(Period value, NpgsqlParameter? parameter)
=> 16;
public override void Write(Period value, NpgsqlWriteBuffer buf, NpgsqlParameter? parameter)
{
var microsecondsInDay =
(((value.Hours * NodaConstants.MinutesPerHour + value.Minutes) * NodaConstants.SecondsPerMinute + value.Seconds) * NodaConstants.MillisecondsPerSecond + value.Milliseconds) * 1000 +
value.Nanoseconds / 1000; // Take the microseconds, discard the nanosecond remainder
buf.WriteInt64(microsecondsInDay);
buf.WriteInt32(value.Weeks * 7 + value.Days); // days
buf.WriteInt32(value.Years * 12 + value.Months); // months
}
}
}