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

Changed the runtime type for LocalDateType, LocalTimeType, and DateType #7717

Merged
merged 4 commits into from
Nov 17, 2024
Merged
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
38 changes: 22 additions & 16 deletions src/HotChocolate/Core/src/Types.Scalars/LocalDateType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace HotChocolate.Types;
/// character sequences YYYY-MM-DD. The scalar follows the specification defined in
/// <a href="https://tools.ietf.org/html/rfc3339">RFC3339</a>
/// </summary>
public class LocalDateType : ScalarType<DateTime, StringValueNode>
public class LocalDateType : ScalarType<DateOnly, StringValueNode>
{
private const string _localFormat = "yyyy-MM-dd";

Expand Down Expand Up @@ -42,13 +42,14 @@ public override IValueNode ParseResult(object? resultValue)
{
null => NullValueNode.Default,
string s => new StringValueNode(s),
DateTimeOffset o => ParseValue(o.DateTime),
DateTime dt => ParseValue(dt),
DateOnly d => ParseValue(d),
DateTimeOffset o => ParseValue(DateOnly.FromDateTime(o.DateTime)),
DateTime dt => ParseValue(DateOnly.FromDateTime(dt)),
_ => throw ThrowHelper.LocalDateType_ParseValue_IsInvalid(this),
};
}

protected override DateTime ParseLiteral(StringValueNode valueSyntax)
protected override DateOnly ParseLiteral(StringValueNode valueSyntax)
{
if (TryDeserializeFromString(valueSyntax.Value, out var value))
{
Expand All @@ -58,7 +59,7 @@ protected override DateTime ParseLiteral(StringValueNode valueSyntax)
throw ThrowHelper.LocalDateType_ParseLiteral_IsInvalid(this);
}

protected override StringValueNode ParseValue(DateTime runtimeValue)
protected override StringValueNode ParseValue(DateOnly runtimeValue)
{
return new(Serialize(runtimeValue));
}
Expand All @@ -70,10 +71,13 @@ public override bool TrySerialize(object? runtimeValue, out object? resultValue)
case null:
resultValue = null;
return true;
case DateTime dt:
resultValue = Serialize(dt);
case DateOnly d:
resultValue = Serialize(d);
return true;
case DateTimeOffset o:
resultValue = Serialize(o);
return true;
case DateTimeOffset dt:
case DateTime dt:
resultValue = Serialize(dt);
return true;
default:
Expand All @@ -92,11 +96,14 @@ public override bool TryDeserialize(object? resultValue, out object? runtimeValu
case string s when TryDeserializeFromString(s, out var d):
runtimeValue = d;
return true;
case DateTimeOffset d:
runtimeValue = d.DateTime;
case DateOnly d:
runtimeValue = d;
return true;
case DateTimeOffset o:
runtimeValue = DateOnly.FromDateTime(o.DateTime);
return true;
case DateTime dt:
runtimeValue = dt;
runtimeValue = DateOnly.FromDateTime(dt);
return true;
default:
runtimeValue = null;
Expand All @@ -111,16 +118,15 @@ private static string Serialize(IFormattable value)

private static bool TryDeserializeFromString(
string? serialized,
[NotNullWhen(true)] out DateTime? value)
[NotNullWhen(true)] out DateOnly? value)
{
if (serialized is not null
&& DateTime.TryParse(
&& DateOnly.TryParse(
serialized,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out var dt))
out var date))
{
value = dt;
value = date;
return true;
}

Expand Down
30 changes: 18 additions & 12 deletions src/HotChocolate/Core/src/Types.Scalars/LocalTimeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace HotChocolate.Types;
/// The `LocalTime` scalar type is a local time string (i.e., with no associated timezone)
/// in 24-hr HH:mm:ss.
/// </summary>
public class LocalTimeType : ScalarType<DateTime, StringValueNode>
public class LocalTimeType : ScalarType<TimeOnly, StringValueNode>
{
private const string _localFormat = "HH:mm:ss";

Expand Down Expand Up @@ -41,13 +41,14 @@ public override IValueNode ParseResult(object? resultValue)
{
null => NullValueNode.Default,
string s => new StringValueNode(s),
TimeOnly t => ParseValue(t),
DateTimeOffset d => ParseValue(d),
DateTime dt => ParseValue(dt),
_ => throw ThrowHelper.LocalTimeType_ParseValue_IsInvalid(this),
};
}

protected override DateTime ParseLiteral(StringValueNode valueSyntax)
protected override TimeOnly ParseLiteral(StringValueNode valueSyntax)
{
if (TryDeserializeFromString(valueSyntax.Value, out var value))
{
Expand All @@ -57,7 +58,7 @@ protected override DateTime ParseLiteral(StringValueNode valueSyntax)
throw ThrowHelper.LocalTimeType_ParseLiteral_IsInvalid(this);
}

protected override StringValueNode ParseValue(DateTime runtimeValue)
protected override StringValueNode ParseValue(TimeOnly runtimeValue)
{
return new(Serialize(runtimeValue));
}
Expand All @@ -69,6 +70,9 @@ public override bool TrySerialize(object? runtimeValue, out object? resultValue)
case null:
resultValue = null;
return true;
case TimeOnly t:
resultValue = Serialize(t);
return true;
case DateTimeOffset dt:
resultValue = Serialize(dt);
return true;
Expand All @@ -88,14 +92,17 @@ public override bool TryDeserialize(object? resultValue, out object? runtimeValu
case null:
runtimeValue = null;
return true;
case string s when TryDeserializeFromString(s, out var d):
runtimeValue = d;
case string s when TryDeserializeFromString(s, out var t):
runtimeValue = t;
return true;
case TimeOnly t:
runtimeValue = t;
return true;
case DateTimeOffset d:
runtimeValue = d.DateTime;
runtimeValue = TimeOnly.FromDateTime(d.DateTime);
return true;
case DateTime d:
runtimeValue = d;
runtimeValue = TimeOnly.FromDateTime(d);
return true;
default:
runtimeValue = null;
Expand All @@ -110,16 +117,15 @@ private static string Serialize(IFormattable value)

private static bool TryDeserializeFromString(
string? serialized,
[NotNullWhen(true)] out DateTime? value)
[NotNullWhen(true)] out TimeOnly? value)
{
if (serialized is not null
&& DateTime.TryParse(
&& TimeOnly.TryParse(
serialized,
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out var dt))
out var time))
{
value = dt;
value = time;
return true;
}

Expand Down
125 changes: 55 additions & 70 deletions src/HotChocolate/Core/src/Types/Types/Scalars/DateType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@

namespace HotChocolate.Types;

public class DateType : ScalarType<DateTime, StringValueNode>
public class DateType : ScalarType<DateOnly, StringValueNode>
{
private const string _dateFormat = "yyyy-MM-dd";

/// <summary>
/// Initializes a new instance of the <see cref="DateTimeType"/> class.
/// Initializes a new instance of the <see cref="DateType"/> class.
/// </summary>
public DateType(
string name,
Expand All @@ -24,14 +24,14 @@ public DateType(
}

/// <summary>
/// Initializes a new instance of the <see cref="DateTimeType"/> class.
/// Initializes a new instance of the <see cref="DateType"/> class.
/// </summary>
[ActivatorUtilitiesConstructor]
public DateType() : this(ScalarNames.Date, TypeResources.DateType_Description)
{
}

protected override DateTime ParseLiteral(StringValueNode valueSyntax)
protected override DateOnly ParseLiteral(StringValueNode valueSyntax)
{
if (TryDeserializeFromString(valueSyntax.Value, out var value))
{
Expand All @@ -43,98 +43,83 @@ protected override DateTime ParseLiteral(StringValueNode valueSyntax)
this);
}

protected override StringValueNode ParseValue(DateTime runtimeValue) =>
protected override StringValueNode ParseValue(DateOnly runtimeValue) =>
new(Serialize(runtimeValue));

public override IValueNode ParseResult(object? resultValue)
{
if (resultValue is null)
return resultValue switch
{
return NullValueNode.Default;
}

if (resultValue is string s)
{
return new StringValueNode(s);
}

if (resultValue is DateTimeOffset o)
{
return ParseValue(o.DateTime);
}

if (resultValue is DateTime dt)
{
return ParseValue(dt);
}

throw new SerializationException(
TypeResourceHelper.Scalar_Cannot_ParseResult(Name, resultValue.GetType()),
this);
null => NullValueNode.Default,
string s => new StringValueNode(s),
DateOnly d => ParseValue(d),
DateTimeOffset o => ParseValue(DateOnly.FromDateTime(o.UtcDateTime)),
DateTime dt => ParseValue(DateOnly.FromDateTime(dt.ToUniversalTime())),
_ => throw new SerializationException(
TypeResourceHelper.Scalar_Cannot_ParseResult(Name, resultValue.GetType()), this)
};
}

public override bool TrySerialize(object? runtimeValue, out object? resultValue)
{
if (runtimeValue is null)
switch (runtimeValue)
{
resultValue = null;
return true;
}

if (runtimeValue is DateTime dt)
{
resultValue = Serialize(dt);
return true;
case null:
resultValue = null;
return true;
case DateOnly d:
resultValue = Serialize(d);
return true;
case DateTimeOffset o:
resultValue = Serialize(o.UtcDateTime);
return true;
case DateTime dt:
resultValue = Serialize(dt.ToUniversalTime());
return true;
default:
resultValue = null;
return false;
}

resultValue = null;
return false;
}

public override bool TryDeserialize(object? resultValue, out object? runtimeValue)
{
if (resultValue is null)
switch (resultValue)
{
runtimeValue = null;
return true;
case null:
runtimeValue = null;
return true;
case string s when TryDeserializeFromString(s, out var d):
runtimeValue = d;
return true;
case DateOnly d:
runtimeValue = d;
return true;
case DateTimeOffset o:
runtimeValue = DateOnly.FromDateTime(o.UtcDateTime);
return true;
case DateTime dt:
runtimeValue = DateOnly.FromDateTime(dt.ToUniversalTime());
return true;
default:
runtimeValue = null;
return false;
}

if (resultValue is string s && TryDeserializeFromString(s, out var d))
{
runtimeValue = d;
return true;
}

if (resultValue is DateTimeOffset dt)
{
runtimeValue = dt.UtcDateTime;
return true;
}

if (resultValue is DateTime)
{
runtimeValue = resultValue;
return true;
}

runtimeValue = null;
return false;
}

private static string Serialize(DateTime value) =>
value.Date.ToString(_dateFormat, CultureInfo.InvariantCulture);
private static string Serialize(IFormattable value) =>
value.ToString(_dateFormat, CultureInfo.InvariantCulture);

private static bool TryDeserializeFromString(
string? serialized,
[NotNullWhen(true)] out DateTime? value)
[NotNullWhen(true)] out DateOnly? value)
{
if (DateTime.TryParse(
if (DateOnly.TryParse(
serialized,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var dateTime))
out var date))
{
value = dateTime.Date;
value = date;
return true;
}

Expand Down
Loading
Loading