Skip to content
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

Feature custom date converter #8

Open
wants to merge 4 commits into
base: main
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
98 changes: 98 additions & 0 deletions dgc.tests/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,35 @@ private static CWT CreateCWTTestData()
return cwt;
}

private static DgCertificate CreateTestEntryCertificate()
{
return new DgCertificate()
{
DateOfBirth = new DateTimeOffset(1978, 1, 26, 0, 0, 0, TimeSpan.Zero),
Name = new Nam()
{
FamilyName = "������",
GivenName = "����� ��������",
FamilyNameTransliterated = "Petkov",
GivenNameTraslitaerated = "Stamo<Georgiev"
},
Test = new TestEntry[] {
new TestEntry()
{
CertificateIdentifier = "urn:uvci:01:BG:1234#5",
CountryOfTest = "BG",
Disease = "840539006",
Issuer = "Ministry of Health",
SampleTakenDate = new DateTimeOffset(2021, 6, 14, 9, 37, 58, TimeSpan.Zero),
TestingCenter = "2204141503",
TestResult = "260415000",
TestResutDate = new DateTimeOffset(2021, 6, 15, 8, 45, 12, TimeSpan.Zero),
TestType = "LP6464-4"
}
}
};
}

[TestMethod]
public void EncodeDecode_RoundTrip_IsValid()
{
Expand Down Expand Up @@ -249,5 +278,74 @@ public void DecodeTest_Vaccination_FaultyCbor()
return;
}
}

/// <summary>
/// Testing DGCDateTimeConverter
/// Only TestEntry has different types of dates
/// </summary>
[TestMethod]
public void SerializeDates()
{
var cert = CreateTestEntryCertificate();
var json = Newtonsoft.Json.JsonConvert.SerializeObject(cert, new Newtonsoft.Json.JsonSerializerSettings()
{
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
Converters = new List<Newtonsoft.Json.JsonConverter>()
{
new DGCDateTimeConverter()
}
});

Assert.IsTrue(json.Contains("\"dob\":\"1978-01-26\""));
Assert.IsTrue(json.Contains("\"sc\":\"2021-06-14T09:37:58+00:00\""));
Assert.IsTrue(json.Contains("\"dr\":\"2021-06-15T08:45:12+00:00\""));
}

/// <summary>
/// Testing DGCDateTimeConverter with default format
/// </summary>
[TestMethod]
public void SerializeDatesWithoutTime()
{
var cert = CreateTestEntryCertificate();
var json = Newtonsoft.Json.JsonConvert.SerializeObject(cert, new Newtonsoft.Json.JsonSerializerSettings()
{
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
Converters = new List<Newtonsoft.Json.JsonConverter>()
{
new DGCDateTimeConverter(null)
}
});

Assert.IsTrue(json.Contains("\"dob\":\"1978-01-26\""));
Assert.IsTrue(json.Contains("\"sc\":\"2021-06-14\""));
Assert.IsTrue(json.Contains("\"dr\":\"2021-06-15\""));
}

/// <summary>
/// Testing DGCDateTimeConverter with special formatters
/// </summary>
[TestMethod]
public void SerializeDatesWithSpecialFormat()
{
var cert = CreateTestEntryCertificate();
var json = Newtonsoft.Json.JsonConvert.SerializeObject(cert, new Newtonsoft.Json.JsonSerializerSettings()
{
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
Converters = new List<Newtonsoft.Json.JsonConverter>()
{
new DGCDateTimeConverter(new (string, string)[]
{
("dob", "yy-MM-dd"),
(@"t\[\d+\]\.(sc)", "yyyy"),
(@"t\[\d+\]\.(dr)", "yyyy-MM")
})
}
});

Assert.IsTrue(json.Contains("\"dob\":\"78-01-26\""));
Assert.IsTrue(json.Contains("\"sc\":\"2021\""));
Assert.IsTrue(json.Contains("\"dr\":\"2021-06\""));
}
}
}
11 changes: 10 additions & 1 deletion dgc/CWT.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Newtonsoft.Json;
using PeterO.Cbor;
using System;
using System.Collections.Generic;

namespace DGC
{
Expand Down Expand Up @@ -46,7 +47,15 @@ internal byte[] EncodeToBytes()

var cborHcer = CBORObject.NewMap();

var json = JsonConvert.SerializeObject(DGCv1);
var json = JsonConvert.SerializeObject(DGCv1, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
Converters = new List<JsonConverter>()
{
new DGCDateTimeConverter()
}
});

cborHcer[1] = CBORObject.FromJSONString(json);

cbor[Header_HCERT] = cborHcer;
Expand Down
129 changes: 129 additions & 0 deletions dgc/DGCDateTimeConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;

namespace DGC
{
/// <summary>
/// Digital Green Certificate Date Time Converter
/// </summary>
public class DGCDateTimeConverter : IsoDateTimeConverter
{
private readonly IEnumerable<(string pattern, string format)> formatters;

/// <summary>
/// Initialize converter with default values
/// </summary>
public DGCDateTimeConverter()
{
formatters = new (string pattern, string formatter)[]
{
// Formates 'sc' and 'dr' in 't' array as ISO 8601 Date
// If pattern matches JSON Path, formatter is used
(@"t\[\d+\]\.(sc|dr)", "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK")
};

this.DateTimeFormat = "yyyy-MM-dd";
this.Culture = CultureInfo.InvariantCulture;
}

/// <summary>
/// Initialize converter with custom formatters
/// </summary>
/// <param name="_formatters">Collection of Custom formatters</param>
public DGCDateTimeConverter(IEnumerable<(string pattern, string format)> _formatters)
: this()
{
formatters = _formatters;
}

/// <summary>
/// Serializes Dates with given format
/// </summary>
/// <param name="writer">Writes value as string</param>
/// <param name="value">Date to be serialized</param>
/// <param name="serializer">Serializer settings</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
string text = null;

try
{
if (value is DateTime dateTime)
{
if (formatters == null || formatters.Count() == 0)
{
text = dateTime
.ToUniversalTime()
.ToString(DateTimeFormat, Culture);
}
else
{
foreach (var formatter in formatters)
{
Regex tester = new Regex(formatter.pattern);

if (tester.IsMatch(writer.Path))
{
text = dateTime
.ToUniversalTime()
.ToString(formatter.format, Culture);
}
}

if (text == null)
{
text = dateTime
.ToUniversalTime()
.ToString(DateTimeFormat, Culture);
}
}
}
else if (value is DateTimeOffset dateTimeOffset)
{
if (formatters == null || formatters.Count() == 0)
{
text = dateTimeOffset
.ToUniversalTime()
.ToString(DateTimeFormat, Culture);
}
else
{
foreach (var formatter in formatters)
{
Regex tester = new Regex(formatter.pattern);

if (tester.IsMatch(writer.Path))
{
text = dateTimeOffset
.ToUniversalTime()
.ToString(formatter.format, Culture);
}
}

if (text == null)
{
text = dateTimeOffset
.ToUniversalTime()
.ToString(DateTimeFormat, Culture);
}
}
}
else
{
throw new ArgumentException();
}

writer.WriteValue(text);
}
catch (Exception)
{
base.WriteJson(writer, value, serializer);
}
}
}
}