Как сериализовать в dateTime - PullRequest
4 голосов
/ 21 ноября 2008

Работа, чтобы получить DateTimes для любого часового пояса. Я использую DateTimeOffset, а также строку и атрибут XmlElement. Когда я это делаю, я получаю следующую ошибку:

[InvalidOperationException: 'dateTime' недопустимое значение для Свойство XmlElementAttribute.DataType. dateTime не может быть преобразован в System.String.]
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (TypeModel модель, String NS, ImportContext контекст, String dataType, XmlAttributes a, логические повторы, Логическая openModel, RecursionLimiter ограничитель) + 450

[InvalidOperationException: было ошибка, отражающая тип 'System.String'.]
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (TypeModel модель, String NS, ImportContext контекст, String dataType, XmlAttributes a, логические повторы, Логическая openModel, RecursionLimiter ограничитель) + 1621
System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping (MemberMapping аксессор, модель FieldModel, XmlAttributes a, String ns, Type choiceIdentifierType, логический RPC, Логическая openModel, RecursionLimiter ограничитель) + 8750
System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping (StructModel родитель, модель FieldModel, XmlAttributes a, String ns, Ограничитель RecursionLimiter) + 139
System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers (StructMapping отображение, модель StructModel, логическое значение openModel, String typeName, Ограничитель RecursionLimiter) + 1273

[InvalidOperationException: было ошибка, отражающая свойство 'creationTimeX'.] ...

Код:

 [System.Xml.Serialization.XmlElement(ElementName = "creationTime",
      DataType="dateTime")]
 public string creationTimeX
    {
        get
        {
            return this.creationTimeField.ToString("yyyy-MM-ddTHH:mm:sszzz");
        }
        set
        {
            DateTimeOffset.TryParse(value, out this.creationTimeField);
        }
    }

[System.Xml.Serialization.XmlIgnoreAttribute()]
public System.DateTimeOffset creationTime
{
    get {
        return this.creationTimeField;
    }
    set {
        this.creationTimeField = value;
    }
}

Ответы [ 6 ]

3 голосов
/ 21 февраля 2012

Вот что у меня сработало

private const string DateTimeOffsetFormatString = "yyyy-MM-ddTHH:mm:sszzz";
private DateTimeOffset eventTimeField;

[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
public string eventTime
{
    get { return eventTimeField.ToString(DateTimeOffsetFormatString); }
    set { eventTimeField = DateTimeOffset.Parse(value); }
}
2 голосов
/ 21 ноября 2008

Посмотрите на этот вопрос StackOverflow о сериализации дат и UTC:

Рекомендации по сериализации DateTime в .Net Framework 3.5 / SQL Server 2008

Нет необходимости создавать специальное свойство только для выполнения сериализации.

1 голос
/ 10 апреля 2014

Используйте методы XmlConvert.ToDateTimeOffset () и .ToString () для правильной сериализации и десериализации DateTimeOffset в свойстве обходного пути XmlSerializer.

Полный пример в статье Microsoft Connect здесь и подтверждение того, что, к сожалению, Microsoft не исправит этот упущение (он должен был изначально поддерживаться XmlSerializer как любой примитивный тип):

https://connect.microsoft.com/VisualStudio/feedback/details/288349/datetimeoffset-is-not-serialized-by-a-xmlserializer

1 голос
/ 21 ноября 2008

Я бы посоветовал вам сериализовать DateTime как long (это то, что реализация использует внутренне для хранения фактического значения).

Вы можете использовать DateTime.Ticks, чтобы получить значение, и у него есть конструктор, который занимает много времени (Int64).

0 голосов
/ 14 февраля 2019

Это 2019 год, и я нашел отличный единственный скрипт для ящика пользовательского типа и свойства UDateTime из этого gist

using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

// we have to use UDateTime instead of DateTime on our classes
// we still typically need to either cast this to a DateTime or read the DateTime field directly
[System.Serializable]
public class UDateTime : ISerializationCallbackReceiver {
    [HideInInspector] public DateTime dateTime;

    // if you don't want to use the PropertyDrawer then remove HideInInspector here
    [HideInInspector] [SerializeField] private string _dateTime;

    public static implicit operator DateTime(UDateTime udt) {
        return (udt.dateTime);
    }

    public static implicit operator UDateTime(DateTime dt) {
        return new UDateTime() {dateTime = dt};
    }

    public void OnAfterDeserialize() {
        DateTime.TryParse(_dateTime, out dateTime);
    }

    public void OnBeforeSerialize() {
        _dateTime = dateTime.ToString();
    }
}

// if we implement this PropertyDrawer then we keep the label next to the text field
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(UDateTime))]
public class UDateTimeDrawer : PropertyDrawer {
    // Draw the property inside the given rect
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty(position, label, property);

        // Draw label
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        // Don't make child fields be indented
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        // Calculate rects
        Rect amountRect = new Rect(position.x, position.y, position.width, position.height);

        // Draw fields - passs GUIContent.none to each so they are drawn without labels
        EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("_dateTime"), GUIContent.none);

        // Set indent back to what it was
        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}
#endif
0 голосов
/ 21 ноября 2008

David

Тип данных свойства (creationTimeX) является строкой, а тип данных XmlSerialization - "dateTime". Вот почему вы получаете это исключение.

Это можно исправить, изменив тип данных на DateTime

Также для вашего вопроса о текущем времени для любого часового пояса, вы должны будете применить DateTime.Now.ToUniveralTime и примените к нему соответствующий шаблон DateTimeFormat.

Шаги для этого здесь

http://msdn.microsoft.com/en-us/library/k494fzbf.aspx

Спасибо -RVZ

...