diff --git a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs index 15aacda4..5ee894a8 100644 --- a/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs +++ b/Src/Newtonsoft.Json.Tests/Converters/IsoDateTimeConverterTests.cs @@ -36,6 +36,26 @@ namespace Newtonsoft.Json.Tests.Converters { public class IsoDateTimeConverterTests : TestFixtureBase { + [Test] + public void PropertiesShouldBeSet() + { + IsoDateTimeConverter converter = new IsoDateTimeConverter(); + Assert.AreEqual(CultureInfo.CurrentCulture, converter.Culture); + Assert.AreEqual(string.Empty, converter.DateTimeFormat); + Assert.AreEqual(DateTimeStyles.RoundtripKind, converter.DateTimeStyles); + + converter = new IsoDateTimeConverter() + { + DateTimeFormat = "F", + Culture = CultureInfo.InvariantCulture, + DateTimeStyles = DateTimeStyles.None + }; + + Assert.AreEqual(CultureInfo.InvariantCulture, converter.Culture); + Assert.AreEqual("F", converter.DateTimeFormat); + Assert.AreEqual(DateTimeStyles.None, converter.DateTimeStyles); + } + [Test] public void SerializeDateTime() { @@ -55,9 +75,9 @@ namespace Newtonsoft.Json.Tests.Converters } [Test] - public void SerializeFormattedDateTime() + public void SerializeFormattedDateTimeInvariantCulture() { - IsoDateTimeConverter converter = new IsoDateTimeConverter() { DateTimeFormat = "F" }; + IsoDateTimeConverter converter = new IsoDateTimeConverter() { DateTimeFormat = "F", Culture = CultureInfo.InvariantCulture }; DateTime d = new DateTime(2000, 12, 15, 22, 11, 3, 0, DateTimeKind.Utc); string result; @@ -72,6 +92,54 @@ namespace Newtonsoft.Json.Tests.Converters Assert.AreEqual(@"""Friday, 15 December 2000 22:11:03""", result); } + [Test] + public void SerializeCustomFormattedDateTime() + { + IsoDateTimeConverter converter = new IsoDateTimeConverter() { DateTimeFormat = "dd/MM/yyyy" }; + + string json = @"""09/12/2006"""; + + DateTime d = JavaScriptConvert.DeserializeObject(json, converter); + + Assert.AreEqual(9, d.Day); + Assert.AreEqual(12, d.Month); + Assert.AreEqual(2006, d.Year); + } + +#if !SILVERLIGHT + [Test] + public void SerializeFormattedDateTimeNewZealandCulture() + { + IsoDateTimeConverter converter = new IsoDateTimeConverter() { DateTimeFormat = "F", Culture = CultureInfo.GetCultureInfo("en-NZ") }; + + DateTime d = new DateTime(2000, 12, 15, 22, 11, 3, 0, DateTimeKind.Utc); + string result; + + result = JavaScriptConvert.SerializeObject(d, converter); + Assert.AreEqual(@"""Friday, 15 December 2000 10:11:03 p.m.""", result); + + Assert.AreEqual(d, JavaScriptConvert.DeserializeObject(result, converter)); + + d = new DateTime(2000, 12, 15, 22, 11, 3, 0, DateTimeKind.Local); + result = JavaScriptConvert.SerializeObject(d, converter); + Assert.AreEqual(@"""Friday, 15 December 2000 10:11:03 p.m.""", result); + } + + [Test] + public void SerializeDateTimeCulture() + { + IsoDateTimeConverter converter = new IsoDateTimeConverter() { Culture = CultureInfo.GetCultureInfo("en-NZ") }; + + string json = @"""09/12/2006"""; + + DateTime d = JavaScriptConvert.DeserializeObject(json, converter); + + Assert.AreEqual(9, d.Day); + Assert.AreEqual(12, d.Month); + Assert.AreEqual(2006, d.Year); + } +#endif + [Test] public void SerializeDateTimeOffset() { @@ -91,33 +159,37 @@ namespace Newtonsoft.Json.Tests.Converters { DateTimeTestClass c = new DateTimeTestClass(); c.DateTimeField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(); + c.DateTimeOffsetField = new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(); c.PreField = "Pre"; c.PostField = "Post"; string json = JavaScriptConvert.SerializeObject(c, new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal }); - Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""2008-12-12T12:12:12.0000000Z"",""PostField"":""Post""}", json); + Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""2008-12-12T12:12:12.0000000Z"",""DateTimeOffsetField"":""2008-12-12T12:12:12.0000000+00:00"",""PostField"":""Post""}", json); //test the other edge case too c.DateTimeField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime(); + c.DateTimeOffsetField = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime(); c.PreField = "Pre"; c.PostField = "Post"; json = JavaScriptConvert.SerializeObject(c, new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal }); - Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""2008-01-01T01:01:01.0000000Z"",""PostField"":""Post""}", json); + Assert.AreEqual(@"{""PreField"":""Pre"",""DateTimeField"":""2008-01-01T01:01:01.0000000Z"",""DateTimeOffsetField"":""2008-01-01T01:01:01.0000000+00:00"",""PostField"":""Post""}", json); } [Test] public void DeserializeUTC() { DateTimeTestClass c = - JavaScriptConvert.DeserializeObject(@"{""PreField"":""Pre"",""DateTimeField"":""2008-12-12T12:12:12Z"",""PostField"":""Post""}", new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal }); + JavaScriptConvert.DeserializeObject(@"{""PreField"":""Pre"",""DateTimeField"":""2008-12-12T12:12:12Z"",""DateTimeOffsetField"":""2008-12-12T12:12:12Z"",""PostField"":""Post""}", new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal }); Assert.AreEqual(new DateTime(2008, 12, 12, 12, 12, 12, 0, DateTimeKind.Utc).ToLocalTime(), c.DateTimeField); + Assert.AreEqual(new DateTimeOffset(2008, 12, 12, 12, 12, 12, 0, TimeSpan.Zero), c.DateTimeOffsetField); Assert.AreEqual("Pre", c.PreField); Assert.AreEqual("Post", c.PostField); DateTimeTestClass c2 = - JavaScriptConvert.DeserializeObject(@"{""PreField"":""Pre"",""DateTimeField"":""2008-01-01T01:01:01Z"",""PostField"":""Post""}", new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal }); + JavaScriptConvert.DeserializeObject(@"{""PreField"":""Pre"",""DateTimeField"":""2008-01-01T01:01:01Z"",""DateTimeOffsetField"":""2008-01-01T01:01:01Z"",""PostField"":""Post""}", new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AssumeUniversal }); Assert.AreEqual(new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc).ToLocalTime(), c2.DateTimeField); + Assert.AreEqual(new DateTimeOffset(2008, 1, 1, 1, 1, 1, 0, TimeSpan.Zero), c2.DateTimeOffsetField); Assert.AreEqual("Pre", c2.PreField); Assert.AreEqual("Post", c2.PostField); } diff --git a/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs b/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs index 1cf57929..ad79bd7e 100644 --- a/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs +++ b/Src/Newtonsoft.Json.Tests/DateTimeTestClass.cs @@ -34,6 +34,7 @@ namespace Newtonsoft.Json.Tests { public string PreField { get; set; } public DateTime DateTimeField { get; set; } + public DateTimeOffset DateTimeOffsetField { get; set; } public string PostField { get; set; } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs index 6e3c7eee..fe9f7526 100644 --- a/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs +++ b/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs @@ -15,7 +15,8 @@ namespace Newtonsoft.Json.Converters private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK"; private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; - private string _dateTimeFormat = DefaultDateTimeFormat; + private string _dateTimeFormat; + private CultureInfo _culture; /// /// Gets or sets the date time styles used when converting a date to and from JSON. @@ -28,13 +29,23 @@ namespace Newtonsoft.Json.Converters } /// - /// Gets or sets the date time format used when converting a date to and fromm JSON. + /// Gets or sets the date time format used when converting a date to and from JSON. /// /// The date time format used when converting a date to and from JSON. public string DateTimeFormat { - get { return _dateTimeFormat; } - set { _dateTimeFormat = value; } + get { return _dateTimeFormat ?? string.Empty; } + set { _dateTimeFormat = StringUtils.NullEmptyString(value); } + } + + /// + /// Gets or sets the culture used when converting a date to and from JSON. + /// + /// The culture used when converting a date to and from JSON. + public CultureInfo Culture + { + get { return _culture ?? CultureInfo.CurrentCulture; } + set { _culture = value; } } /// @@ -54,16 +65,20 @@ namespace Newtonsoft.Json.Converters || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) dateTime = dateTime.ToUniversalTime(); - text = dateTime.ToString(_dateTimeFormat, CultureInfo.InvariantCulture); + text = dateTime.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); } - else + else if (value is DateTimeOffset) { DateTimeOffset dateTimeOffset = (DateTimeOffset)value; if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) dateTimeOffset = dateTimeOffset.ToUniversalTime(); - text = dateTimeOffset.ToString(_dateTimeFormat, CultureInfo.InvariantCulture); + text = dateTimeOffset.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); + } + else + { + throw new Exception("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value))); } writer.WriteValue(text); @@ -83,9 +98,17 @@ namespace Newtonsoft.Json.Converters string dateText = reader.Value.ToString(); if (objectType == typeof(DateTimeOffset)) - return DateTimeOffset.Parse(dateText, CultureInfo.InvariantCulture, _dateTimeStyles); + { + if (!string.IsNullOrEmpty(_dateTimeFormat)) + return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); + else + return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles); + } - return DateTime.Parse(dateText, CultureInfo.InvariantCulture, _dateTimeStyles); + if (!string.IsNullOrEmpty(_dateTimeFormat)) + return DateTime.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); + else + return DateTime.Parse(dateText, Culture, _dateTimeStyles); } ///