Skip to content

Commit 8a64324

Browse files
committed
Add Timestamp struct
This type implements MsgPack Timestamp specification with following utilities: * Arithmatic operations like System.DateTime. * Basic string conversion. Currently, exact parsing and ISO styles are only supported. * Date/time components properties like System.DateTime. * Type conversion between System.DateTime and System.DateTimeOffset.
1 parent f4050bb commit 8a64324

12 files changed

Lines changed: 2661 additions & 0 deletions
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
#region -- License Terms --
2+
//
3+
// MessagePack for CLI
4+
//
5+
// Copyright (C) 2010-2015 FUJIWARA, Yusuke
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
#endregion -- License Terms --
20+
21+
#if UNITY_5 || UNITY_STANDALONE || UNITY_WEBPLAYER || UNITY_WII || UNITY_IPHONE || UNITY_ANDROID || UNITY_PS3 || UNITY_XBOX360 || UNITY_FLASH || UNITY_BKACKBERRY || UNITY_WINRT
22+
#define UNITY
23+
#endif
24+
25+
using System;
26+
#if CORE_CLR || UNITY || NETSTANDARD1_1
27+
using Contract = MsgPack.MPContract;
28+
#else
29+
using System.Diagnostics.Contracts;
30+
#endif // CORE_CLR || UNITY || NETSTANDARD1_1
31+
#if !NET35
32+
using System.Numerics;
33+
#endif // !NET35
34+
35+
namespace MsgPack
36+
{
37+
partial struct Timestamp
38+
{
39+
#if !NET35
40+
private static readonly BigInteger NanoToSecondsAsBigInteger = new BigInteger( 1000 * 1000 * 1000 );
41+
#endif // !NET35
42+
43+
/// <summary>
44+
/// Adds a specified <see cref="TimeSpan"/> to this instance.
45+
/// </summary>
46+
/// <param name="offset">A <see cref="TimeSpan"/> which represents offset. Note that this value can be negative.</param>
47+
/// <returns>The result <see cref="Timestamp"/>.</returns>
48+
/// <exception cref="OverflowException">
49+
/// The result of calculation overflows <see cref="MaxValue"/> or underflows <see cref="MinValue"/>.
50+
/// </exception>
51+
public Timestamp Add( TimeSpan offset )
52+
{
53+
long secondsOffset;
54+
int nanosOffset;
55+
FromOffsetTicks( offset.Ticks, out secondsOffset, out nanosOffset );
56+
var seconds = checked( this.unixEpochSeconds + secondsOffset );
57+
var nanos = this.nanoseconds + nanosOffset;
58+
if ( nanos > MaxNanoSeconds )
59+
{
60+
checked
61+
{
62+
seconds++;
63+
}
64+
nanos -= ( MaxNanoSeconds + 1 );
65+
}
66+
else if ( nanos < 0 )
67+
{
68+
checked
69+
{
70+
seconds--;
71+
}
72+
nanos = ( MaxNanoSeconds + 1 ) + nanos;
73+
}
74+
75+
return new Timestamp( seconds, unchecked(( int )nanos) );
76+
}
77+
78+
/// <summary>
79+
/// Subtracts a specified <see cref="TimeSpan"/> from this instance.
80+
/// </summary>
81+
/// <param name="offset">A <see cref="TimeSpan"/> which represents offset. Note that this value can be negative.</param>
82+
/// <returns>The result <see cref="Timestamp"/>.</returns>
83+
/// <exception cref="OverflowException">
84+
/// The result of calculation overflows <see cref="MaxValue"/> or underflows <see cref="MinValue"/>.
85+
/// </exception>
86+
public Timestamp Subtract( TimeSpan offset )
87+
{
88+
return this.Add( -offset );
89+
}
90+
91+
#if !NET35
92+
/// <summary>
93+
/// Adds a specified nanoseconds represented as a <see cref="BigInteger"/> from this instance.
94+
/// </summary>
95+
/// <param name="offsetNanoseconds">A <see cref="BigInteger"/> which represents offset. Note that this value can be negative.</param>
96+
/// <returns>The result <see cref="Timestamp"/>.</returns>
97+
/// <exception cref="OverflowException">
98+
/// The result of calculation overflows <see cref="MaxValue"/> or underflows <see cref="MinValue"/>.
99+
/// </exception>
100+
public Timestamp Add( BigInteger offsetNanoseconds )
101+
{
102+
BigInteger nanosecondsOffset;
103+
var secondsOffset = ( long )BigInteger.DivRem( offsetNanoseconds, NanoToSecondsAsBigInteger, out nanosecondsOffset );
104+
105+
var seconds = checked( this.unixEpochSeconds + secondsOffset );
106+
var nanos = this.nanoseconds + unchecked( ( int )nanosecondsOffset );
107+
if ( nanos > MaxNanoSeconds )
108+
{
109+
checked
110+
{
111+
seconds++;
112+
}
113+
nanos -= ( MaxNanoSeconds + 1 );
114+
}
115+
else if ( nanos < 0 )
116+
{
117+
checked
118+
{
119+
seconds--;
120+
}
121+
nanos = ( MaxNanoSeconds + 1 ) + nanos;
122+
}
123+
124+
return new Timestamp( seconds, unchecked(( int )nanos) );
125+
}
126+
127+
/// <summary>
128+
/// Subtracts a specified nanoseconds represented as a <see cref="BigInteger"/> from this instance.
129+
/// </summary>
130+
/// <param name="offsetNanoseconds">A <see cref="BigInteger"/> which represents offset. Note that this value can be negative.</param>
131+
/// <returns>The result <see cref="Timestamp"/>.</returns>
132+
/// <exception cref="OverflowException">
133+
/// The result of calculation overflows <see cref="MaxValue"/> or underflows <see cref="MinValue"/>.
134+
/// </exception>
135+
public Timestamp Subtract( BigInteger offsetNanoseconds )
136+
{
137+
return this.Add( -offsetNanoseconds );
138+
}
139+
140+
/// <summary>
141+
/// Calculates a difference this instance and a specified <see cref="Timestamp"/> in nanoseconds.
142+
/// </summary>
143+
/// <param name="other">A <see cref="Timestamp"/> to be differentiated.</param>
144+
/// <returns>A <see cref="BigInteger"/> which represents difference in nanoseconds.</returns>
145+
public BigInteger Subtract( Timestamp other )
146+
{
147+
var seconds = new BigInteger( this.unixEpochSeconds ) - other.unixEpochSeconds;
148+
var nanos = ( long )this.nanoseconds - other.nanoseconds;
149+
#if DEBUG
150+
Contract.Assert( nanos <= MaxNanoSeconds, nanos + " <= MaxNanoSeconds" );
151+
#endif // DEBUG
152+
if ( nanos < 0 )
153+
{
154+
// move down
155+
seconds--;
156+
nanos = ( MaxNanoSeconds + 1 ) + nanos;
157+
}
158+
159+
return seconds * SecondsToNanos + nanos;
160+
}
161+
#endif // !NET35
162+
163+
/// <summary>
164+
/// Calculates a <see cref="Timestamp"/> with specified <see cref="Timestamp"/> and an offset represented as <see cref="TimeSpan"/>.
165+
/// </summary>
166+
/// <param name="value">A <see cref="Timestamp"/>.</param>
167+
/// <param name="offset">An offset in <see cref="TimeSpan"/>. This value can be negative.</param>
168+
/// <returns>A <see cref="Timestamp"/>.</returns>
169+
public static Timestamp operator +( Timestamp value, TimeSpan offset )
170+
{
171+
return value.Add( offset );
172+
}
173+
174+
/// <summary>
175+
/// Calculates a <see cref="Timestamp"/> with specified <see cref="Timestamp"/> and an offset represented as <see cref="TimeSpan"/>.
176+
/// </summary>
177+
/// <param name="value">A <see cref="Timestamp"/>.</param>
178+
/// <param name="offset">An offset in <see cref="TimeSpan"/>. This value can be negative.</param>
179+
/// <returns>A <see cref="Timestamp"/>.</returns>
180+
public static Timestamp operator -( Timestamp value, TimeSpan offset )
181+
{
182+
return value.Subtract( offset );
183+
}
184+
185+
#if !NET35
186+
187+
/// <summary>
188+
/// Calculates a <see cref="Timestamp"/> with specified <see cref="Timestamp"/> and a nanoseconds offset represented as <see cref="BigInteger"/>.
189+
/// </summary>
190+
/// <param name="value">A <see cref="Timestamp"/>.</param>
191+
/// <param name="offsetNanoseconds">An offset in nanoseconds as <see cref="BigInteger"/>. This value can be negative.</param>
192+
/// <returns>A <see cref="Timestamp"/>.</returns>
193+
public static Timestamp operator +( Timestamp value, BigInteger offsetNanoseconds )
194+
{
195+
return value.Add( offsetNanoseconds );
196+
}
197+
198+
/// <summary>
199+
/// Calculates a <see cref="Timestamp"/> with specified <see cref="Timestamp"/> and a nanoseconds represented as <see cref="BigInteger"/>.
200+
/// </summary>
201+
/// <param name="value">A <see cref="Timestamp"/>.</param>
202+
/// <param name="offsetNanoseconds">An offset in nanoseconds as <see cref="BigInteger"/>. This value can be negative.</param>
203+
/// <returns>A <see cref="Timestamp"/>.</returns>
204+
public static Timestamp operator -( Timestamp value, BigInteger offsetNanoseconds )
205+
{
206+
return value.Subtract( offsetNanoseconds );
207+
}
208+
209+
/// <summary>
210+
/// Calculates a difference between specified two <see cref="Timestamp"/>s in nanoseconds.
211+
/// </summary>
212+
/// <param name="left">A <see cref="Timestamp"/>.</param>
213+
/// <param name="right">A <see cref="Timestamp"/>.</param>
214+
/// <returns>A <see cref="BigInteger"/> which represents difference in nanoseconds.</returns>
215+
public static BigInteger operator -( Timestamp left, Timestamp right )
216+
{
217+
return left.Subtract( right );
218+
}
219+
#endif // !NET35
220+
}
221+
}

0 commit comments

Comments
 (0)