Skip to content

Commit 8988880

Browse files
committed
Add Timestamp related serializers.
1 parent 3e4111d commit 8988880

21 files changed

Lines changed: 611 additions & 39 deletions

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ Release 1.0.0-beta1 T.B.D.
713713
NEW FEATURES
714714
* .NET Standard 2.0 which supports serializer source code generation on .NET Core. Note that serializer assembly generation is not supported.
715715
* MessagePackSerializer.UnpackMessagePackObject(byte[]) utility method.
716+
* MessagePack timestamp type support. This includes interoperability with DateTime/DateTimeOffset as well as MsgPack.Timespan type with basic arithmatics, properties, and conversions.
716717

717718
BUG FIXES
718719
* Fix ByteArrayPacker throws IndexOutOfBoundException when the buffer remaining bytes is equal to packed scalar size. #252

src/MsgPack/KnownExtTypeCode.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// MessagePack for CLI
44
//
5-
// Copyright (C) 2015 FUJIWARA, Yusuke
5+
// Copyright (C) 2015-2017 FUJIWARA, Yusuke
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -31,6 +31,17 @@ namespace MsgPack
3131
/// </remarks>
3232
public static class KnownExtTypeCode
3333
{
34+
/// <summary>
35+
/// Gets the ext type code which represents MsgPack timestamp.
36+
/// </summary>
37+
/// <value>
38+
/// 0xFF(-1).
39+
/// </value>
40+
public static byte Timestamp
41+
{
42+
get { return 0xFF; }
43+
}
44+
3445
/// <summary>
3546
/// Gets the ext type code which represents multidimensional array.
3647
/// </summary>
@@ -42,4 +53,4 @@ public static byte MultidimensionalArray
4253
get { return 0x71; }
4354
}
4455
}
45-
}
56+
}

src/MsgPack/KnownExtTypeName.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#region -- License Terms --
1+
#region -- License Terms --
22
//
33
// MessagePack for CLI
44
//
5-
// Copyright (C) 2015 FUJIWARA, Yusuke
5+
// Copyright (C) 2015-2017 FUJIWARA, Yusuke
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -31,6 +31,17 @@ namespace MsgPack
3131
/// </remarks>
3232
public static class KnownExtTypeName
3333
{
34+
/// <summary>
35+
/// Gets the ext type name which represents MsgPack timestamp.
36+
/// </summary>
37+
/// <value>
38+
/// "Timestamp".
39+
/// </value>
40+
public static string Timestamp
41+
{
42+
get { return "Timestamp"; }
43+
}
44+
3445
/// <summary>
3546
/// Gets the ext type name which represents multidimensional array.
3647
/// </summary>

src/MsgPack/MessagePackObject.Utilities.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#region -- License Terms --
1+
#region -- License Terms --
22
//
33
// MessagePack for CLI
44
//
5-
// Copyright (C) 2010-2016 FUJIWARA, Yusuke
5+
// Copyright (C) 2010-2017 FUJIWARA, Yusuke
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -1785,6 +1785,23 @@ public object ToObject()
17851785
}
17861786
}
17871787

1788+
/// <summary>
1789+
/// Gets a this object as a <see cref="Timestamp"/> value.
1790+
/// </summary>
1791+
/// <returns>A <see cref="Timestamp"/> value.</returns>
1792+
/// <exception cref="InvalidOperationException">This object does not represent <see cref="Timestamp"/> value.</exception>
1793+
public Timestamp AsTimestamp()
1794+
{
1795+
try
1796+
{
1797+
return Timestamp.Decode( this.AsMessagePackExtendedTypeObject() );
1798+
}
1799+
catch(ArgumentException ex)
1800+
{
1801+
throw new InvalidOperationException( ex.Message, ex );
1802+
}
1803+
}
1804+
17881805
#region -- Structure Operator Overloads --
17891806

17901807
/// <summary>

src/MsgPack/MsgPack.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@
504504
<Compile Remove="Serialization\DefaultSerializers\FileTimeMessagePackSerializerProvider.cs" />
505505
<Compile Remove="Serialization\DefaultSerializers\NativeFileTimeMessagePackSerializer.cs" />
506506
<Compile Remove="Serialization\DefaultSerializers\UnixEpocFileTimeMessagePackSerializer.cs" />
507+
<Compile Remove="Serialization\DefaultSerializers\TimestampFileTimeMessagePackSerializer.cs" />
507508
<Compile Remove="Serialization\ReflectionExtensions.ConstructorDelegate.cs" />
508509
</ItemGroup>
509510
<ItemGroup Condition="'$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'netstandard1.1' or '$(TargetFramework)' == 'netstandard1.3' or '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'uap10.0' or '$(TargetFramework)' == 'MonoAndroid10' or '$(TargetFramework)' == 'Xamarin.iOS10'">

src/MsgPack/Serialization/DateTimeConversionMethod.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,34 @@ public enum DateTimeConversionMethod
3131
/// Uses <see cref="DateTime.Ticks"/> context, that is, Gregorian 0000-01-01 based, 100 nano seconds resolution. This value also preserves <see cref="DateTimeKind"/>.
3232
/// </summary>
3333
/// <remarks>
34-
/// As of 0.6, this value has been become default. This option prevents accidental data loss.
34+
/// As of 0.6 to 0.9, this value became default. This option prevents accidental data loss.
3535
/// </remarks>
3636
Native = 0,
3737

3838
/// <summary>
3939
/// Uses Unix epoc context, that is, Gregirian 1970-01-01 based, milliseconds resolution.
4040
/// </summary>
4141
/// <remarks>
42-
/// Many binding such as Java uses this resolution, so this option gives maximom interoperability.
42+
/// Many binding such as Java uses this resolution, so this option gives maximum interoperability.
4343
/// </remarks>
44-
UnixEpoc = 1
44+
UnixEpoc = 1,
45+
46+
/// <summary>
47+
/// Uses MsgPack timestamp format, that is, Gregirian 1970-01-01 based, nanoseconds resolution, with reserved ext type format.
48+
/// </summary>
49+
/// <remarks>
50+
/// <para>
51+
/// As of 1.0, this value became default.
52+
/// </para>
53+
/// <para>
54+
/// This is best choice for interoperability and prevents accidental data loss, but old implementation does not recognize this type.
55+
/// For backward compability purposes, use <see cref="Native"/> or <see cref="UnixEpoc"/> instead.
56+
/// </para>
57+
/// <para>
58+
/// Note that <see cref="DateTime"/> and <see cref="DateTimeOffset"/> cannot hold nanoseconds value.
59+
/// If you can depend on this assembly, consider <see cref="Timestamp"/> for date-time typed members to maximize interoperability for other languages.
60+
/// </para>
61+
/// </remarks>
62+
Timestamp = 2
4563
}
46-
}
64+
}

src/MsgPack/Serialization/DateTimeMemberConversionMethod.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@ public enum DateTimeMemberConversionMethod
4949
/// <remarks>
5050
/// Many binding such as Java uses this resolution, so this option gives maximom interoperability.
5151
/// </remarks>
52-
UnixEpoc = 2
52+
UnixEpoc = 2,
53+
54+
/// <summary>
55+
/// Uses MsgPack timestamp format, that is, Gregirian 1970-01-01 based, nanoseconds resolution, with reserved ext type format.
56+
/// </summary>
57+
/// <remarks>
58+
/// <para>
59+
/// As of 1.0, this value became default.
60+
/// </para>
61+
/// <para>
62+
/// This is best choice for interoperability and prevents accidental data loss, but old implementation does not recognize this type.
63+
/// For backward compability purposes, use <see cref="Native"/> or <see cref="UnixEpoc"/> instead.
64+
/// </para>
65+
/// <para>
66+
/// Note that <see cref="DateTime"/> and <see cref="DateTimeOffset"/> cannot hold nanoseconds value.
67+
/// If you can depend on this assembly, consider <see cref="Timestamp"/> for date-time typed members to maximize interoperability for other languages.
68+
/// </para>
69+
/// </remarks>
70+
Timestamp = 3
5371
}
54-
}
72+
}

src/MsgPack/Serialization/DateTimeMessagePackSerializerHelpers.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#region -- License Terms --
1+
#region -- License Terms --
22
//
33
// MessagePack for CLI
44
//
5-
// Copyright (C) 2015 FUJIWARA, Yusuke
5+
// Copyright (C) 2015-2017 FUJIWARA, Yusuke
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -73,6 +73,10 @@ DateTimeMemberConversionMethod dateTimeMemberConversionMethod
7373
{
7474
return DateTimeConversionMethod.UnixEpoc;
7575
}
76+
case DateTimeMemberConversionMethod.Timestamp:
77+
{
78+
return DateTimeConversionMethod.Timestamp;
79+
}
7680
default:
7781
{
7882
return context.DefaultDateTimeConversionMethod;
@@ -89,8 +93,9 @@ internal static bool IsDateTime( Type dateTimeType )
8993
|| dateTimeType == typeof( FILETIME )
9094
|| dateTimeType == typeof( FILETIME? )
9195
#endif // ( !SILVERLIGHT || WINDOWS_PHONE ) && !XAMARIN && !UNITY
92-
// DateTimeOffset? is not have to be treat specially.
93-
|| dateTimeType == typeof( DateTimeOffset );
96+
// DateTimeOffset? and Timestamp? do not have to be treat specially.
97+
|| dateTimeType == typeof( DateTimeOffset )
98+
|| dateTimeType == typeof( Timestamp );
9499
}
95100
}
96-
}
101+
}

src/MsgPack/Serialization/DefaultSerializers/DateTimeMessagePackSerializerProvider.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// MessagePack for CLI
44
//
5-
// Copyright (C) 2015 FUJIWARA, Yusuke
5+
// Copyright (C) 2015-2017 FUJIWARA, Yusuke
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@ internal class DateTimeMessagePackSerializerProvider : MessagePackSerializerProv
3434
{
3535
private readonly MessagePackSerializer _unixEpoc;
3636
private readonly MessagePackSerializer _native;
37+
private readonly MessagePackSerializer _timestamp;
3738

3839
public DateTimeMessagePackSerializerProvider( SerializationContext context, bool isNullable )
3940
{
@@ -44,17 +45,22 @@ public DateTimeMessagePackSerializerProvider( SerializationContext context, bool
4445
new NullableMessagePackSerializer<DateTime>( context, new UnixEpocDateTimeMessagePackSerializer( context ) );
4546
this._native =
4647
new NullableMessagePackSerializer<DateTime>( context, new NativeDateTimeMessagePackSerializer( context ) );
48+
this._timestamp =
49+
new NullableMessagePackSerializer<DateTime>( context, new TimestampDateTimeMessagePackSerializer( context ) );
4750
#else
4851
this._unixEpoc =
4952
new NullableMessagePackSerializer( context, typeof( DateTime? ), new UnixEpocDateTimeMessagePackSerializer( context ) );
5053
this._native =
5154
new NullableMessagePackSerializer( context, typeof( DateTime? ), new NativeDateTimeMessagePackSerializer( context ) );
55+
this._timestamp =
56+
new NullableMessagePackSerializer( context, typeof( DateTime? ), new TimestampDateTimeMessagePackSerializer( context ) );
5257
#endif // !UNITY
5358
}
5459
else
5560
{
5661
this._unixEpoc = new UnixEpocDateTimeMessagePackSerializer( context );
5762
this._native = new NativeDateTimeMessagePackSerializer( context );
63+
this._timestamp = new TimestampDateTimeMessagePackSerializer( context );
5864
}
5965
}
6066

@@ -72,6 +78,10 @@ public override object Get( SerializationContext context, object providerParamet
7278
{
7379
return this._unixEpoc;
7480
}
81+
case DateTimeConversionMethod.Timestamp:
82+
{
83+
return this._timestamp;
84+
}
7585
}
7686
}
7787

@@ -85,6 +95,10 @@ public override object Get( SerializationContext context, object providerParamet
8595
{
8696
return this._unixEpoc;
8797
}
98+
case DateTimeConversionMethod.Timestamp:
99+
{
100+
return this._timestamp;
101+
}
88102
default:
89103
{
90104
throw new NotSupportedException(
@@ -99,4 +113,4 @@ public override object Get( SerializationContext context, object providerParamet
99113
}
100114
}
101115
}
102-
}
116+
}

src/MsgPack/Serialization/DefaultSerializers/DateTimeOffsetMessagePackSerializer.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// MessagePack for CLI
44
//
5-
// Copyright (C) 2015-2016 FUJIWARA, Yusuke
5+
// Copyright (C) 2015-2017 FUJIWARA, Yusuke
66
//
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
@@ -52,7 +52,11 @@ public DateTimeOffsetMessagePackSerializer( SerializationContext ownerContext, D
5252
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Validated by caller in base class" )]
5353
protected internal override void PackToCore( Packer packer, DateTimeOffset objectTree )
5454
{
55-
if ( this._conversion == DateTimeConversionMethod.Native )
55+
if ( this._conversion == DateTimeConversionMethod.Timestamp )
56+
{
57+
packer.Pack( Timestamp.FromDateTimeOffset( objectTree ).Encode() );
58+
}
59+
else if ( this._conversion == DateTimeConversionMethod.Native )
5660
{
5761
packer.PackArrayHeader( 2 );
5862
packer.Pack( objectTree.DateTime.ToBinary() );
@@ -73,7 +77,11 @@ protected internal override void PackToCore( Packer packer, DateTimeOffset objec
7377
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods", MessageId = "0", Justification = "Validated by caller in base class" )]
7478
protected internal override DateTimeOffset UnpackFromCore( Unpacker unpacker )
7579
{
76-
if ( unpacker.IsArrayHeader )
80+
if ( unpacker.LastReadData.IsTypeOf<MessagePackExtendedTypeObject>().GetValueOrDefault() )
81+
{
82+
return Timestamp.Decode( unpacker.LastReadData.DeserializeAsMessagePackExtendedTypeObject() ).ToDateTimeOffset();
83+
}
84+
else if ( unpacker.IsArrayHeader )
7785
{
7886
if ( UnpackHelpers.GetItemsCount( unpacker ) != 2 )
7987
{
@@ -104,7 +112,11 @@ protected internal override DateTimeOffset UnpackFromCore( Unpacker unpacker )
104112

105113
protected internal override async Task PackToAsyncCore( Packer packer, DateTimeOffset objectTree, CancellationToken cancellationToken )
106114
{
107-
if ( this._conversion == DateTimeConversionMethod.Native )
115+
if ( this._conversion == DateTimeConversionMethod.Timestamp )
116+
{
117+
await packer.PackAsync( Timestamp.FromDateTimeOffset( objectTree ).Encode(), cancellationToken ).ConfigureAwait( false );
118+
}
119+
else if ( this._conversion == DateTimeConversionMethod.Native )
108120
{
109121
await packer.PackArrayHeaderAsync( 2, cancellationToken ).ConfigureAwait( false );
110122
await packer.PackAsync( objectTree.DateTime.ToBinary(), cancellationToken ).ConfigureAwait( false );
@@ -141,4 +153,4 @@ protected internal override Task<DateTimeOffset> UnpackFromAsyncCore( Unpacker u
141153
#endif // FEATURE_TAP
142154

143155
}
144-
}
156+
}

0 commit comments

Comments
 (0)