Skip to content

Commit 5686a73

Browse files
JessieWadmanHorusiath
authored andcommitted
Added support for DateTimeOffset as a primitive (#79)
* Added support for DateTimeOffset as a primitive * Corrected comment * Corrected another comment * Changed serialization of DateTimeOffset from ticks+minutes to ticks+ticks.
1 parent 2f01f53 commit 5686a73

File tree

8 files changed

+108
-4
lines changed

8 files changed

+108
-4
lines changed

Hyperion.PerfTest/Program.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ private static void Run()
3535

3636
var guidTest = new GuidTest();
3737
guidTest.Run(1000000);
38+
39+
var dateTimeOffsetTest = new DateTimeOffsetTest();
40+
dateTimeOffsetTest.Run(1000000);
41+
3842
var typicalPersonArrayTest = new TypicalPersonArrayTest();
39-
typicalPersonArrayTest.Run(1000);
43+
typicalPersonArrayTest.Run(1000);
4044

4145
var typicalPersonTest = new TypicalPersonTest();
4246
typicalPersonTest.Run(100000);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#region copyright
2+
// -----------------------------------------------------------------------
3+
// <copyright file="DateTimeOffsetTest.cs" company="Akka.NET Team">
4+
// Copyright (C) 2015-2016 AsynkronIT <https://github.com/AsynkronIT>
5+
// Copyright (C) 2016-2016 Akka.NET Team <https://github.com/akkadotnet>
6+
// </copyright>
7+
// -----------------------------------------------------------------------
8+
#endregion
9+
10+
using System;
11+
12+
namespace Hyperion.PerfTest.Tests
13+
{
14+
class DateTimeOffsetTest : TestBase<DateTimeOffset>
15+
{
16+
protected override DateTimeOffset GetValue()
17+
{
18+
return DateTimeOffset.Now;
19+
}
20+
}
21+
}

Hyperion.Tests/PrimitivesTests.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,29 @@ public void CanSerializeGuid()
7676
}
7777

7878
[Fact]
79-
public void CanSerializeDateTime()
79+
public void CanSerializeDateTimeUtc()
8080
{
8181
SerializeAndAssert(DateTime.UtcNow);
8282
}
8383

84+
[Fact]
85+
public void CanSerializeDateTimeLocal()
86+
{
87+
SerializeAndAssert(new DateTime(DateTime.Now.Ticks, DateTimeKind.Local));
88+
}
89+
90+
[Fact]
91+
public void CanSerializeDateTimeOffsetNow()
92+
{
93+
SerializeAndAssert(DateTimeOffset.Now);
94+
}
95+
96+
[Fact]
97+
public void CanSerializeDateTimeOffsetUtc()
98+
{
99+
SerializeAndAssert(DateTimeOffset.UtcNow);
100+
}
101+
84102
[Fact]
85103
public void CanSerializeDecimal()
86104
{

Hyperion/Extensions/TypeEx.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public static class TypeEx
3535
public static readonly Type SByteType = typeof(sbyte);
3636
public static readonly Type BoolType = typeof(bool);
3737
public static readonly Type DateTimeType = typeof(DateTime);
38+
public static readonly Type DateTimeOffsetType = typeof(DateTimeOffset);
3839
public static readonly Type StringType = typeof(string);
3940
public static readonly Type GuidType = typeof(Guid);
4041
public static readonly Type FloatType = typeof(float);
@@ -56,6 +57,7 @@ public static bool IsHyperionPrimitive(this Type type)
5657
type == ByteType ||
5758
type == SByteType ||
5859
type == DateTimeType ||
60+
type == DateTimeOffsetType ||
5961
type == BoolType ||
6062
type == StringType ||
6163
type == GuidType ||

Hyperion/NoAllocBitConverter.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,15 @@ public static unsafe void GetBytes(DateTime dateTime, byte[] bytes)
112112
*((long*) b) = dateTime.Ticks;
113113
bytes[DateTimeSerializer.Size - 1] = (byte) dateTime.Kind;
114114
}
115+
116+
public static unsafe void GetBytes(DateTimeOffset dateTime, byte[] bytes)
117+
{
118+
//datetimeoffset size is 16 ticks + offset
119+
fixed (byte* b = bytes)
120+
{
121+
*((long*)b) = dateTime.Ticks;
122+
*((long*)(b + sizeof(long))) = (long)dateTime.Offset.Ticks;
123+
}
124+
}
115125
}
116126
}

Hyperion/Serializer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ private void AddDeserializers()
5858
_deserializerLookup[StringSerializer.Manifest] = StringSerializer.Instance;
5959
_deserializerLookup[Int32Serializer.Manifest] = Int32Serializer.Instance;
6060
_deserializerLookup[ByteArraySerializer.Manifest] = ByteArraySerializer.Instance;
61-
//10 not yet used
61+
_deserializerLookup[DateTimeOffsetSerializer.Manifest] = DateTimeOffsetSerializer.Instance;
6262
_deserializerLookup[GuidSerializer.Manifest] = GuidSerializer.Instance;
6363
_deserializerLookup[FloatSerializer.Manifest] = FloatSerializer.Instance;
6464
_deserializerLookup[DoubleSerializer.Manifest] = DoubleSerializer.Instance;
@@ -96,6 +96,7 @@ private void AddSerializers()
9696
AddValueSerializer<char>(CharSerializer.Instance);
9797
AddValueSerializer<byte[]>(ByteArraySerializer.Instance);
9898
AddValueSerializer<DateTime>(DateTimeSerializer.Instance);
99+
AddValueSerializer<DateTimeOffset>(DateTimeOffsetSerializer.Instance);
99100

100101
AddValueSerializer<Type>(TypeSerializer.Instance);
101102
AddValueSerializer(TypeSerializer.Instance, TypeEx.RuntimeType);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#region copyright
2+
// -----------------------------------------------------------------------
3+
// <copyright file="DateTimeSerializer.cs" company="Akka.NET Team">
4+
// Copyright (C) 2015-2016 AsynkronIT <https://github.com/AsynkronIT>
5+
// Copyright (C) 2016-2016 Akka.NET Team <https://github.com/akkadotnet>
6+
// </copyright>
7+
// -----------------------------------------------------------------------
8+
#endregion
9+
10+
using System;
11+
using System.IO;
12+
13+
namespace Hyperion.ValueSerializers
14+
{
15+
public class DateTimeOffsetSerializer : SessionAwareByteArrayRequiringValueSerializer<DateTimeOffset>
16+
{
17+
public const byte Manifest = 10;
18+
public const int Size = sizeof(long) + sizeof(long);
19+
public static readonly DateTimeOffsetSerializer Instance = new DateTimeOffsetSerializer();
20+
21+
public DateTimeOffsetSerializer() : base(Manifest, () => WriteValueImpl, () => ReadValueImpl)
22+
{
23+
}
24+
25+
private static void WriteValueImpl(Stream stream, DateTimeOffset dateTimeOffset, byte[] bytes)
26+
{
27+
NoAllocBitConverter.GetBytes(dateTimeOffset, bytes);
28+
stream.Write(bytes, 0, Size);
29+
}
30+
31+
public static DateTimeOffset ReadValueImpl(Stream stream, byte[] bytes)
32+
{
33+
var dateTime = ReadDateTimeOffset(stream, bytes);
34+
return dateTime;
35+
}
36+
37+
private static DateTimeOffset ReadDateTimeOffset(Stream stream, byte[] bytes)
38+
{
39+
stream.Read(bytes, 0, Size);
40+
var dateTimeTicks = BitConverter.ToInt64(bytes, 0);
41+
var offsetTicks = BitConverter.ToInt64(bytes, sizeof(long));
42+
var dateTimeOffset = new DateTimeOffset(dateTimeTicks, TimeSpan.FromTicks(offsetTicks));
43+
return dateTimeOffset;
44+
}
45+
46+
public override int PreallocatedByteBufferSize => Size;
47+
}
48+
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Hyperion was designed to safely transfer messages in distributed systems, for ex
1515
In message based systems, it is common to receive different types of messages and apply pattern matching over those messages.
1616
If the messages does not carry over all the relevant type information to the receiveing side, the message might no longer match exactly what your system expect.
1717

18-
Consilder the following case:
18+
Consider the following case:
1919

2020
```csharp
2121
public class Envelope

0 commit comments

Comments
 (0)