Skip to content

Commit

Permalink
Handle ISO8601 basic format offsets (#4910) (#4925)
Browse files Browse the repository at this point in the history
This commit handles ISO8601 basic format offsets
of the form:

- [+-]hh
- [+-]hhmm

in addition to the extended format offset form

- [+-]hh:mm

Fixes #4876

Co-authored-by: Russ Cam <russ.cam@elastic.co>
github-actions[bot] and russcam authored Aug 4, 2020

Verified

This commit was signed with the committer’s verified signature.
SorsOps SorsOps
1 parent 9a67121 commit 2404113
Showing 2 changed files with 109 additions and 6 deletions.
29 changes: 23 additions & 6 deletions src/Elasticsearch.Net/Utf8Json/Formatters/DateTimeFormatter.cs
Original file line number Diff line number Diff line change
@@ -359,14 +359,22 @@ public DateTime Deserialize(ref JsonReader reader, IJsonFormatterResolver format
}
else if (i < to && array[i] == '-' || array[i] == '+')
{
if (!(i + 5 < to)) goto ERROR;
if (len != 30 && len != 32 && len != 33) goto ERROR;

kind = DateTimeKind.Local;
var minus = array[i++] == '-';

var h = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0');
i++;
var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0');
var m = 0;
if (i < to)
{
if (len == 33)
{
if (array[i] != ':') goto ERROR;
i++;
}
m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0');
}

var offset = new TimeSpan(h, m, 0);
if (minus) offset = offset.Negate();
@@ -705,13 +713,22 @@ public DateTimeOffset Deserialize(ref JsonReader reader, IJsonFormatterResolver

if (i < to && array[i] == '-' || array[i] == '+')
{
if (!(i + 5 < to)) goto ERROR;
if (len != 30 && len != 32 && len != 33) goto ERROR;

var minus = array[i++] == '-';

var h = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0');
i++;
var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0');
var m = 0;
if (i < to)
{
if (len == 33)
{
if (array[i] != ':') goto ERROR;
i++;
}

m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0');
}

var offset = new TimeSpan(h, m, 0);
if (minus) offset = offset.Negate();
86 changes: 86 additions & 0 deletions tests/Tests.Reproduce/GitHubIssue4876.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using System;
using System.IO;
using System.Text;
using Elastic.Elasticsearch.Xunit.XunitPlumbing;
using FluentAssertions;
using Nest;

namespace Tests.Reproduce
{
public class GitHubIssue4876
{
private readonly ElasticClient _client;

public GitHubIssue4876() => _client = new ElasticClient();

[U]
public void CanDeserializeExtendedFormatOffsetIso8601DateTime() =>
AssertDateTime("{\"timestamp\":\"2020-07-31T12:29:29.4425068+10:00\"}");

[U]
public void CanDeserializeBasicFormatOffsetWithMinutesIso8601DateTime() =>
AssertDateTime("{\"timestamp\":\"2020-07-31T12:29:29.4425068+1000\"}");

[U]
public void CanDeserializeBasicFormatOffsetIso8601DateTime() =>
AssertDateTime("{\"timestamp\":\"2020-07-31T12:29:29.4425068+10\"}");

[U]
public void ThrowExceptionWhenInvalidBasicFormatOffset()
{
Action action = () => AssertDateTime("{\"timestamp\":\"2020-07-31T12:29:29.4425068+100\"}");
action.Should().Throw<InvalidOperationException>();
}

[U]
public void ThrowExceptionWhenInvalidBasicFormatOffset2()
{
Action action = () => AssertDateTime("{\"timestamp\":\"2020-07-31T12:29:29.4425068-10000\"}");
action.Should().Throw<InvalidOperationException>();
}

[U]
public void CanDeserializeExtendedFormatOffsetIso8601DateTimeOffset() =>
AssertDateTimeOffset("{\"timestamp\":\"2020-07-31T12:29:29.4425068+10:00\"}");

[U]
public void CanDeserializeBasicFormatOffsetWithMinutesIso8601DateTimeOffset() =>
AssertDateTimeOffset("{\"timestamp\":\"2020-07-31T12:29:29.4425068+1000\"}");

[U]
public void CanDeserializeBasicFormatOffsetIso8601DateTimeOffset() =>
AssertDateTimeOffset("{\"timestamp\":\"2020-07-31T12:29:29.4425068+10\"}");

private void AssertDateTime(string json)
{
var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var document = _client.SourceSerializer.Deserialize<Document>(stream);

document.Timestamp.Should().Be(
new DateTime(637317593694425068, DateTimeKind.Utc).ToLocalTime());
}

private void AssertDateTimeOffset(string json)
{
var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var document = _client.SourceSerializer.Deserialize<Document2>(stream);

document.Timestamp.Should().Be(
new DateTimeOffset(637317593694425068, TimeSpan.Zero));
}

public class Document
{
public DateTime Timestamp { get; set; }
}

public class Document2
{
public DateTimeOffset Timestamp { get; set; }
}
}
}

0 comments on commit 2404113

Please sign in to comment.