Let's understand that DateTimeOffset gives you UTC in addition to how different this value is from UTC. Thus, a value always uniquely identifies one point in time. This is very valuable information that you might not want to lose. But if due to requirements you have to keep only the offset, then continue reading below.
Since you have the flexibility to change the DateTimeOffset type to a string, perhaps you can change the type a bit and use DateTimeOffset.
For instance,
using System; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; using Newtonsoft.Json; namespace ConsoleApplication8 { public struct Iso8601SerializableDateTimeOffset : IXmlSerializable { public 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")); } } public class Foo { public Guid Id { get; set; } [JsonConverter(typeof(UtcDateTimeOffsetConverter))] public Iso8601SerializableDateTimeOffset AcquireDate { get; set; } } class Program { static void Main(string[] args) { var foo = new Foo { Id = Guid.NewGuid(), AcquireDate = DateTimeOffset.Now }; var xmlSerializer = new System.Xml.Serialization.XmlSerializer(foo.GetType()); xmlSerializer.Serialize(Console.Out, foo); Console.WriteLine(); Console.ReadLine(); } } }
Output
<?xml version="1.0" encoding="IBM437"?> <Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Id>830cabe2-340b-42c6-bad4-12b5b8b1c43f</Id> <AcquireDate>2016-03-14T10:47:51.8162249-04:00</AcquireDate> </Foo>
For JSON, we need a converter, but we can reuse Newtonsoft.Json.Converters.IsoDateTimeConverter
public class UtcDateTimeOffsetConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value is Iso8601SerializableDateTimeOffset) { var date = (Iso8601SerializableDateTimeOffset)value; value = date.value; } base.WriteJson(writer, value, serializer); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { object value = base.ReadJson(reader, objectType, existingValue, serializer); if (value is Iso8601SerializableDateTimeOffset) { var date = (Iso8601SerializableDateTimeOffset)value; value = date.value; } return value; } }
Controller
public class ValuesController : ApiController { public class Foo { public Guid Id { get; set; } [JsonConverter(typeof(UtcDateTimeOffsetConverter))] public Iso8601SerializableDateTimeOffset AcquireDate { get; set; } }
Output
<ArrayOfFoo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebApplication1.Models"> <Foo> <AcquireDate>2016-03-14T12:04:30.2791167-04:00</AcquireDate> <Id>b3188528-f854-454a-bf9f-9822ff27dc6f</Id> </Foo> </ArrayOfFoo>
Json
[{"Id":"e24bc769-3463-4320-b39a-9ff97e709142","AcquireDate":"2016-03-15T10:47:29.3061449-04:00"}]
A full example can be found on github: https://github.com/alexnolasco/DatetimeOffsetXMLSerializationExample
See also: How can I serialize the XML property of a DateTimeOffset?
Choose between DateTime, DateTimeOffset, TimeSpan and TimeZoneInfo