Force XmlSerializer to serialize DateTime as 'YYYY-MM-DD hh:mm:ss'

C#.NetXml Serialization

C# Problem Overview


I have a XSD schema for some RESTful service. When used in conjunction with xsd.exe tool to generate C# code, XSD's xs:date generates the following code:

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

When deserializing XML to objects using XmlSerializer all seems to be well. The problem I am facing is that the service expects dates to be formatted as YYYY-MM-DD hh:mm:ss and the XSD generated code seems to produce only YYYY-MM-DD.

If I modify XSD manually to xs:dateTime type, the generated C# code produces: 2010-08-20T20:07:03.915039Z.

Basically, how do I force serialization to produce YYYY-MM-DD hh:mm:ss? Is there something to do to XSD or is there something I can do to alter generated C# code?

C# Solutions


Solution 1 - C#

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); }
    }
}

Solution 2 - C#

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.

Solution 3 - C#

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

https://stackoverflow.com/questions/1004698/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

Solution 4 - C#

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

Solution 5 - C#

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);
    }
}

Solution 6 - C#

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwpfwannabeView Question on Stackoverflow
Solution 1 - C#kbrimingtonView Answer on Stackoverflow
Solution 2 - C#Bill GatesView Answer on Stackoverflow
Solution 3 - C#João AntunesView Answer on Stackoverflow
Solution 4 - C#EricView Answer on Stackoverflow
Solution 5 - C#BrianView Answer on Stackoverflow
Solution 6 - C#philippeView Answer on Stackoverflow