diff options
author | JamesNK <james@newtonking.com> | 2010-09-12 07:39:39 +0400 |
---|---|---|
committer | JamesNK <james@newtonking.com> | 2010-09-12 07:39:39 +0400 |
commit | 235770442ac9d8ee3bcf3428c5202dde431cecca (patch) | |
tree | 2cfe53fafa430bc2cb9cdf70d133a0e7e78c6043 /Src/Newtonsoft.Json | |
parent | 11ce71ee8b72a0892cbfdfa22d5343e0dffa7fa8 (diff) |
-Added JsonReader.ReadAsDateTimeOffset
-Fixed losing timezone information when deserializing DateTimeOffsets
Diffstat (limited to 'Src/Newtonsoft.Json')
-rw-r--r-- | Src/Newtonsoft.Json/Bson/BsonReader.cs | 17 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/JsonReader.cs | 8 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/JsonTextReader.cs | 77 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/JsonValidatingReader.cs | 14 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Linq/JTokenReader.cs | 16 | ||||
-rw-r--r-- | Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs | 12 |
6 files changed, 130 insertions, 14 deletions
diff --git a/Src/Newtonsoft.Json/Bson/BsonReader.cs b/Src/Newtonsoft.Json/Bson/BsonReader.cs index 4b94357..8db767a 100644 --- a/Src/Newtonsoft.Json/Bson/BsonReader.cs +++ b/Src/Newtonsoft.Json/Bson/BsonReader.cs @@ -150,6 +150,23 @@ namespace Newtonsoft.Json.Bson return (byte[])Value;
}
+#if !NET20
+ /// <summary>
+ /// Reads the next JSON token from the stream as a <see cref="DateTimeOffset"/>.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="DateTimeOffset"/>.
+ /// </returns>
+ public override DateTimeOffset ReadAsDateTimeOffset()
+ {
+ Read();
+ if (TokenType != JsonToken.Date)
+ throw new JsonReaderException("Error reading date. Expected bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
+
+ return new DateTimeOffset((DateTime)Value);
+ }
+#endif
+
/// <summary>
/// Reads the next JSON token from the stream.
/// </summary>
diff --git a/Src/Newtonsoft.Json/JsonReader.cs b/Src/Newtonsoft.Json/JsonReader.cs index d516578..2ec2883 100644 --- a/Src/Newtonsoft.Json/JsonReader.cs +++ b/Src/Newtonsoft.Json/JsonReader.cs @@ -210,6 +210,14 @@ namespace Newtonsoft.Json /// <returns>A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.</returns>
public abstract byte[] ReadAsBytes();
+#if !NET20
+ /// <summary>
+ /// Reads the next JSON token from the stream as a <see cref="DateTimeOffset"/>.
+ /// </summary>
+ /// <returns>A <see cref="DateTimeOffset"/>.</returns>
+ public abstract DateTimeOffset ReadAsDateTimeOffset();
+#endif
+
/// <summary>
/// Skips the children of the current token.
/// </summary>
diff --git a/Src/Newtonsoft.Json/JsonTextReader.cs b/Src/Newtonsoft.Json/JsonTextReader.cs index 9121732..7b45688 100644 --- a/Src/Newtonsoft.Json/JsonTextReader.cs +++ b/Src/Newtonsoft.Json/JsonTextReader.cs @@ -41,7 +41,10 @@ namespace Newtonsoft.Json private enum ReadType
{
Read,
- ReadAsBytes
+ ReadAsBytes,
+#if !NET20
+ ReadAsDateTimeOffset
+#endif
}
private readonly TextReader _reader;
@@ -190,6 +193,22 @@ namespace Newtonsoft.Json return new JsonReaderException(message, null, _currentLineNumber, _currentLinePosition);
}
+ private TimeSpan ReadOffset(string offsetText)
+ {
+ bool negative = (offsetText[0] == '-');
+
+ int hours = int.Parse(offsetText.Substring(1, 2), NumberStyles.Integer, CultureInfo.InvariantCulture);
+ int minutes = 0;
+ if (offsetText.Length >= 5)
+ minutes = int.Parse(offsetText.Substring(3, 2), NumberStyles.Integer, CultureInfo.InvariantCulture);
+
+ TimeSpan offset = TimeSpan.FromHours(hours) + TimeSpan.FromMinutes(minutes);
+ if (negative)
+ offset = offset.Negate();
+
+ return offset;
+ }
+
private void ParseDate(string text)
{
string value = text.Substring(6, text.Length - 8);
@@ -200,30 +219,44 @@ namespace Newtonsoft.Json if (index == -1)
index = value.IndexOf('-', 1);
+ TimeSpan offset = TimeSpan.Zero;
+
if (index != -1)
{
kind = DateTimeKind.Local;
+ offset = ReadOffset(value.Substring(index));
value = value.Substring(0, index);
}
long javaScriptTicks = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
+
DateTime utcDateTime = JsonConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
- DateTime dateTime;
- switch (kind)
+#if !NET20
+ if (_readType == ReadType.ReadAsDateTimeOffset)
{
- case DateTimeKind.Unspecified:
- dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
- break;
- case DateTimeKind.Local:
- dateTime = utcDateTime.ToLocalTime();
- break;
- default:
- dateTime = utcDateTime;
- break;
+ SetToken(JsonToken.Date, new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset));
}
+ else
+#endif
+ {
+ DateTime dateTime;
- SetToken(JsonToken.Date, dateTime);
+ switch (kind)
+ {
+ case DateTimeKind.Unspecified:
+ dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
+ break;
+ case DateTimeKind.Local:
+ dateTime = utcDateTime.ToLocalTime();
+ break;
+ default:
+ dateTime = utcDateTime;
+ break;
+ }
+
+ SetToken(JsonToken.Date, dateTime);
+ }
}
private const int LineFeedValue = StringUtils.LineFeed;
@@ -299,6 +332,24 @@ namespace Newtonsoft.Json throw CreateJsonReaderException("Unexpected token when reading bytes: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition);
}
+#if !NET20
+ /// <summary>
+ /// Reads the next JSON token from the stream as a <see cref="DateTimeOffset"/>.
+ /// </summary>
+ /// <returns>A <see cref="DateTimeOffset"/>.</returns>
+ public override DateTimeOffset ReadAsDateTimeOffset()
+ {
+ _readType = ReadType.ReadAsDateTimeOffset;
+ if (!ReadInternal())
+ throw CreateJsonReaderException("Unexpected end when reading date: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
+
+ if (TokenType == JsonToken.Date)
+ return (DateTimeOffset)Value;
+
+ throw CreateJsonReaderException("Unexpected token when reading date: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition);
+ }
+#endif
+
private bool ReadInternal()
{
while (true)
diff --git a/Src/Newtonsoft.Json/JsonValidatingReader.cs b/Src/Newtonsoft.Json/JsonValidatingReader.cs index 4a46a90..b90abc6 100644 --- a/Src/Newtonsoft.Json/JsonValidatingReader.cs +++ b/Src/Newtonsoft.Json/JsonValidatingReader.cs @@ -318,6 +318,20 @@ namespace Newtonsoft.Json return data;
}
+#if !NET20
+ /// <summary>
+ /// Reads the next JSON token from the stream as a <see cref="DateTimeOffset"/>.
+ /// </summary>
+ /// <returns>A <see cref="DateTimeOffset"/>.</returns>
+ public override DateTimeOffset ReadAsDateTimeOffset()
+ {
+ DateTimeOffset dateTimeOffset = _reader.ReadAsDateTimeOffset();
+
+ ValidateCurrentToken();
+ return dateTimeOffset;
+ }
+#endif
+
/// <summary>
/// Reads the next JSON token from the stream.
/// </summary>
diff --git a/Src/Newtonsoft.Json/Linq/JTokenReader.cs b/Src/Newtonsoft.Json/Linq/JTokenReader.cs index b09037d..7bd68fe 100644 --- a/Src/Newtonsoft.Json/Linq/JTokenReader.cs +++ b/Src/Newtonsoft.Json/Linq/JTokenReader.cs @@ -54,6 +54,22 @@ namespace Newtonsoft.Json.Linq throw new JsonReaderException("Error reading bytes. Expected bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}
+#if !NET20
+ /// <summary>
+ /// Reads the next JSON token from the stream as a <see cref="DateTimeOffset"/>.
+ /// </summary>
+ /// <returns>A <see cref="DateTimeOffset"/>.</returns>
+ public override DateTimeOffset ReadAsDateTimeOffset()
+ {
+ Read();
+
+ if (TokenType == JsonToken.Date)
+ return new DateTimeOffset((DateTime)Value);
+
+ throw new JsonReaderException("Error reading date. Expected bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
+ }
+#endif
+
/// <summary>
/// Reads the next JSON token from the stream.
/// </summary>
diff --git a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index 4ca5afb..2ab3295 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -928,10 +928,20 @@ namespace Newtonsoft.Json.Serialization continue;
}
- if (property.PropertyType == typeof(byte[]))
+ // don't read properties with converters as a specific value
+ // the value might be a string which will then get converted which will error if read as date for example
+ bool hasConverter = (GetConverter(GetContractSafe(property.PropertyType), property.Converter) != null);
+
+ if (property.PropertyType == typeof(byte[]) && !hasConverter)
{
reader.ReadAsBytes();
}
+#if !NET20
+ else if (property.PropertyType == typeof(DateTimeOffset) && !hasConverter)
+ {
+ reader.ReadAsDateTimeOffset();
+ }
+#endif
else
{
if (!reader.Read())
|