c# - 序列化UTC时间c#

标签 c# datetime string-formatting datacontractserializer

我在数据协定中有一个 DateTime 数据成员。默认情况下,datacontractserializer 将 UTC 时间序列化为 yyyy-MM-ddTHH:mm:ss.fffffffZ 格式。我需要 yyyy-MM-ddTHH:mm:ss.000Z 格式,但无法控制数据契约(Contract)。那么我可以用 DataContractSerializer 做些什么,以我想要的格式提供 UTC 时间。谢谢

最佳答案

我创建了一个实现,它使用 IDataContractSurrogate 的实现来将您的 DTO 与您拥有的 DTO 序列化。

DTO

您没有提供 DTO,因此我创建了一个作为您的原始 DTO(您无法更改)和一个我们拥有的替代 DTO。它们将具有相同的公共(public)签名,只是它们的 DateTime 属性更改为 String 类型。

/// <summary>
/// original DTO, is fixed
/// </summary>
[DataContract]
class DTO
{
    [DataMember]
    public DateTime FirstDate { get; set; }

}

/// <summary>
/// Our own DTO, will act as surrogate
/// </summary>
[DataContract(Name="DTO")]
class DTO_UTC
{
    [DataMember]
    public string FirstDate { get; set; }
}

IDataContractSurrogate

IDataContractSurrogate提供在序列化和反序列化期间将一种类型替换为另一种类型所需的方法。

我在这里使用了简单的反射。如果您需要更好的性能,请考虑在类型之间发出生成的代码,甚至生成目标类型。

public class DTOTypeSurrogate : IDataContractSurrogate
{
    // this determines how you want to replace one type with the other
    public Type GetDataContractType(Type type)
    {
        if (type == typeof(DTO))
        {
            return typeof(DTO_UTC);
        }
        return type;
    }

    public object GetDeserializedObject(object obj, Type targetType)
    {
        // do we know this type
        if (targetType == typeof(DTO))
        {
            // find each DateTime prop and copy over
            var objType = obj.GetType();
            var target = Activator.CreateInstance(targetType);
            foreach(var prop in targetType.GetProperties())
            {
                // value comes in
                var src =  objType.GetProperty(prop.Name);
                // do we need special handling
                if (prop.PropertyType == typeof(DateTime))
                {
                    DateTime utcConvert;
                    // parse to a datetime
                    if (DateTime.TryParse(
                        (string) src.GetValue(obj),
                        System.Globalization.CultureInfo.InvariantCulture, 
                        System.Globalization.DateTimeStyles.AdjustToUniversal, 
                        out utcConvert))
                    {
                        // store 
                        prop.SetValue(target, utcConvert);
                    }
                }
                else
                {
                    // store non DateTime types
                    prop.SetValue(target, src);
                }
            }
            return target;
        }
        return obj;
    }

    public object GetObjectToSerialize(object obj, Type targetType)
    {
        // go from DTO to DTO_UTC
        if (targetType == typeof(DTO_UTC))
        {
            var utcObj = Activator.CreateInstance(targetType);
            var objType = obj.GetType();
            // find our DateTime props
            foreach(var prop in objType.GetProperties())
            {
                var src = prop.GetValue(obj);
                if (prop.PropertyType == typeof(DateTime))
                {
                    // create the string
                    var dateUtc = (DateTime)src;
                    var utcString = dateUtc.ToString(
                        "yyyy-MM-ddThh:mm:ss.000Z", 
                        System.Globalization.CultureInfo.InvariantCulture);
                    // store
                    targetType.GetProperty(prop.Name).SetValue(utcObj, utcString);
                } else
                {
                    // normal copy
                    targetType.GetProperty(prop.Name).SetValue(utcObj, src);
                }
            }
            return utcObj;
        }
        // unknown types return the original obj
        return obj;
    }
   // omitted the other methods in the interfaces for brevity
}

使用序列化器

在这里,我们创建了 DataContractSerializer 并为其提供了一个实例化的 DTO,在序列化之后,我们反转该过程以检查结果是否相同。

var surrogateSerializer =
    new DataContractSerializer(
        typeof(DTO),
        new Type[] {}, 
        Int16.MaxValue, 
        false, 
        true, 
        new DTOTypeSurrogate()); // here we provide our own implementation

var ms = new MemoryStream();
// test data
var testDto = new DTO { 
    FirstDate = new DateTime(2015, 12, 31, 4, 5, 6, DateTimeKind.Utc) };
// serialize
surrogateSerializer.WriteObject(ms, testDto);
// debug
var wireformat = Encoding.UTF8.GetString(ms.ToArray());

//reset
ms.Position = 0;
//deserialize
var dtoInstance = (DTO) surrogateSerializer.ReadObject(ms);
// verify we have the same data returned
Debug.Assert(dtoInstance.FirstDate == testDto.FirstDate);

关于c# - 序列化UTC时间c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34167762/

相关文章:

R:将 "special"字母转换为 UTF-8?

c# - 如何在 C# 程序中嵌入 perl 解释器

c# - 如何首先在多个表的 Entity Framework 代码中植入身份种子值

c# - 日期时间丢失毫秒

javascript - 堆叠面积图未呈现

javascript - 如何在 Javascript 中为字符串添加斜杠?

c# - 无法创建 NopEngine 实例

c# - 将 2D List 上的循环更改为 LINQ

java - 将日历日期格式设置为受时区影响的 dd-MM-yyyy

python - 如何在 python str.format 中转义点