The odd task that I have been given is to serialize a LARGE object using XML Serialization. This object contains multiple Nested UserDefined classes, with multiple DateTime fields. The Requirement for the DateTime data is that it must ALWAYS be displayed in the TimeZone of the user who initially created and set the data. Thus, I Cannot use UTC OR Local times because when de-serialized, they wouldn’t be the same as they were. I also cannot display the values in UTC, they must be displayed in Local Time. What I need is some odd serialization format that represents the concept of “Absolute Local Time”…that would be “Local Time without TimeZone”.
I can strip the TZ from the date string using Regex, that’s easy. but the sheer size of the object I’m dealing with means that more often than not I get an OutOfMemoryException. I watched it run without debug once and my used memory spiked from 100k to 800k during the operation. Not nice. And that was one of the smaller files.
Doc.DocumentElement.InnerXML = Regex.Replace(Doc.DocumentElement.InnerXML, "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})(\\+|-)(\\d{2}:\\d{2})", "$1")
So far, the only option I have seen is to create duplicates of ALL the dateTime fields, set the DT fields themselves as “XmlIgnore()”, and then manually restore all the dates from the serialized string data after the doc is re-loaded. This is also not practical.
See Custom DateTime XML Serialization
Is there any way to force the serialization engine to serialize DateTime objects without their TimeZone data? Preferably something generic that doesn’t have to be individually applied to every DT property in the object?
!!EDIT!!
I may have found a partial solution. It might at least help moving forward. DateTimeKind.Unspecified, when serialized, doesn’t seem to have any TimeZone data attached to it. Is this the solution I’m looking for. Forcefully cast all my DateTime data using DateTime.SpecifyKind?
public DateTime? StartDate
{
get
{ return _StartDate; }
set
{
if (_StartDate == value)
return;
if (value != null)
_StartDate = DateTime.SpecifyKind(value.Value, DateTimeKind.Unspecified);
else
_StartDate = value;
OnPropertyChanged("StartDate");
}
}
Found an answer. This is not exactly what I was looking for, but serves as an effective work around.
After reading in the XML From the file, and before running it through the serializer, run the Regex on the bare XML Text to remove the offset. The function returns a string reader running against the modified XML string, which can then be run through a de-serialization into the object.
Rather than using the serializer to save the xml directly to the output stream, you can use a stringBuilder to intercept the serialized xml. Then using the same process as during the loading procedure, you remove the TimeZone offset via RegularExpression, then return a StringReader linked to the modified text, which is then used to write the data back out into a file.
Slightly hackish feeling, but effective. Very memory intensive though, avoid debugging the functions directly if you can, or if you have to, try not to evaluate the strings, last time I tried that it crashed my VS instance completely.