From 4113ba5420852aeadb8c5698b0af20fcf3da1bd0 Mon Sep 17 00:00:00 2001
From: Jan Tattermusch <jtattermusch@google.com>
Date: Wed, 22 Jul 2015 18:37:35 -0700
Subject: [PATCH] implemented FromDateTime

---
 .../Grpc.Core.Tests/Internal/TimespecTest.cs  | 15 +++++++-
 src/csharp/Grpc.Core/Internal/Timespec.cs     | 35 +++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
index 69b94bb393..8469a9e3da 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs
@@ -41,9 +41,22 @@ namespace Grpc.Core.Internal.Tests
     public class TimespecTest
     {
         [Test]
-        public void Now()
+        public void Now_IsInUtc() 
+        {
+            Assert.AreEqual(DateTimeKind.Utc, Timespec.Now.ToDateTime().Kind);
+        }
+
+        [Test]
+        public void Now_AgreesWithUtcNow()
         {
             var timespec = Timespec.Now;
+            var utcNow = DateTime.UtcNow;
+
+            TimeSpan difference = utcNow - timespec.ToDateTime();
+
+            // This test is inherently a race - but the two timestamps
+            // should really be way less that a minute apart.
+            Assert.IsTrue(difference.TotalSeconds < 60);
         }
 
         [Test]
diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs
index 32a9c93f77..887eae5dd7 100644
--- a/src/csharp/Grpc.Core/Internal/Timespec.cs
+++ b/src/csharp/Grpc.Core/Internal/Timespec.cs
@@ -179,6 +179,41 @@ namespace Grpc.Core.Internal
                 return tv_sec.ToInt64() > 0 ? DateTime.MaxValue : DateTime.MinValue;
             }
         }
+            
+        public static Timespec FromDateTime(DateTime dateTime)
+        {
+            if (dateTime == DateTime.MaxValue)
+            {
+                return Timespec.InfFuture;
+            }
+
+            if (dateTime == DateTime.MinValue)
+            {
+                return Timespec.InfPast;
+            }
+
+            Preconditions.CheckArgument(dateTime.Kind == DateTimeKind.Utc, "dateTime");
+
+            try
+            {
+                TimeSpan timeSpan = dateTime - UnixEpoch;
+                long ticks = timeSpan.Ticks;
+
+                IntPtr seconds = new IntPtr(ticks / TicksPerSecond);  // possible OverflowException
+                // (x % m + m) % m is workaround for modulo semantics with negative numbers.
+                int nanos = (int)(((ticks % TicksPerSecond + TicksPerSecond) % TicksPerSecond) * NanosPerTick);
+
+                return new Timespec(seconds, nanos);
+            }
+            catch (OverflowException)
+            {
+                return dateTime > UnixEpoch ? Timespec.InfFuture : Timespec.InfPast;
+            }
+            catch (ArgumentOutOfRangeException)
+            {
+                return dateTime > UnixEpoch ? Timespec.InfFuture : Timespec.InfPast;
+            }
+        }
 
         internal static int NativeSize
         {
-- 
GitLab