Add support for multiple ctors in JavaScriptDateTimeConverter
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
cls
|
||||
powershell -Command "& { [Console]::WindowWidth = 150; [Console]::WindowHeight = 50; Start-Transcript '%~dp0\Temp\runbuild.txt'; Import-Module '%~dp0..\Tools\PSake\psake.psm1'; Invoke-psake '%~dp0..\Build\build.ps1' %*; Stop-Transcript; exit !($psake.build_success); }"
|
||||
powershell -Command "& { Start-Transcript '%~dp0\Temp\runbuild.txt'; Import-Module '%~dp0..\Tools\PSake\psake.psm1'; Invoke-psake '%~dp0..\Build\build.ps1' %*; Stop-Transcript; exit !($psake.build_success); }"
|
||||
|
||||
ECHO %ERRORLEVEL%
|
||||
EXIT /B %ERRORLEVEL%
|
||||
@@ -124,6 +124,79 @@ namespace Newtonsoft.Json.Tests.Converters
|
||||
Assert.AreEqual(new DateTime(2000, 12, 15, 22, 11, 3, 55, DateTimeKind.Utc), result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeDateTime_MultipleArguments()
|
||||
{
|
||||
JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
|
||||
|
||||
DateTime result;
|
||||
|
||||
result = JsonConvert.DeserializeObject<DateTime>("new Date(2000, 11)", converter);
|
||||
Assert.AreEqual(new DateTime(2000, 12, 1, 0, 0, 0, 0, DateTimeKind.Utc), result);
|
||||
|
||||
result = JsonConvert.DeserializeObject<DateTime>("new Date(2000, 11, 12)", converter);
|
||||
Assert.AreEqual(new DateTime(2000, 12, 12, 0, 0, 0, 0, DateTimeKind.Utc), result);
|
||||
|
||||
result = JsonConvert.DeserializeObject<DateTime>("new Date(2000, 11, 12, 20)", converter);
|
||||
Assert.AreEqual(new DateTime(2000, 12, 12, 20, 0, 0, 0, DateTimeKind.Utc), result);
|
||||
|
||||
result = JsonConvert.DeserializeObject<DateTime>("new Date(2000, 11, 12, 20, 1)", converter);
|
||||
Assert.AreEqual(new DateTime(2000, 12, 12, 20, 1, 0, 0, DateTimeKind.Utc), result);
|
||||
|
||||
result = JsonConvert.DeserializeObject<DateTime>("new Date(2000, 11, 12, 20, 1, 2)", converter);
|
||||
Assert.AreEqual(new DateTime(2000, 12, 12, 20, 1, 2, 0, DateTimeKind.Utc), result);
|
||||
|
||||
result = JsonConvert.DeserializeObject<DateTime>("new Date(2000, 11, 12, 20, 1, 2, 3)", converter);
|
||||
Assert.AreEqual(new DateTime(2000, 12, 12, 20, 1, 2, 3, DateTimeKind.Utc), result);
|
||||
|
||||
result = JsonConvert.DeserializeObject<DateTime>("new Date(2000, 11, 1, 0, 0, 0, 0)", converter);
|
||||
Assert.AreEqual(new DateTime(2000, 12, 1, 0, 0, 0, 0, DateTimeKind.Utc), result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeDateTime_TooManyArguments()
|
||||
{
|
||||
JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(() =>
|
||||
{
|
||||
JsonConvert.DeserializeObject<DateTime>("new Date(1, 2, 3, 4, 5, 6, 7, 8)", converter);
|
||||
}, "Unexpected number of arguments when reading date constructor. Path '', line 1, position 32.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeDateTime_NoArguments()
|
||||
{
|
||||
JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(() =>
|
||||
{
|
||||
JsonConvert.DeserializeObject<DateTime>("new Date()", converter);
|
||||
}, "Date constructor has no arguments. Path '', line 1, position 10.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeDateTime_NotArgumentsNotClosed()
|
||||
{
|
||||
JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(() =>
|
||||
{
|
||||
JsonConvert.DeserializeObject<DateTime>("new Date(", converter);
|
||||
}, "Unexpected end when reading date constructor. Path '', line 1, position 9.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeDateTime_NotClosed()
|
||||
{
|
||||
JavaScriptDateTimeConverter converter = new JavaScriptDateTimeConverter();
|
||||
|
||||
ExceptionAssert.Throws<JsonSerializationException>(() =>
|
||||
{
|
||||
JsonConvert.DeserializeObject<DateTime>("new Date(2, 3", converter);
|
||||
}, "Unexpected end when reading date constructor. Path '[1]', line 1, position 13.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConverterList()
|
||||
{
|
||||
|
||||
@@ -91,22 +91,9 @@ namespace Newtonsoft.Json.Converters
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
|
||||
}
|
||||
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType != JsonToken.Integer)
|
||||
if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime d, out string errorMessage))
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
}
|
||||
|
||||
long ticks = (long)reader.Value;
|
||||
|
||||
DateTime d = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
|
||||
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType != JsonToken.EndConstructor)
|
||||
{
|
||||
throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected EndConstructor, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
|
||||
throw JsonSerializationException.Create(reader, errorMessage);
|
||||
}
|
||||
|
||||
#if HAVE_DATE_TIME_OFFSET
|
||||
|
||||
@@ -696,32 +696,12 @@ namespace Newtonsoft.Json
|
||||
|
||||
private void WriteConstructorDate(JsonReader reader)
|
||||
{
|
||||
List<long> DateParams = new List<long>();
|
||||
while (true)
|
||||
if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string errorMessage))
|
||||
{
|
||||
if (!reader.Read())
|
||||
throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null);
|
||||
if (reader.TokenType == JsonToken.EndConstructor)
|
||||
break;
|
||||
if (reader.TokenType != JsonToken.Integer)
|
||||
throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null);
|
||||
DateParams.Add((long)reader.Value);
|
||||
if (DateParams.Count > 7)
|
||||
throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Wrong number of arguments", null);
|
||||
throw JsonWriterException.Create(this, errorMessage, null);
|
||||
}
|
||||
DateTime date;
|
||||
if (DateParams.Count == 1)
|
||||
{
|
||||
date = DateTimeUtils.ConvertJavaScriptTicksToDateTime(DateParams[0]);
|
||||
}
|
||||
else if (DateParams.Count == 7) //Add support: new Date(2018,5,26,11,14,31,36)
|
||||
{
|
||||
date = new DateTime((int)DateParams[0], (int)DateParams[1] + 1, (int)DateParams[2], (int)DateParams[3],
|
||||
(int)DateParams[4], (int)DateParams[5], (int)DateParams[6]);
|
||||
}
|
||||
else
|
||||
throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Wrong number of arguments", null);
|
||||
WriteValue(date);
|
||||
|
||||
WriteValue(dateTime);
|
||||
}
|
||||
|
||||
private void WriteEnd(JsonContainerType type)
|
||||
|
||||
@@ -564,5 +564,90 @@ namespace Newtonsoft.Json.Utilities
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime dateTime, out string errorMessage)
|
||||
{
|
||||
dateTime = default(DateTime);
|
||||
errorMessage = null;
|
||||
|
||||
if (!TryGetDateConstructorValue(reader, out long? t1, out errorMessage) || t1 == null)
|
||||
{
|
||||
errorMessage = errorMessage ?? "Date constructor has no arguments.";
|
||||
return false;
|
||||
}
|
||||
if (!TryGetDateConstructorValue(reader, out long? t2, out errorMessage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (t2 != null)
|
||||
{
|
||||
// Only create a list when there is more than one argument
|
||||
List<long> dateArgs = new List<long>
|
||||
{
|
||||
t1.Value,
|
||||
t2.Value
|
||||
};
|
||||
while (true)
|
||||
{
|
||||
if (!TryGetDateConstructorValue(reader, out long? integer, out errorMessage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (integer != null)
|
||||
{
|
||||
dateArgs.Add(integer.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dateArgs.Count > 7)
|
||||
{
|
||||
errorMessage = "Unexpected number of arguments when reading date constructor.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pad args out to the number used by the ctor
|
||||
while (dateArgs.Count < 7)
|
||||
{
|
||||
dateArgs.Add(0);
|
||||
}
|
||||
|
||||
dateTime = new DateTime((int)dateArgs[0], (int)dateArgs[1] + 1, dateArgs[2] == 0 ? 1 : (int)dateArgs[2],
|
||||
(int)dateArgs[3], (int)dateArgs[4], (int)dateArgs[5], (int)dateArgs[6]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(t1.Value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, out string errorMessage)
|
||||
{
|
||||
integer = null;
|
||||
errorMessage = null;
|
||||
|
||||
if (!reader.Read())
|
||||
{
|
||||
errorMessage = "Unexpected end when reading date constructor.";
|
||||
return false;
|
||||
}
|
||||
if (reader.TokenType == JsonToken.EndConstructor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (reader.TokenType != JsonToken.Integer)
|
||||
{
|
||||
errorMessage = "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType;
|
||||
return false;
|
||||
}
|
||||
|
||||
integer = (long)reader.Value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user