Skip to content

Add config option to save DateTime and TimeOffset as Int64 #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions Assets/FullSerializer/Source/Converters/fsDateConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,45 @@ public override bool CanProcess(Type type) {
public override fsResult TrySerialize(object instance, out fsData serialized, Type storageType) {
if (instance is DateTime) {
var dateTime = (DateTime)instance;
serialized = new fsData(dateTime.ToString(DateTimeFormatString));
if(Serializer.Config.SerializeDateTimeAsInteger) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if (

serialized = new fsData(dateTime.Ticks);
} else {
serialized = new fsData(dateTime.ToString(DateTimeFormatString));
return fsResult.Success;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop return (handled immediately below)

}
return fsResult.Success;
}

if (instance is DateTimeOffset) {
var dateTimeOffset = (DateTimeOffset)instance;
serialized = new fsData(dateTimeOffset.ToString(DateTimeOffsetFormatString));
serialized = new fsData(dateTimeOffset.Ticks);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change intentional? The fsConfig comment implies that this should still be serialized as a string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I honestly can't remember - I wrote this ages ago and forgot to submit a PR... it looks like I thought I had a reason for sticking to string for DateTimeOffset. Maybe this code is just a left-over experiment? I'll have a look.

return fsResult.Success;
}

if (instance is TimeSpan) {
var timeSpan = (TimeSpan)instance;
serialized = new fsData(timeSpan.ToString());
if(Serializer.Config.SerializeDateTimeAsInteger) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if (

serialized = new fsData(timeSpan.Ticks);
} else {
serialized = new fsData(timeSpan.ToString());
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would drop all of the config checks in this function; deserialization should be successful regardless of the current config mode.

}
return fsResult.Success;
}

throw new InvalidOperationException("FullSerializer Internal Error -- Unexpected serialization type");
}

public override fsResult TryDeserialize(fsData data, ref object instance, Type storageType) {
if (data.IsString == false) {
return fsResult.Fail("Date deserialization requires a string, not " + data.Type);
if (data.IsString == false && (data.IsInt64 == false || Serializer.Config.SerializeDateTimeAsInteger == false || instance is DateTimeOffset)) {
return fsResult.Fail("Date deserialization requires a string or int, not " + data.Type);
}

if (storageType == typeof(DateTime)) {
if (Serializer.Config.SerializeDateTimeAsInteger && data.IsInt64) {
instance = new DateTime(data.AsInt64);
return fsResult.Success;
}

DateTime result;
if (DateTime.TryParse(data.AsString, null, DateTimeStyles.RoundtripKind, out result)) {
instance = result;
Expand Down Expand Up @@ -84,6 +98,11 @@ public override fsResult TryDeserialize(fsData data, ref object instance, Type s
}

if (storageType == typeof(TimeSpan)) {
if (Serializer.Config.SerializeDateTimeAsInteger && data.IsInt64) {
instance = new TimeSpan(data.AsInt64);
return fsResult.Success;
}

TimeSpan result;
if (TimeSpan.TryParse(data.AsString, out result)) {
instance = result;
Expand Down
6 changes: 6 additions & 0 deletions Assets/FullSerializer/Source/fsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ public class fsConfig {
/// </summary>
public string CustomDateTimeFormatString = null;

/// <summary>
/// If true, DateTime and TimeSpan will be saved as 64 bit integers
/// rather than strings. DateTimeOffset will still be saved as string.
/// </summary>
public bool SerializeDateTimeAsInteger = false;

/// <summary>
/// Int64 and UInt64 will be serialized and deserialized as string for
/// compatibility
Expand Down
48 changes: 39 additions & 9 deletions Assets/FullSerializer/Testing/Editor/DateTimeTests.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,44 @@
using System;
using FullSerializer;
using NUnit.Framework;

public class DateTimeTests {
[Test]
public void StrangeFormatTests() {
var serializer = new fsSerializer();
DateTime time = DateTime.Now;
serializer.TryDeserialize(new fsData("2016-01-22T12:06:57.503005Z"), ref time).AssertSuccessWithoutWarnings();
namespace FullSerializer.Tests {
public class DateTimeTests {
[Test]
public void StrangeFormatTests() {
var serializer = new fsSerializer();
DateTime time = DateTime.Now;
serializer.TryDeserialize(new fsData("2016-01-22T12:06:57.503005Z"), ref time).AssertSuccessWithoutWarnings();

Assert.AreEqual(Convert.ToDateTime("2016-01-22T12:06:57.503005Z"), time);
Assert.AreEqual(Convert.ToDateTime("2016-01-22T12:06:57.503005Z"), time);
}

[Test]
public void TestDateTimeAsIntIsInt() {
var serializer = new fsSerializer {Config = {SerializeDateTimeAsInteger = true}};

var original = new DateTime(1985, 8, 22, 4, 19, 01, 123, DateTimeKind.Utc);
fsData serializedData;
serializer.TrySerialize(original, out serializedData).AssertSuccessWithoutWarnings();

Assert.That(serializedData.IsInt64);
}

[Test]
public void TestDateTimeAsIntRoundTrips() {
var serializer = new fsSerializer {Config = {SerializeDateTimeAsInteger = true}};

var original = new DateTime(1985, 8, 22, 4, 19, 01, 123, DateTimeKind.Utc);
var deserialized = Clone(original, serializer, serializer);

Assert.AreEqual(original, deserialized);
}

public static T Clone<T>(T original, fsSerializer serializer, fsSerializer deserializer) {
fsData serializedData;
serializer.TrySerialize(original, out serializedData).AssertSuccessWithoutWarnings();
var actual = default(T);
deserializer.TryDeserialize(serializedData, ref actual);
return actual;
}
}
}
}