Webservice-如何在datetime元素中传递时区信息

本文关键字:时区 信息 元素 datetime Webservice- | 更新日期: 2023-09-27 18:24:28

我得到了一个wsdl,我必须按照它的规范创建一个web服务;我正在使用visual studio 2010。除此之外,还有这种复杂类型的定义:

    <xsd:complexType name="Person">
        <xsd:sequence>
            <xsd:element name="surname" type="xsd:string"/>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="birthDate" nillable="true" type="xsd:dateTime"/>
        </xsd:sequence>
    </xsd:complexType>

使用VS,我得到了以下cs(我不记得我是怎么做的,但我遵循了网上的说明):

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://XXX/Submitter/")]
    public partial class Person {
        private string surnameField;
        private string nameField;
        private System.Nullable<System.DateTime> birthDateField;
        /// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string surname {
            get {
                return this.surnameField;
            }
            set {
                this.surnameField = value;
            }
        }
        /// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string name {
            get {
                return this.nameField;
            }
            set {
                this.nameField = value;
            }
        }
        /// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
        public System.Nullable<System.DateTime> birthDate {
            get {
                return this.birthDateField;
            }
            set {
                this.birthDateField = value;
            }
        }

一切都是正确的:它编译、运行并给出预期的结果;唯一的问题是,给我wsdl的另一方在调用我的web服务时,希望将出生日期字段作为

2013-02-15T17:28:00+01:00

使用时区信息,而他们收到的结果就像

2015-11-17T18:30:11

没有时区。

我的问题是,我有一个DateTime?类型,这就是我传递给从类实例化的对象的类型;我应该重写序列化还是有其他最常见的解决方案?感谢

Webservice-如何在datetime元素中传递时区信息

不幸的是,XSD与.NET在SOAP web服务中支持的内容严重不匹配。

.NET对于这类信息只有两种类型——DateTimeDateTimeOffset。从技术上讲,最好将xs:datetime映射到DateTimeOffset,但这不是它的工作方式。相反,xs:datetime被映射到DateTime,并且在很大程度上依赖于值的Kind属性来确定它的序列化方式。

  • DateTime.KindDateTimeKind.Unspecified时,不传递偏移信息。

  • DateTime.KindDateTimeKind.Utc时,则通过Z,与+00:00相同。

  • DateTime.KindDateTimeKind.Local时,则通过与给定日期相对应的本地偏移。

您可以使用DateTime.SpecifyKind应用种类,或者如果您想在过程中转换值,可以使用.ToUniversalTime().ToLocalTime()。或者,如果您知道这些值属于特定时区,则可以使用TimeZoneInfo对象的转换方法。只要得到的种类是Unspecified以外的任何东西,它就会包括偏移。

不幸的是,没有指定任意偏移的选项。这将需要DateTimeOffset类型,而SOAP服务不支持这种类型。

另外,考虑一下xs:datetime类型实际上是错误的出生日期类型。它应该使用xs:date只是一个日期,例如"2013-02-15"。目前在.NET中还没有支持这一点的类型,尽管很快就会有一个类型,如corefxlab包中System.Time包中的Date。这对类似的场景很有用,但我们是否可以返回并修复SOAP序列化程序以使用它们还有待观察。

实际上,最好的想法是不使用XML和SOAP。而是围绕JSON和REST来设计web服务。在那里你可以完全控制这样的事情。

您可能想看看Jon Skeet的答案。他提出了这样一个结构:

public struct DateTimeWithZone
{
    private readonly DateTime utcDateTime;
    private readonly TimeZoneInfo timeZone;
    public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone)
    {
        utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZone); 
        this.timeZone = timeZone;
    }
    public DateTime UniversalTime { get { return utcDateTime; } }
    public TimeZoneInfo TimeZone { get { return timeZone; } }
    public DateTime LocalTime
    { 
        get 
        { 
            return TimeZoneInfo.ConvertTime(utcDateTime, timeZone); 
        }
    }        
}