[英]How to serialize to dateTime
努力獲取任何時區的日期時間。 我正在使用 DateTimeOffset、一個字符串和一個 XmlElement 屬性。 當我這樣做時,我收到以下錯誤:
[InvalidOperationException: 'dateTime' 是 XmlElementAttribute.DataType 屬性的無效值。 dateTime 不能轉換為 System.String。]
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel 模型,字符串 ns,ImportContext 上下文,字符串數據類型,XmlAttributes a,布爾重復,布爾 openModel,RecursionLimiter 限制器)+450[InvalidOperationException: 有一個錯誤反映類型“System.String”。]
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel 模型,字符串 ns,ImportContext 上下文,字符串數據類型,XmlAttributes a,布爾重復,布爾 openModel,RecursionLimiter 限制器)+1621
System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter) +8750
System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter) +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;
}
}
這對我有用
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); }
}
看看這個關於序列化日期和 UTC 的 StackOverflow 問題:
.Net framework 3.5/SQL Server 2008 中 DateTime 序列化的最佳實踐
無需創建特殊屬性來完成序列化。
使用 XmlConvert.ToDateTimeOffset() 和 .ToString() 方法正確序列化和反序列化 XmlSerializer 變通方法屬性中的 DateTimeOffset。
此處 Microsoft Connect 文章中的完整示例,並確認不幸的是 Microsoft 不會修復此疏忽(XmlSerializer 作為任何原始類型本應支持它):
我建議您將 DateTime 序列化為 long(這是實現在內部用於存儲實際值的內容)。
您可以使用DateTime.Ticks
來獲取值,它有一個需要很長時間的構造函數( Int64
)。
屬性creationTimeX
的數據類型是字符串,而 XmlSerialization 數據類型是DateTime
。 這就是為什么你會得到那個例外。
您可以通過將數據類型更改為DateTime
來解決此問題。
此外,對於任何時區的當前時間問題,您必須應用DateTime.Now.ToUniveralTime()
並在其上應用適當的 DateTimeFormat 模式。
這是 2019 年,我從這個要點中找到了一個很棒的自定義類型和屬性抽屜UDateTime
腳本
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.