Comprendiamo che DateTimeOffset ti offre l'ora UTC oltre a quanto tale valore differisce da UTC. Pertanto, il valore identifica sempre univocamente un singolo punto nel tempo. Questa è un'informazione molto preziosa che potresti non voler perdere. Ma se a causa dei requisiti è necessario memorizzare solo l'offset, quindi continua a leggere la soluzione di seguito.
Poiché è possibile modificare il tipo da DateTimeOffset a una stringa, è possibile modificare il tipo un po 'e utilizzare ancora DateTimeOffset.
Per esempio,
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();
}
}
}
uscita
<?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>
Per JSON, abbiamo bisogno di un convertitore, ma siamo in grado di riutilizzare 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;
}
}
Il controller
public class ValuesController : ApiController
{
public class Foo
{
public Guid Id { get; set; }
[JsonConverter(typeof(UtcDateTimeOffsetConverter))]
public Iso8601SerializableDateTimeOffset AcquireDate { get; set; }
}
// GET api/values
public IEnumerable<Foo> Get()
{
return new Foo[] {
new Foo() {
Id = Guid.NewGuid(),
AcquireDate = DateTimeOffset.Now
}
};
}
}
uscita
<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"}]
esempio completi sono disponibili all'indirizzo github: https://github.com/alexnolasco/DatetimeOffsetXMLSerializationExample
Consulta anche: How can I XML Serialize a DateTimeOffset Property?
Choosing Between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo
Come dovrei usarlo con API Web? Qualsiasi esempio sarebbe utile. –
@NileshThakkar Aggiunto un metodo APIController di esempio alla risposta, vedere se questo aiuta. –
Dobbiamo apportare modifiche alla configurazione per farlo funzionare per le API Web? Poiché l'API Web per impostazione predefinita utilizza DataContractSerializer per XMLMediaTypeFormatter. –