From ba6b2526ab8463fa49d1e24bf6c87248e1ef996d Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 30 Apr 2018 10:18:41 -0400 Subject: [PATCH 1/7] Add Failing Tests --- .../DateTimeJsonConverterTest.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs diff --git a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs new file mode 100644 index 0000000..9b17cf5 --- /dev/null +++ b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs @@ -0,0 +1,23 @@ +using System; + +using Intercom.Test; +using NUnit.Framework; + +namespace Intercom.Tests.Converters.ClassConverters +{ + [TestFixture] + public class DateTimeJsonConverterTest : TestBase + { + [Test] + public void ReadJson_ForDateTime_ReturnsValidDateTime() + { + throw new NotImplementedException(); + } + + [Test] + public void WriteJson_ForDateTime_ReturnsValidUnixTimestamp() + { + throw new NotImplementedException(); + } + } +} From 5ebeebffa867f85ccd69ea9dd0712fef70bd3d67 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 30 Apr 2018 10:48:16 -0400 Subject: [PATCH 2/7] Implement ReadJson() --- .../DateTimeJsonConverterTest.cs | 23 +++++++++-- .../ClassConverters/DateTimeJsonConverter.cs | 39 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs diff --git a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs index 9b17cf5..1093bf5 100644 --- a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs +++ b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs @@ -1,17 +1,34 @@ using System; +using System.IO; using Intercom.Test; +using Newtonsoft.Json; using NUnit.Framework; +using Intercom.Converters.ClassConverters; + namespace Intercom.Tests.Converters.ClassConverters { [TestFixture] public class DateTimeJsonConverterTest : TestBase { - [Test] - public void ReadJson_ForDateTime_ReturnsValidDateTime() + private readonly DateTimeJsonConverter _converter; + + public DateTimeJsonConverterTest() { - throw new NotImplementedException(); + _converter = new DateTimeJsonConverter(); + } + + [TestCase("608688900")] + public void ReadJson_ForDateTime_ReturnsValidDateTime(string json) + { + using (StringReader stringReader = new StringReader(json)) + using (JsonReader jsonReader = new JsonTextReader(stringReader)) + { + DateTime dateCreated = (DateTime)_converter.ReadJson(jsonReader, typeof(DateTime), null, null); + + Assert.AreEqual(new DateTime(1989, 4, 16, 0, 15, 0), dateCreated); + } } [Test] diff --git a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs new file mode 100644 index 0000000..6ca7f02 --- /dev/null +++ b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs @@ -0,0 +1,39 @@ +using System; + +using Newtonsoft.Json; + +namespace Intercom.Converters.ClassConverters +{ + public class DateTimeJsonConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return objectType.Equals(typeof(DateTime)); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + long unixTimestamp; + + try + { + unixTimestamp = Convert.ToInt64(reader.ReadAsDouble()); + } + + catch (InvalidCastException ex) + { + throw new FormatException("Dates must be represented as UNIX timestamps in JSON.", ex); + } + + DateTime unixEpoch = new DateTime(1970, 1, 1); + DateTime result = unixEpoch.AddSeconds(unixTimestamp); + + return result; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + } +} From 66862672f4cc4671b746de89919f75dfb1f4b8a8 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 30 Apr 2018 11:07:29 -0400 Subject: [PATCH 3/7] Implement WriteJson() --- .../DateTimeJsonConverterTest.cs | 36 ++++++++++++++++--- .../ClassConverters/DateTimeJsonConverter.cs | 7 +++- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs index 1093bf5..5f44f98 100644 --- a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs +++ b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs @@ -12,6 +12,9 @@ namespace Intercom.Tests.Converters.ClassConverters [TestFixture] public class DateTimeJsonConverterTest : TestBase { + private const string _DateCreatedISO = "1989-04-16T00:15:00Z"; + private const string _DateCreatedUnix = "608688900"; + private readonly DateTimeJsonConverter _converter; public DateTimeJsonConverterTest() @@ -19,7 +22,7 @@ public DateTimeJsonConverterTest() _converter = new DateTimeJsonConverter(); } - [TestCase("608688900")] + [TestCase(_DateCreatedUnix)] public void ReadJson_ForDateTime_ReturnsValidDateTime(string json) { using (StringReader stringReader = new StringReader(json)) @@ -27,14 +30,37 @@ public void ReadJson_ForDateTime_ReturnsValidDateTime(string json) { DateTime dateCreated = (DateTime)_converter.ReadJson(jsonReader, typeof(DateTime), null, null); - Assert.AreEqual(new DateTime(1989, 4, 16, 0, 15, 0), dateCreated); + Assert.AreEqual(_ParseUtcDateString(_DateCreatedISO), dateCreated); + } + } + + [TestCase(_DateCreatedISO)] + public void WriteJson_ForDateTime_ReturnsValidUnixTimestamp(string input) + { + DateTime inputDate; + + try + { + inputDate = _ParseUtcDateString(input); + } + + catch (Exception ex) + { + throw new Exception("Failed to properly parse the test input.", ex); + } + + using (StringWriter stringWriter = new StringWriter()) + using (JsonWriter jsonWriter = new JsonTextWriter(stringWriter)) + { + _converter.WriteJson(jsonWriter, inputDate, null); + + Assert.AreEqual(_DateCreatedUnix, stringWriter.GetStringBuilder().ToString()); } } - [Test] - public void WriteJson_ForDateTime_ReturnsValidUnixTimestamp() + private DateTime _ParseUtcDateString(string input) { - throw new NotImplementedException(); + return DateTimeOffset.Parse(input).UtcDateTime; } } } diff --git a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs index 6ca7f02..527fb8e 100644 --- a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs +++ b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs @@ -33,7 +33,12 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - throw new NotImplementedException(); + DateTime unixEpoch = new DateTime(1970, 1, 1); + DateTime dateTime = (DateTime)value; + + long unixTimestamp = Convert.ToInt64((dateTime - unixEpoch).TotalSeconds); + + writer.WriteRawValue(unixTimestamp.ToString()); } } } From 3a2028d145bc45dadb52b1b3cf093b361820587d Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 30 Apr 2018 11:18:43 -0400 Subject: [PATCH 4/7] Support Nullable DateTime --- .../DateTimeJsonConverterTest.cs | 25 +++++++++++++++++++ .../ClassConverters/DateTimeJsonConverter.cs | 20 +++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs index 5f44f98..6c2410f 100644 --- a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs +++ b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs @@ -14,6 +14,7 @@ public class DateTimeJsonConverterTest : TestBase { private const string _DateCreatedISO = "1989-04-16T00:15:00Z"; private const string _DateCreatedUnix = "608688900"; + private const string _Null = "null"; private readonly DateTimeJsonConverter _converter; @@ -34,6 +35,30 @@ public void ReadJson_ForDateTime_ReturnsValidDateTime(string json) } } + [TestCase(_Null)] + public void ReadJson_ForNullableDateTime_ReturnsNull(string json) + { + using (StringReader stringReader = new StringReader(json)) + using (JsonReader jsonReader = new JsonTextReader(stringReader)) + { + DateTime? dateCreated = (DateTime?)_converter.ReadJson(jsonReader, typeof(DateTime?), null, null); + + Assert.AreEqual(null, dateCreated); + } + } + + [TestCase(null)] + public void WriteJsonForNullableDateTime_ReturnsNull(DateTime? input) + { + using (StringWriter stringWriter = new StringWriter()) + using (JsonWriter jsonWriter = new JsonTextWriter(stringWriter)) + { + _converter.WriteJson(jsonWriter, input, null); + + Assert.AreEqual(_Null, stringWriter.GetStringBuilder().ToString()); + } + } + [TestCase(_DateCreatedISO)] public void WriteJson_ForDateTime_ReturnsValidUnixTimestamp(string input) { diff --git a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs index 527fb8e..ecafa13 100644 --- a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs +++ b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs @@ -8,16 +8,25 @@ public class DateTimeJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { - return objectType.Equals(typeof(DateTime)); + return (objectType.Equals(typeof(DateTime)) || objectType.Equals(typeof(DateTime?))); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { + reader.Read(); + + object value = reader.Value; + + if (value == null) + { + return null; + } + long unixTimestamp; try { - unixTimestamp = Convert.ToInt64(reader.ReadAsDouble()); + unixTimestamp = Convert.ToInt64(value); } catch (InvalidCastException ex) @@ -33,6 +42,13 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { + if (value == null) + { + writer.WriteRawValue("null"); + + return; + } + DateTime unixEpoch = new DateTime(1970, 1, 1); DateTime dateTime = (DateTime)value; From b73938027febbc0b7051669cc4c9d7e95515cf4a Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 30 Apr 2018 11:29:03 -0400 Subject: [PATCH 5/7] Int64 -> DateTime --- src/Intercom/Clients/UsersClient.cs | 14 ++------------ src/Intercom/Data/Company.cs | 13 +++++++++---- src/Intercom/Data/Conversation.cs | 13 +++++++++---- src/Intercom/Data/ConversationPart.cs | 11 ++++++++--- src/Intercom/Data/Event.cs | 4 +++- src/Intercom/Data/Note.cs | 5 ++++- src/Intercom/Data/Segment.cs | 9 ++++++--- src/Intercom/Data/User.cs | 13 +++++++++---- 8 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/Intercom/Clients/UsersClient.cs b/src/Intercom/Clients/UsersClient.cs index 17702c7..2264aff 100644 --- a/src/Intercom/Clients/UsersClient.cs +++ b/src/Intercom/Clients/UsersClient.cs @@ -240,36 +240,26 @@ public User Delete(String id) return result.Result; } - public User UpdateLastSeenAt(String id, long timestamp) + public User UpdateLastSeenAt(String id, DateTime timestamp) { if (String.IsNullOrEmpty(id)) { throw new ArgumentNullException(nameof(id)); } - if (timestamp <= 0) - { - throw new ArgumentException("'timestamp' argument should be bigger than zero."); - } - ClientResponse result = null; String body = JsonConvert.SerializeObject(new { id = id, last_request_at = timestamp }); result = Post(body); return result.Result; } - public User UpdateLastSeenAt(User user, long timestamp) + public User UpdateLastSeenAt(User user, DateTime timestamp) { if (user == null) { throw new ArgumentNullException(nameof(user)); } - if (timestamp <= 0) - { - throw new ArgumentException("'timestamp' argument should be bigger than zero."); - } - String body = String.Empty; if (!String.IsNullOrEmpty(user.id)) diff --git a/src/Intercom/Data/Company.cs b/src/Intercom/Data/Company.cs index 4e0f982..a00954a 100644 --- a/src/Intercom/Data/Company.cs +++ b/src/Intercom/Data/Company.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using Intercom.Converters.AttributeConverters; +using Intercom.Converters.ClassConverters; namespace Intercom.Data { @@ -12,10 +13,14 @@ public class Company : Model public string name { get; set; } public Plan plan { get; set; } public string company_id { get; set; } - public long? remote_created_at { get; set; } - public long? created_at { get; set; } - public long? updated_at { get; set; } - public long? last_request_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? remote_created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? updated_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? last_request_at { get; set; } public int? monthly_spend { get; set; } public int? session_count { get; set; } public int? user_count { get; set; } diff --git a/src/Intercom/Data/Conversation.cs b/src/Intercom/Data/Conversation.cs index 1551df2..2b2f344 100644 --- a/src/Intercom/Data/Conversation.cs +++ b/src/Intercom/Data/Conversation.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Intercom.Clients; using Intercom.Converters.AttributeConverters; +using Intercom.Converters.ClassConverters; using Intercom.Core; using Intercom.Data; using Intercom.Exceptions; @@ -11,10 +12,14 @@ namespace Intercom.Data { public class Conversation : Model { - public long created_at { get; set; } - public long updated_at { get; set; } - public long? waiting_since { get; set; } - public long? snoozed_until { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime updated_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? waiting_since { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? snoozed_until { get; set; } public Assignee assignee { get; set; } public User user { get; set; } public bool open { get; set; } diff --git a/src/Intercom/Data/ConversationPart.cs b/src/Intercom/Data/ConversationPart.cs index 0dc894b..0ca8246 100644 --- a/src/Intercom/Data/ConversationPart.cs +++ b/src/Intercom/Data/ConversationPart.cs @@ -4,6 +4,8 @@ using Intercom.Clients; using Intercom.Exceptions; using System.Collections.Generic; +using Newtonsoft.Json; +using Intercom.Converters.ClassConverters; namespace Intercom.Data { @@ -11,9 +13,12 @@ public class ConversationPart : Model { public string part_type { get; set; } public string body { get; set; } - public long created_at { get; set; } - public long updated_at { get; set; } - public long notified_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime updated_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime notified_at { get; set; } public Assignee assigned_to { get; set; } public Author author { get; set; } public List attachments { get; set; } diff --git a/src/Intercom/Data/Event.cs b/src/Intercom/Data/Event.cs index eae74cb..f27bf4b 100644 --- a/src/Intercom/Data/Event.cs +++ b/src/Intercom/Data/Event.cs @@ -6,13 +6,15 @@ using System.Collections.Generic; using Newtonsoft.Json; using Intercom.Converters.AttributeConverters; +using Intercom.Converters.ClassConverters; namespace Intercom.Data { public class Event : Model { public string event_name { get; set; } - public long? created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? created_at { get; set; } public string user_id { get; set; } public string email { get; set; } diff --git a/src/Intercom/Data/Note.cs b/src/Intercom/Data/Note.cs index cb72523..e71fa41 100644 --- a/src/Intercom/Data/Note.cs +++ b/src/Intercom/Data/Note.cs @@ -3,12 +3,15 @@ using Intercom.Data; using Intercom.Clients; using Intercom.Exceptions; +using Newtonsoft.Json; +using Intercom.Converters.ClassConverters; namespace Intercom.Data { public class Note : Model { - public long? created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? created_at { get; set; } public string body { get; set; } public Admin author { get; set; } public User user { get; set; } diff --git a/src/Intercom/Data/Segment.cs b/src/Intercom/Data/Segment.cs index 3fa1e88..b57b36d 100644 --- a/src/Intercom/Data/Segment.cs +++ b/src/Intercom/Data/Segment.cs @@ -6,15 +6,18 @@ using Intercom.Clients; using Intercom.Exceptions; - +using Newtonsoft.Json; +using Intercom.Converters.ClassConverters; namespace Intercom.Data { public class Segment : Model { public string name { get; set; } - public long created_at { get; set; } - public long updated_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime updated_at { get; set; } public Segment () { diff --git a/src/Intercom/Data/User.cs b/src/Intercom/Data/User.cs index cbffb37..ad9c4c2 100644 --- a/src/Intercom/Data/User.cs +++ b/src/Intercom/Data/User.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using Intercom.Converters.AttributeConverters; +using Intercom.Converters.ClassConverters; namespace Intercom.Data { @@ -12,12 +13,16 @@ public class User : Model public string email { get; set; } public string phone { get; set; } public string name { get; set; } - public long? updated_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? updated_at { get; set; } public string last_seen_ip { get; set; } public bool? unsubscribed_from_emails { get; set; } - public long? last_request_at { get; set; } - public long? signed_up_at { get; set; } - public long? created_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? last_request_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? signed_up_at { get; set; } + [JsonConverter(typeof(DateTimeJsonConverter))] + public DateTime? created_at { get; set; } public int? session_count { get; set; } public bool? new_session { get; set; } public string user_agent_data { get; set; } From 3363d46c359ca6c194587183f685d3e3ceb00dbf Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Mon, 30 Apr 2018 11:47:13 -0400 Subject: [PATCH 6/7] Use DateTimeOffset Using DateTimeOffset instead of DateTime will allow us to force use of UTC with the API even if the consumer wants to use local timezones. --- .../DateTimeJsonConverterTest.cs | 52 ++++++++++++++----- src/Intercom/Clients/UsersClient.cs | 4 +- .../ClassConverters/DateTimeJsonConverter.cs | 21 +++++--- src/Intercom/Data/Company.cs | 16 +++--- src/Intercom/Data/Conversation.cs | 16 +++--- src/Intercom/Data/ConversationPart.cs | 12 ++--- src/Intercom/Data/Event.cs | 4 +- src/Intercom/Data/Note.cs | 4 +- src/Intercom/Data/Segment.cs | 8 +-- src/Intercom/Data/User.cs | 16 +++--- 10 files changed, 93 insertions(+), 60 deletions(-) diff --git a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs index 6c2410f..4d808f4 100644 --- a/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs +++ b/src/Intercom.Tests/Converters/ClassConverters/DateTimeJsonConverterTest.cs @@ -10,45 +10,71 @@ namespace Intercom.Tests.Converters.ClassConverters { [TestFixture] - public class DateTimeJsonConverterTest : TestBase + public class DateTimeOffsetJsonConverterTest : TestBase { private const string _DateCreatedISO = "1989-04-16T00:15:00Z"; private const string _DateCreatedUnix = "608688900"; private const string _Null = "null"; - private readonly DateTimeJsonConverter _converter; + private readonly DateTimeOffsetJsonConverter _converter; - public DateTimeJsonConverterTest() + public DateTimeOffsetJsonConverterTest() { - _converter = new DateTimeJsonConverter(); + _converter = new DateTimeOffsetJsonConverter(); } [TestCase(_DateCreatedUnix)] - public void ReadJson_ForDateTime_ReturnsValidDateTime(string json) + public void ReadJson_ForDateTimeOffset_ReturnsValidDateTimeOffset(string json) { using (StringReader stringReader = new StringReader(json)) using (JsonReader jsonReader = new JsonTextReader(stringReader)) { - DateTime dateCreated = (DateTime)_converter.ReadJson(jsonReader, typeof(DateTime), null, null); + DateTimeOffset dateCreated = (DateTimeOffset)_converter.ReadJson(jsonReader, typeof(DateTimeOffset), null, null); Assert.AreEqual(_ParseUtcDateString(_DateCreatedISO), dateCreated); } } + [TestCase(_DateCreatedISO)] + public void WriteJsonForDateTimeOffset_ForcesUtc(string input) + { + DateTimeOffset inputDate; + + try + { + inputDate = _ParseUtcDateString(input); + } + + catch (Exception ex) + { + throw new Exception("Failed to properly parse the test input.", ex); + } + + inputDate.ToOffset(TimeSpan.FromHours(-5)); + + using (StringWriter stringWriter = new StringWriter()) + using (JsonWriter jsonWriter = new JsonTextWriter(stringWriter)) + { + _converter.WriteJson(jsonWriter, inputDate, null); + + Assert.AreEqual(_DateCreatedUnix, stringWriter.GetStringBuilder().ToString()); + } + } + [TestCase(_Null)] - public void ReadJson_ForNullableDateTime_ReturnsNull(string json) + public void ReadJson_ForNullableDateTimeOffset_ReturnsNull(string json) { using (StringReader stringReader = new StringReader(json)) using (JsonReader jsonReader = new JsonTextReader(stringReader)) { - DateTime? dateCreated = (DateTime?)_converter.ReadJson(jsonReader, typeof(DateTime?), null, null); + DateTimeOffset? dateCreated = (DateTimeOffset?)_converter.ReadJson(jsonReader, typeof(DateTimeOffset?), null, null); Assert.AreEqual(null, dateCreated); } } [TestCase(null)] - public void WriteJsonForNullableDateTime_ReturnsNull(DateTime? input) + public void WriteJsonForNullableDateTimeOffset_ReturnsNull(DateTimeOffset? input) { using (StringWriter stringWriter = new StringWriter()) using (JsonWriter jsonWriter = new JsonTextWriter(stringWriter)) @@ -60,9 +86,9 @@ public void WriteJsonForNullableDateTime_ReturnsNull(DateTime? input) } [TestCase(_DateCreatedISO)] - public void WriteJson_ForDateTime_ReturnsValidUnixTimestamp(string input) + public void WriteJson_ForDateTimeOffset_ReturnsValidUnixTimestamp(string input) { - DateTime inputDate; + DateTimeOffset inputDate; try { @@ -83,9 +109,9 @@ public void WriteJson_ForDateTime_ReturnsValidUnixTimestamp(string input) } } - private DateTime _ParseUtcDateString(string input) + private DateTimeOffset _ParseUtcDateString(string input) { - return DateTimeOffset.Parse(input).UtcDateTime; + return DateTimeOffset.Parse(input); } } } diff --git a/src/Intercom/Clients/UsersClient.cs b/src/Intercom/Clients/UsersClient.cs index 2264aff..41b0066 100644 --- a/src/Intercom/Clients/UsersClient.cs +++ b/src/Intercom/Clients/UsersClient.cs @@ -240,7 +240,7 @@ public User Delete(String id) return result.Result; } - public User UpdateLastSeenAt(String id, DateTime timestamp) + public User UpdateLastSeenAt(String id, DateTimeOffset timestamp) { if (String.IsNullOrEmpty(id)) { @@ -253,7 +253,7 @@ public User UpdateLastSeenAt(String id, DateTime timestamp) return result.Result; } - public User UpdateLastSeenAt(User user, DateTime timestamp) + public User UpdateLastSeenAt(User user, DateTimeOffset timestamp) { if (user == null) { diff --git a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs index ecafa13..bcccd18 100644 --- a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs +++ b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs @@ -4,11 +4,11 @@ namespace Intercom.Converters.ClassConverters { - public class DateTimeJsonConverter : JsonConverter + public class DateTimeOffsetJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { - return (objectType.Equals(typeof(DateTime)) || objectType.Equals(typeof(DateTime?))); + return (objectType.Equals(typeof(DateTimeOffset)) || objectType.Equals(typeof(DateTimeOffset?))); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) @@ -34,8 +34,8 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist throw new FormatException("Dates must be represented as UNIX timestamps in JSON.", ex); } - DateTime unixEpoch = new DateTime(1970, 1, 1); - DateTime result = unixEpoch.AddSeconds(unixTimestamp); + DateTimeOffset unixEpoch = _GetUnixEpoch(); + DateTimeOffset result = unixEpoch.AddSeconds(unixTimestamp); return result; } @@ -49,12 +49,19 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s return; } - DateTime unixEpoch = new DateTime(1970, 1, 1); - DateTime dateTime = (DateTime)value; + DateTimeOffset unixEpoch = _GetUnixEpoch(); + DateTimeOffset dateTimeOffset = (DateTimeOffset)value; - long unixTimestamp = Convert.ToInt64((dateTime - unixEpoch).TotalSeconds); + dateTimeOffset = dateTimeOffset.ToOffset(TimeSpan.Zero); + + long unixTimestamp = Convert.ToInt64((dateTimeOffset - unixEpoch).TotalSeconds); writer.WriteRawValue(unixTimestamp.ToString()); } + + private DateTimeOffset _GetUnixEpoch() + { + return new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + } } } diff --git a/src/Intercom/Data/Company.cs b/src/Intercom/Data/Company.cs index a00954a..43b4559 100644 --- a/src/Intercom/Data/Company.cs +++ b/src/Intercom/Data/Company.cs @@ -13,14 +13,14 @@ public class Company : Model public string name { get; set; } public Plan plan { get; set; } public string company_id { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? remote_created_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? created_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? updated_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? last_request_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? remote_created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? updated_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? last_request_at { get; set; } public int? monthly_spend { get; set; } public int? session_count { get; set; } public int? user_count { get; set; } diff --git a/src/Intercom/Data/Conversation.cs b/src/Intercom/Data/Conversation.cs index 2b2f344..c6da62e 100644 --- a/src/Intercom/Data/Conversation.cs +++ b/src/Intercom/Data/Conversation.cs @@ -12,14 +12,14 @@ namespace Intercom.Data { public class Conversation : Model { - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime created_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime updated_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? waiting_since { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? snoozed_until { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset updated_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? waiting_since { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? snoozed_until { get; set; } public Assignee assignee { get; set; } public User user { get; set; } public bool open { get; set; } diff --git a/src/Intercom/Data/ConversationPart.cs b/src/Intercom/Data/ConversationPart.cs index 0ca8246..23fcbcc 100644 --- a/src/Intercom/Data/ConversationPart.cs +++ b/src/Intercom/Data/ConversationPart.cs @@ -13,12 +13,12 @@ public class ConversationPart : Model { public string part_type { get; set; } public string body { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime created_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime updated_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime notified_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset updated_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset notified_at { get; set; } public Assignee assigned_to { get; set; } public Author author { get; set; } public List attachments { get; set; } diff --git a/src/Intercom/Data/Event.cs b/src/Intercom/Data/Event.cs index f27bf4b..0198680 100644 --- a/src/Intercom/Data/Event.cs +++ b/src/Intercom/Data/Event.cs @@ -13,8 +13,8 @@ namespace Intercom.Data public class Event : Model { public string event_name { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? created_at { get; set; } public string user_id { get; set; } public string email { get; set; } diff --git a/src/Intercom/Data/Note.cs b/src/Intercom/Data/Note.cs index e71fa41..7e2b2dd 100644 --- a/src/Intercom/Data/Note.cs +++ b/src/Intercom/Data/Note.cs @@ -10,8 +10,8 @@ namespace Intercom.Data { public class Note : Model { - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? created_at { get; set; } public string body { get; set; } public Admin author { get; set; } public User user { get; set; } diff --git a/src/Intercom/Data/Segment.cs b/src/Intercom/Data/Segment.cs index b57b36d..6e65db1 100644 --- a/src/Intercom/Data/Segment.cs +++ b/src/Intercom/Data/Segment.cs @@ -14,10 +14,10 @@ namespace Intercom.Data public class Segment : Model { public string name { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime created_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime updated_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset updated_at { get; set; } public Segment () { diff --git a/src/Intercom/Data/User.cs b/src/Intercom/Data/User.cs index ad9c4c2..32630a4 100644 --- a/src/Intercom/Data/User.cs +++ b/src/Intercom/Data/User.cs @@ -13,16 +13,16 @@ public class User : Model public string email { get; set; } public string phone { get; set; } public string name { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? updated_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? updated_at { get; set; } public string last_seen_ip { get; set; } public bool? unsubscribed_from_emails { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? last_request_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? signed_up_at { get; set; } - [JsonConverter(typeof(DateTimeJsonConverter))] - public DateTime? created_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? last_request_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? signed_up_at { get; set; } + [JsonConverter(typeof(DateTimeOffsetJsonConverter))] + public DateTimeOffset? created_at { get; set; } public int? session_count { get; set; } public bool? new_session { get; set; } public string user_agent_data { get; set; } From d7354a353f698c54a952ba6bea2f40acce97e206 Mon Sep 17 00:00:00 2001 From: Josh Johnson Date: Tue, 1 May 2018 16:07:05 -0400 Subject: [PATCH 7/7] Fix Serialization Error No need to forward to the next token. We can just get the value of the current property. --- .../Converters/ClassConverters/DateTimeJsonConverter.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs index bcccd18..90c21f6 100644 --- a/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs +++ b/src/Intercom/Converters/ClassConverters/DateTimeJsonConverter.cs @@ -13,8 +13,6 @@ public override bool CanConvert(Type objectType) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - reader.Read(); - object value = reader.Value; if (value == null)