diff --git a/Src/Newtonsoft.Json.Tests/Utilities/DateTimeUtilsTests.cs b/Src/Newtonsoft.Json.Tests/Utilities/DateTimeUtilsTests.cs
index 6a91d1a1..eb156ea2 100644
--- a/Src/Newtonsoft.Json.Tests/Utilities/DateTimeUtilsTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Utilities/DateTimeUtilsTests.cs
@@ -70,6 +70,32 @@ namespace Newtonsoft.Json.Tests.Utilities
Assert.AreEqual(value, parsedDt);
}
+ [Test]
+ public void Parse24HourDateTime()
+ {
+ DateTime dt;
+ Assert.IsTrue(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:00:00Z"), DateTimeZoneHandling.RoundtripKind, out dt));
+ Assert.AreEqual(new DateTime(2000, 12, 16, 0, 0, 0, DateTimeKind.Utc), dt);
+
+ Assert.IsFalse(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:01:00Z"), DateTimeZoneHandling.RoundtripKind, out dt));
+ Assert.IsFalse(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:00:01Z"), DateTimeZoneHandling.RoundtripKind, out dt));
+ Assert.IsFalse(DateTimeUtils.TryParseDateTimeIso(CreateStringReference("2000-12-15T24:00:00.0000001Z"), DateTimeZoneHandling.RoundtripKind, out dt));
+ }
+
+#if !NET20
+ [Test]
+ public void Parse24HourDateTimeOffset()
+ {
+ DateTimeOffset dt;
+ Assert.IsTrue(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:00:00Z"), out dt));
+ Assert.AreEqual(new DateTimeOffset(2000, 12, 16, 0, 0, 0, TimeSpan.Zero), dt);
+
+ Assert.IsFalse(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:01:00Z"), out dt));
+ Assert.IsFalse(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:00:01Z"), out dt));
+ Assert.IsFalse(DateTimeUtils.TryParseDateTimeOffsetIso(CreateStringReference("2000-12-15T24:00:00.0000001Z"), out dt));
+ }
+#endif
+
[Test]
public void NewDateTimeParse()
{
diff --git a/Src/Newtonsoft.Json/JsonSerializerSettings.cs b/Src/Newtonsoft.Json/JsonSerializerSettings.cs
index 7c0bb65c..cc18cb9e 100644
--- a/Src/Newtonsoft.Json/JsonSerializerSettings.cs
+++ b/Src/Newtonsoft.Json/JsonSerializerSettings.cs
@@ -138,7 +138,7 @@ namespace Newtonsoft.Json
}
///
- /// Gets or sets a collection that will be used during serialization.
+ /// Gets or sets a collection that will be used during serialization.
///
/// The converters.
public IList Converters { get; set; }
diff --git a/Src/Newtonsoft.Json/Utilities/DateTimeParser.cs b/Src/Newtonsoft.Json/Utilities/DateTimeParser.cs
index 0a182694..9addb98e 100644
--- a/Src/Newtonsoft.Json/Utilities/DateTimeParser.cs
+++ b/Src/Newtonsoft.Json/Utilities/DateTimeParser.cs
@@ -123,13 +123,14 @@ namespace Newtonsoft.Json.Utilities
private bool ParseTime(ref int start)
{
if (!(Parse2Digit(start, out Hour)
- && Hour < 24
+ && Hour <= 24
&& ParseChar(start + LzHH, ':')
&& Parse2Digit(start + LzHH_, out Minute)
&& Minute < 60
&& ParseChar(start + LzHH_mm, ':')
&& Parse2Digit(start + LzHH_mm_, out Second)
- && Second < 60))
+ && Second < 60
+ && (Hour != 24 || (Minute == 0 && Second == 0)))) // hour can be 24 if minute/second is zero)
{
return false;
}
@@ -162,6 +163,11 @@ namespace Newtonsoft.Json.Utilities
Fraction *= Power10[MaxFractionDigits - numberOfDigits];
}
+
+ if (Hour == 24 && Fraction != 0)
+ {
+ return false;
+ }
}
return true;
}
diff --git a/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs b/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs
index afe56b35..44e05350 100644
--- a/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs
+++ b/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs
@@ -206,8 +206,7 @@ namespace Newtonsoft.Json.Utilities
return false;
}
- DateTime d = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second);
- d = d.AddTicks(dateTimeParser.Fraction);
+ DateTime d = CreateDateTime(dateTimeParser);
long ticks;
@@ -269,8 +268,7 @@ namespace Newtonsoft.Json.Utilities
return false;
}
- DateTime d = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second);
- d = d.AddTicks(dateTimeParser.Fraction);
+ DateTime d = CreateDateTime(dateTimeParser);
TimeSpan offset;
@@ -302,6 +300,29 @@ namespace Newtonsoft.Json.Utilities
}
#endif
+ private static DateTime CreateDateTime(DateTimeParser dateTimeParser)
+ {
+ bool is24Hour;
+ if (dateTimeParser.Hour == 24)
+ {
+ is24Hour = true;
+ dateTimeParser.Hour = 0;
+ }
+ else
+ {
+ is24Hour = false;
+ }
+
+ DateTime d = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second);
+ d = d.AddTicks(dateTimeParser.Fraction);
+
+ if (is24Hour)
+ {
+ d = d.AddDays(1);
+ }
+ return d;
+ }
+
internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt)
{
if (s.Length > 0)