强制 XmlSerializer 将 DateTime 序列化为‘ YYYY-MM-DD hh: mm: ss’

我有一个针对某些 RESTful 服务的 XSD 模式。当与 xsd.exe工具一起使用来生成 C # 代码时,XSD 的 xs:date会生成以下代码:

[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="date")]
public System.DateTime time {
get {
return this.timeField;
}
set {
this.timeField = value;
}
}

当使用 XmlSerializer将 XML 反序列化到对象时,一切似乎都很顺利。我面临的问题是,服务期望日期格式化为 YYYY-MM-DD hh:mm:ss,而 XSD 生成的代码似乎只生成 YYYY-MM-DD

如果我手动将 XSD 修改为 xs:dateTime类型,生成的 C # 代码将生成: 2010-08-20T20:07:03.915039Z

基本上,如何强制序列化生成 YYYY-MM-DD hh:mm:ss?有什么事情可以对 XSD 做,或者有什么事情我可以做来改变生成的 C # 代码?

110172 次浏览

In the past, I've done the following to control datetime serialization:

  • Ignore the DateTime property.
  • Create a dummy string property that serializes/deserializes the way I want

Here is an example:

public class SomeClass
{
[XmlIgnore]
public DateTime SomeDate { get; set; }


[XmlElement("SomeDate")]
public string SomeDateString
{
get { return this.SomeDate.ToString("yyyy-MM-dd HH:mm:ss"); }
set { this.SomeDate = DateTime.Parse(value); }
}
}

I believe implementing IXmlSerializable interface will do a trick. You can then control how you serialize and deserialize your object.

Use [XmlElement(DataType = "date")] attribute to format your DateTime property value as you need.

From MSDN:

Note:
The attribute that annotates the publicationdate field has a DataType property. There is no type in the .NET Framework that matches the type xs:date completely. The closest match is System.DateTime, which stores date and time data. Specifying the DataType property as a "date" ensures that the XmlSerializer will only serialize the date part of the DateTime object.

If you only need to clear out the millisecond part. Refer to:

How to truncate milliseconds off of a .NET DateTime

And basicly do something like:

  startDateTimeToUse = startDateTimeToUse.AddTicks(-(startDateTimeToUse.Ticks % TimeSpan.TicksPerSecond));
endDate = endDate.AddTicks(-(endDate.Ticks % TimeSpan.TicksPerSecond));

I can confirm that this serializes to:

            <startDate>2015-10-31T12:13:04</startDate>
<endDate>2016-11-10T12:13:06</endDate>

I must also state that Before clearing the milliseconds I'm doing this:

            var startDateTimeToUse = ssStartDateTime.ToUniversalTime();
var endDate = DateTime.Now.ToUniversalTime();
startDateTimeToUse = DateTime.SpecifyKind(startDateTimeToUse, DateTimeKind.Unspecified);
endDate = DateTime.SpecifyKind(endDate, DateTimeKind.Unspecified);

Which I don't know if it's having any effect on the serialization or not at this point

see answers above but to add-- if you only wanted output when the value is non-null (e.g. XML maxOccurs=0) you can utilize something like this:

private System.DateTime? someDateField;


public string someDate
{
get
{
return someDateField?.ToString("MM-dd-yyyy");
}
set
{
dobField = System.DateTime.Parse(value);
}
}

I may have another option. When setting your DateTime just subtract the number of ticks of everything after the seconds, like:

    public DateTime Dt
{
get => _dt;
set
{
_dt = value;
long elapsedTicks = _dt.Ticks - new DateTime(_dt.Year, _dt.Month, _dt.Day, _dt.Hour, _dt.Minute, _dt.Second).Ticks;
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
_dt = _dt.Subtract(elapsedSpan);
}
}
private DateTime _dt = default(DateTime);

That way when you serialize your DateTime (Dt) the milliseconds won't be used and you'll have a value hh:mm:ss, that is at least what it gave me. That way no need to modify anything inside your XML definition.