How can I XML Serialize a DateTimeOffset Property?
Solution 1:
It's a few years late, but here's the quick and easy way to completely serialize DateTimeOffset
using ISO 8601:
[XmlElement("lastUpdatedTime")]
public string lastUpdatedTimeForXml // format: 2011-11-11T15:05:46.4733406+01:00
{
get { return lastUpdatedTime.ToString("o"); } // o = yyyy-MM-ddTHH:mm:ss.fffffffzzz
set { lastUpdatedTime = DateTimeOffset.Parse(value); }
}
[XmlIgnore]
public DateTimeOffset lastUpdatedTime;
Solution 2:
I came up with this struct which implements XML serialization based on ISO 8601 formatting (e.g. 2011-11-11T15:05:46.4733406+01:00
). Hint: Trying to parse a DateTime
value such as 2011-11-11T15:05:46
fails as expected.
Feedback welcome. I didn't include the unit tests here because that would be too much text.
/// <remarks>
/// The default value is <c>DateTimeOffset.MinValue</c>. This is a value
/// type and has the same hash code as <c>DateTimeOffset</c>! Implicit
/// assignment from <c>DateTime</c> is neither implemented nor desirable!
/// </remarks>
public struct Iso8601SerializableDateTimeOffset : IXmlSerializable
{
private DateTimeOffset value;
public Iso8601SerializableDateTimeOffset(DateTimeOffset value)
{
this.value = value;
}
public static implicit operator Iso8601SerializableDateTimeOffset(DateTimeOffset value)
{
return new Iso8601SerializableDateTimeOffset(value);
}
public static implicit operator DateTimeOffset(Iso8601SerializableDateTimeOffset instance)
{
return instance.value;
}
public static bool operator ==(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value == b.value;
}
public static bool operator !=(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value != b.value;
}
public static bool operator <(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value < b.value;
}
public static bool operator >(Iso8601SerializableDateTimeOffset a, Iso8601SerializableDateTimeOffset b)
{
return a.value > b.value;
}
public override bool Equals(object o)
{
if(o is Iso8601SerializableDateTimeOffset)
return value.Equals(((Iso8601SerializableDateTimeOffset)o).value);
else if(o is DateTimeOffset)
return value.Equals((DateTimeOffset)o);
else
return false;
}
public override int GetHashCode()
{
return value.GetHashCode();
}
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
var text = reader.ReadElementString();
value = DateTimeOffset.ParseExact(text, format: "o", formatProvider: null);
}
public override string ToString()
{
return value.ToString(format: "o");
}
public string ToString(string format)
{
return value.ToString(format);
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(value.ToString(format: "o"));
}
}
Solution 3:
I'm also unsure of the best way, but here is what I did:
[XmlElement("lastUpdatedTime")]
public string lastUpdatedTimeForXml
{
get { return lastUpdatedTime.ToString(); }
set { lastUpdatedTime = DateTimeOffset.Parse(value); }
}
[XmlIgnore]
public DateTimeOffset lastUpdatedTime;
Solution 4:
I have found the solution here: http://tneustaedter.blogspot.com/2012/02/proper-way-to-serialize-and-deserialize.html
Replacing XmlSerializer with DataContractSerializer works awesome. See sample code below:
public static string XmlSerialize(this object input)
{
using (MemoryStream stream = new MemoryStream())
{
DataContractSerializer serializer = new DataContractSerializer(input.GetType());
serializer.WriteObject(stream, input);
return new UTF8Encoding().GetString(stream.ToArray());
}
}
public static T XmlDeserialize<T>(this string input)
{
using (MemoryStream memoryStream = new MemoryStream(new UTF8Encoding().GetBytes(input)))
{
DataContractSerializer serializer = new DataContractSerializer(typeof(T));
return (T)serializer.ReadObject(memoryStream);
}
}