Skip to content

Commit a2ef1d7

Browse files
authored
Added switch to disable the LocalDate/LocalTime/Date format check (#8408)
1 parent 9ed4805 commit a2ef1d7

File tree

6 files changed

+134
-14
lines changed

6 files changed

+134
-14
lines changed

src/HotChocolate/Core/src/Types/Types/Scalars/DateType.cs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,32 @@ namespace HotChocolate.Types;
88
public class DateType : ScalarType<DateOnly, StringValueNode>
99
{
1010
private const string DateFormat = "yyyy-MM-dd";
11+
private readonly bool _enforceSpecFormat;
1112

1213
/// <summary>
1314
/// Initializes a new instance of the <see cref="DateType"/> class.
1415
/// </summary>
1516
public DateType(
1617
string name,
1718
string? description = null,
18-
BindingBehavior bind = BindingBehavior.Explicit)
19+
BindingBehavior bind = BindingBehavior.Explicit,
20+
bool disableFormatCheck = false)
1921
: base(name, bind)
2022
{
2123
Description = description;
24+
_enforceSpecFormat = !disableFormatCheck;
25+
}
26+
27+
/// <summary>
28+
/// Initializes a new instance of the <see cref="DateType"/> class.
29+
/// </summary>
30+
public DateType(bool disableFormatCheck)
31+
: this(
32+
ScalarNames.Date,
33+
TypeResources.DateType_Description,
34+
BindingBehavior.Implicit,
35+
disableFormatCheck: disableFormatCheck)
36+
{
2237
}
2338

2439
/// <summary>
@@ -108,14 +123,27 @@ public override bool TryDeserialize(object? resultValue, out object? runtimeValu
108123
private static string Serialize(IFormattable value) =>
109124
value.ToString(DateFormat, CultureInfo.InvariantCulture);
110125

111-
private static bool TryDeserializeFromString(
126+
private bool TryDeserializeFromString(
112127
string? serialized,
113128
[NotNullWhen(true)] out DateOnly? value)
114129
{
115-
if (DateOnly.TryParseExact(
116-
serialized,
117-
DateFormat,
118-
out var date))
130+
if (_enforceSpecFormat)
131+
{
132+
if (DateOnly.TryParseExact(
133+
serialized,
134+
DateFormat,
135+
CultureInfo.InvariantCulture,
136+
DateTimeStyles.None,
137+
out var date))
138+
{
139+
value = date;
140+
return true;
141+
}
142+
}
143+
else if (DateOnly.TryParse(
144+
serialized,
145+
CultureInfo.InvariantCulture,
146+
out var date))
119147
{
120148
value = date;
121149
return true;

src/HotChocolate/Core/src/Types/Types/Scalars/LocalDateType.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,32 @@ namespace HotChocolate.Types;
1313
public class LocalDateType : ScalarType<DateOnly, StringValueNode>
1414
{
1515
private const string LocalFormat = "yyyy-MM-dd";
16+
private readonly bool _enforceSpecFormat;
1617

1718
/// <summary>
1819
/// Initializes a new instance of the <see cref="LocalDateType"/> class.
1920
/// </summary>
2021
public LocalDateType(
2122
string name,
2223
string? description = null,
23-
BindingBehavior bind = BindingBehavior.Explicit)
24+
BindingBehavior bind = BindingBehavior.Explicit,
25+
bool disableFormatCheck = false)
2426
: base(name, bind)
2527
{
2628
Description = description;
29+
_enforceSpecFormat = !disableFormatCheck;
30+
}
31+
32+
/// <summary>
33+
/// Initializes a new instance of the <see cref="LocalDateType"/> class.
34+
/// </summary>
35+
public LocalDateType(bool disableFormatCheck)
36+
: this(
37+
ScalarNames.LocalDate,
38+
TypeResources.LocalDateType_Description,
39+
BindingBehavior.Implicit,
40+
disableFormatCheck: disableFormatCheck)
41+
{
2742
}
2843

2944
/// <summary>
@@ -120,17 +135,27 @@ private static string Serialize(IFormattable value)
120135
return value.ToString(LocalFormat, CultureInfo.InvariantCulture);
121136
}
122137

123-
private static bool TryDeserializeFromString(
138+
private bool TryDeserializeFromString(
124139
string? serialized,
125140
[NotNullWhen(true)] out DateOnly? value)
126141
{
127-
if (serialized is not null
128-
&& DateOnly.TryParseExact(
142+
if (_enforceSpecFormat)
143+
{
144+
if (DateOnly.TryParseExact(
129145
serialized,
130146
LocalFormat,
131147
CultureInfo.InvariantCulture,
132148
DateTimeStyles.None,
133149
out var date))
150+
{
151+
value = date;
152+
return true;
153+
}
154+
}
155+
else if (DateOnly.TryParse(
156+
serialized,
157+
CultureInfo.InvariantCulture,
158+
out var date))
134159
{
135160
value = date;
136161
return true;

src/HotChocolate/Core/src/Types/Types/Scalars/LocalTimeType.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,32 @@ namespace HotChocolate.Types;
1212
public class LocalTimeType : ScalarType<TimeOnly, StringValueNode>
1313
{
1414
private const string LocalFormat = "HH:mm:ss";
15+
private readonly bool _enforceSpecFormat;
1516

1617
/// <summary>
1718
/// Initializes a new instance of the <see cref="LocalTimeType"/> class.
1819
/// </summary>
1920
public LocalTimeType(
2021
string name,
2122
string? description = null,
22-
BindingBehavior bind = BindingBehavior.Explicit)
23+
BindingBehavior bind = BindingBehavior.Explicit,
24+
bool disableFormatCheck = false)
2325
: base(name, bind)
2426
{
2527
Description = description;
28+
_enforceSpecFormat = !disableFormatCheck;
29+
}
30+
31+
/// <summary>
32+
/// Initializes a new instance of the <see cref="LocalTimeType"/> class.
33+
/// </summary>
34+
public LocalTimeType(bool disableFormatCheck)
35+
: this(
36+
ScalarNames.LocalTime,
37+
TypeResources.LocalTimeType_Description,
38+
BindingBehavior.Implicit,
39+
disableFormatCheck: disableFormatCheck)
40+
{
2641
}
2742

2843
/// <summary>
@@ -119,17 +134,27 @@ private static string Serialize(IFormattable value)
119134
return value.ToString(LocalFormat, CultureInfo.InvariantCulture);
120135
}
121136

122-
private static bool TryDeserializeFromString(
137+
private bool TryDeserializeFromString(
123138
string? serialized,
124139
[NotNullWhen(true)] out TimeOnly? value)
125140
{
126-
if (serialized is not null
127-
&& TimeOnly.TryParseExact(
141+
if (_enforceSpecFormat)
142+
{
143+
if (TimeOnly.TryParseExact(
128144
serialized,
129145
LocalFormat,
130146
CultureInfo.InvariantCulture,
131147
DateTimeStyles.None,
132148
out var time))
149+
{
150+
value = time;
151+
return true;
152+
}
153+
}
154+
else if (TimeOnly.TryParse(
155+
serialized,
156+
CultureInfo.InvariantCulture,
157+
out var time))
133158
{
134159
value = time;
135160
return true;

src/HotChocolate/Core/test/Types.Tests/Types/Scalars/DateTypeTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,20 @@ public async Task DateOnly_As_ReturnValue()
474474
.MatchSnapshotAsync();
475475
}
476476

477+
[Fact]
478+
public void DateType_Relaxed_Format_Check()
479+
{
480+
// arrange
481+
const string s = "2011-08-30T08:46:14.116";
482+
483+
// act
484+
var dateType = new DateType(disableFormatCheck: true);
485+
var result = dateType.Deserialize(s);
486+
487+
// assert
488+
Assert.IsType<DateOnly>(result);
489+
}
490+
477491
public class Query
478492
{
479493
[GraphQLType(typeof(DateType))]

src/HotChocolate/Core/test/Types.Tests/Types/Scalars/LocalDateTypeTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,20 @@ public async Task DateOnly_As_ReturnValue()
507507
.MatchSnapshotAsync();
508508
}
509509

510+
[Fact]
511+
public void LocalDate_Relaxed_Format_Check()
512+
{
513+
// arrange
514+
const string s = "2011-08-30T08:46:14.116";
515+
516+
// act
517+
var localDateType = new LocalDateType(disableFormatCheck: true);
518+
var result = localDateType.Deserialize(s);
519+
520+
// assert
521+
Assert.IsType<DateOnly>(result);
522+
}
523+
510524
public class Query
511525
{
512526
[GraphQLType(typeof(LocalDateType))]

src/HotChocolate/Core/test/Types.Tests/Types/Scalars/LocalTimeTypeTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,20 @@ public async Task TimeOnly_As_ReturnValue()
472472
.MatchSnapshotAsync();
473473
}
474474

475+
[Fact]
476+
public void LocalTime_Relaxed_Format_Check()
477+
{
478+
// arrange
479+
const string s = "8:46 am";
480+
481+
// act
482+
var localTimeType = new LocalTimeType(disableFormatCheck: true);
483+
var result = localTimeType.Deserialize(s);
484+
485+
// assert
486+
Assert.IsType<TimeOnly>(result);
487+
}
488+
475489
public class Query
476490
{
477491
[GraphQLType(typeof(LocalTimeType))]

0 commit comments

Comments
 (0)