How do I properly serialize a DateTime object (e.g. using a BinaryWriter), and preserve its complete state?
I was under the impression that a date time was only represen
There are two pieces of information to worry about:
Internally these are both encoded into a single long, the dateData like so:
this.dateData = (ulong) (ticks | (((long) kind) << 62));
So the Ticks
property will not encode all the state. It will be missing the DateTimeKind information.
The dateData
does encode all the data, so it is a curious thing that the serialiser stores both that and Ticks
!
So what you could do is this:
ulong dataToSerialise = (ulong) (date.Ticks | ((long) date.Kind) << 62);
And when deserializing, you can do this:
long ticks = (long)(deserialisedData & 0x3FFFFFFFFFFFFFFF);
DateTimeKind kind = (DateTimeKind)(deserialisedData >> 62);
DateTime date = new DateTime(ticks, kind);
This does make use of knowledge about the internals of DateTime, and it could theoretically change in the future, which could break this kind of serialisation.
EDIT
There are some gotchas to do with local time adjustment.
So I'm going to suggest that instead of messing about with all of the above, you look at the DateTime.ToBinary() and DateTime.FromBinary() methods which will allow you to serialize as a long, subject to the caveats relating to the local time adjustment. These caveats are fully documented in the MSDN links above.
i have done this with serialization for transmitting date in TCP Sockets
here is code you can serialize any object like this
public static byte[] DateToBytes(DateTime _Date)
{
using (System.IO.MemoryStream MS = new System.IO.MemoryStream()) {
BinaryFormatter BF = new BinaryFormatter();
BF.Serialize(MS, _Date);
return MS.GetBuffer();
}
}
public static DateTime BytesToDate(byte[] _Data)
{
using (System.IO.MemoryStream MS = new System.IO.MemoryStream(_Data)) {
MS.Seek(0, SeekOrigin.Begin);
BinaryFormatter BF = new BinaryFormatter();
return (DateTime)BF.Deserialize(MS);
}
}
EDIT
without binaryformatter
//uses 8 byte
DateTime tDate = DateAndTime.Now;
long dtVal = tDate.ToBinary();
//64bit binary
byte[] Bits = BitConverter.GetBytes(tDate.ToBinary());
//your byte output
//reverse
long nVal = BitConverter.ToInt64(Bits, 0);
//get 64bit binary
DateTime nDate = DateTime.FromBinary(nVal);
//convert it to date