Freigeben über


Interop and DateTime formatting

Interop and Date or Time values

While many people have moved beyond the fundamentals and are working on secure, reliable, transacted webservices, or on adding those kinds of quality-of-service to other interop mechanisms, the fundamental data-type interop issues are still with us.

Date and Time values are a case in point. One source of interop troubles: a Java app can serialize a nil Date, while in .NET the xsd:date maps to System.DateTime, which is a value type. What does a .NET app do when it receives a nil date sent from a Java app? (Answer: by default, it chokes.)

Another source of trouble: assumptions about the timezone when there is none present in the serialized form (example:10/3/2005 00:00:00"), and the implications of those assumptions. In .NET, the de-serialization for DateTime assumes the local timezone if no timezone is present in the string. When a .NET app running in New York City de-serializes a string like "10/3/2005 00:00:00", it reads that as, "Midnight on 3 October 2005, in New York". When the same .NET app running in London does the same thing, it reads the value as "Midnight on 3 October 2005, in London", which is not the same point in time.

Other platforms may make different assumptions about timezone in serialized forms. For example, the serializer may assume "no timezone at all" or may assume "UTC". Neither of these will give correct results when connected to a .NET app that makes different assumptions.

To avoid this confusion, explicitly pass the timezone in the serialized form, and explicitly handle the nil condition. You can do this in .NET, for weird formats, with a surrogate string field, and a Parse/ParseExact. Something like this:

public class MyType {

private static string formatString= "yyyy-MM-ddTHH:mm:ss.fffffffzzz";

private static System.Globalization.CultureInfo CInfo= new System.Globalization.CultureInfo("en-US", true);

[XmlIgnore] public System.DateTime internal_DateTimeField;

[XmlIgnore] public bool DateTimeFieldIsNull;

[XmlElement(IsNullable=true)]

public string DateTimeStringProperty {

set {

if ((value!=null) && (value != "")) {

internal_DateTimeField= System.DateTime.ParseExact(value, formatString, CInfo);

DateTimeFieldIsNull= false;

}

else

DateTimeFieldIsNull= true;

}

get {

return (DateTimeFieldIsNull) ?

null :

internal_DateTimeField.ToString(formatString) ;

}

}

}

This class provides a string field as a surrogate for the actual DateTime value. The app can directly use the internal DateTime value (internal_DateTimeField), but during serialization or de-serialization, that DateTime value is [XmlIgnore]'d. Instead the serializer gets the string property, which contains a directly-controlled version of the DateTime value.

You need to do this when you don't control both ends of the wire, as for example, when there is an existing Date/time format in use, or when it is VB6 or Java or PHP or somebody else on the other end of the line, and your choices are limited. You can specify a format string to the ParseExact() and ToString() methods, to handle just about any time format you like.

You'll have to make similar arrangements on the other side of the wire, whether they two are connected by web services, a message queue, a database, email, or smoke-signals. If you have .NET on both ends of the wire, it becomes simpler: you can use the same code and same formatting string. In all cases, just make sure you include the timezone. The issue of assumptions on serialization formats applies regardless of the envelope you enclose the message in, and regardless of what delivery service you use, and regardless of what technology is used on either end of the wire.

Full example source here

Coincidentally, the nice people at W3C also see that dates and times can be an issue. They filed a note in October on this subject: NOTE-timezone-20051013.

-Dino

Comments