简体   繁体   中英

Parsing Datetime string to Datetime in Xml Serialization

I am retrieving a datetime string as "2015-07-16T07:40:35Z".

<?xml version="1.0" encoding="UTF-8"?>
<people type="array">
   <person>
      <last-name>lastName</last-name>
      <first-name>firstName</first-name>
      <id type="integer">123</id>
      <last-changed-on type="date">2014-11-21T15:04:53Z</last-changed-on>
   </person>
</people>

I searched about this problem and found something like below.

[XmlIgnore]
public DateTime Start { get; set; }

[XmlElement("start")]
public string StartDateString
{
    get { return this.Start.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'"); }
    set { this.Start = DateTime.Parse(value); }
}

I want to deserialize that XmlElement to a Datetime property of an object. After that when I serialize that object I want to create a datetime string with format of "2015-07-16T07:40:35Z". So how would i change get/set block of properties for this issue.

It looks like the formats you're dealing with are in the standard XML DateTime format. So in this case you don't need a proxy string property to handle it, you can use the built in functionality of the XmlSerializer and specify the dateTime data type on the relevant XmlElement . Update: specifying the dateTime doesn't work if the element is empty (even in combination with isNullable ), here is a way to convert the string manually to a DateTime .

For example..

[XmlRoot("person")]
public class Person
{
    [XmlElement("last-name")]
    public string LastName { get; set; }
    [XmlElement("first-name")]
    public string FirstName { get; set; }
    [XmlElement("id")]
    public int Id { get; set; }
    [XmlElement(ElementName = "last-changed-on")]
    public XmlDateTime LastChangedOn { get; set; }
}

Edit: sounds like you have Xml where LastChangedOn can be empty or missing. In this case you can implement a custom class to handle the conversion and keep the Person class clean. I've added implict conversions so you can just treat the property as if it were a DateTime . Above changes slightly to have XmlDateTime instead of DateTime .

[DebuggerDisplay("{Value}")]
public class XmlDateTime : IXmlSerializable
{
    public DateTime Value { get; set; }
    public bool HasValue { get { return Value != DateTime.MinValue; } }
    private const string XML_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        if (reader.IsEmptyElement)
        {
            reader.ReadStartElement();
            return;
        }

        string someDate = reader.ReadInnerXml();
        if (String.IsNullOrWhiteSpace(someDate) == false)
        {
            Value = XmlConvert.ToDateTime(someDate, XML_DATE_FORMAT);
        }
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        if (Value == DateTime.MinValue)
            return;

        writer.WriteRaw(XmlConvert.ToString(Value, XML_DATE_FORMAT));
    }

    public static implicit operator DateTime(XmlDateTime custom)
    {
        return custom.Value;
    }

    public static implicit operator XmlDateTime(DateTime custom)
    {
        return new XmlDateTime() { Value = custom };
    }
}

Instead of serialization you can use XML linq like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = 
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<people type=\"array\">" +
                   "<person>" +
                      "<last-name>lastName</last-name>" +
                      "<first-name>firstName</first-name>" +
                      "<id type=\"integer\">123</id>" +
                      "<last-changed-on>2014-11-21T15:04:53Z</last-changed-on>" +
                   "</person>" +
                "</people>";

            XDocument doc = XDocument.Parse(input);

            var results = doc.Descendants("person").Select(x => new {
                last_name = x.Element("last-name").Value,
                first_name = x.Element("first-name").Value,
                id = int.Parse(x.Element("id").Value),
                last_changed = DateTime.Parse(x.Element("last-changed-on").Value)
            }).ToList();
        }
    }
}
​

If dont like System.Xml.XmlConvert.ToDateTime(str, "yyyy-MM-dd'T'HH:mm:ssZ")
Can use standart function: DateTime.ParseExact(str, "yyyy-MM-dd'T'HH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM