我们来分析一下DateTime的数据需求,DateTime主体要求是保存时间,年月日时分秒。在.net的DateTime结构中提供ToBinary()方法,将DateTime序列化成long型数值。这篇文章描述的也正是一种时间序列化方法。
数据位分析:
年-> 4位有效数字,最大数字 9999, 二进制 10011100001111, 位数 14 。
月-> 2位有效数字,最大数字 12, 二进制 1100, 位数 4 。
日-> 2位有效数字,最大数字 31, 二进制 11111, 位数 5 。
时-> 2位有效数字,最大数字 23, 二进制 10111, 位数 5 。
分-> 2位有效数字,最大数字 59, 二进制 111011, 位数 6 。
秒-> 2位有效数字,最大数字 59, 二进制 111011, 位数 6 。
毫秒-> 3位有效数字,最大数字 999, 二进制 1111100111, 位数 10 。
钠秒-> 9位有效数字,最大数字 999999999,二进制 111011100110101100100111111111,位数 30 。
注意:在.net中 DateTime精度是100钠秒。
百钠秒-> 7位有效数字,最大数字 9999999,二进制 100110001001011001111111,位数 24 。
十万钠秒-> 4位有效数字,最大数字 9999,二进制 10011100001111,位数 14 。
采用毫秒融入后,最终时间数据是:
年 + 月 + 日 + 时 + 分 + 秒 + 毫秒 + 10万钠秒
采用百钠秒融入后,最终时间数据是:
年 + 月 + 日 + 时 + 分 + 秒 + 百钠秒
yyyy-MM-dd HH:mm:ss.fffffff
所需位数是:14 + 4 + 5 + 5 + 6 + 6 + 10 + 14 = 64。
和long类型长度一致,不得不说是一个巧合,是偶然也是必然。在.net中,正是使用long类型来序列化DateTime结构。
using System;
public class 自定义时间
{
private const UInt32 DEFAULT_FOUR_BITS = 0xf;
private const UInt32 DEFAULT_FIVE_BITS = 0x1f;
private const UInt32 DEFAULT_SIX_BITS = 0x3f;
private const UInt32 DEFAULT_TEN_BITS = 0x3ff;
private const UInt32 DEFAULT_FOURTEEN_BITS = 0x3fff;
private const UInt32 DEFAULT_TWENTY_FOUR_BITS = 0xffffff;
private const byte DEFAULT_MOVE_FOUR_BITES = 4;
private const byte DEFAULT_MOVE_FIVE_BITES = 5;
private const byte DEFAULT_MOVE_SIX_BITES = 6;
private const byte DEFAULT_MOVE_TEN_BITES = 10;
private const byte DEFAULT_MOVE_THIRTEEN_BITES = 13;
private const byte DEFAULT_MOVE_TWENTY_FOUR_BITES = 24;
public Int64 时间数据 { get; set; }
public int 年
{
get
{
return (int)(时间数据 & DEFAULT_FOURTEEN_BITS);
}
set
{
时间数据 |= (UInt32)value;
}
}
public int 月
{
get
{
return (int)((时间数据 >> DEFAULT_MOVE_THIRTEEN_BITES) & DEFAULT_FOUR_BITS);
}
set
{
时间数据 |= (UInt32)value << DEFAULT_MOVE_THIRTEEN_BITES;
}
}
public int 日
{
get
{
return (int)((时间数据 >> DEFAULT_MOVE_THIRTEEN_BITES + DEFAULT_MOVE_FOUR_BITES) & DEFAULT_FIVE_BITS);
}
set
{
时间数据 |= (UInt32)value << (DEFAULT_MOVE_THIRTEEN_BITES + DEFAULT_MOVE_FOUR_BITES);
}
}
public int 时
{
get
{
return (int)((时间数据 >> DEFAULT_MOVE_THIRTEEN_BITES + DEFAULT_MOVE_FOUR_BITES + DEFAULT_MOVE_FIVE_BITES) & DEFAULT_FIVE_BITS);
}
set
{
时间数据 |= (UInt32)value << (DEFAULT_MOVE_THIRTEEN_BITES + DEFAULT_MOVE_FOUR_BITES + DEFAULT_MOVE_FIVE_BITES);
}
}
public int 分
{
get
{
return (int)((时间数据 >> DEFAULT_MOVE_THIRTEEN_BITES + DEFAULT_MOVE_FOUR_BITES + DEFAULT_MOVE_FIVE_BITES * 2) & DEFAULT_SIX_BITS);
}
set
{
时间数据 |= (UInt32)value << (DEFAULT_MOVE_THIRTEEN_BITES + DEFAULT_MOVE_FOUR_BITES + DEFAULT_MOVE_FIVE_BITES * 2);
}
}
public int 秒
{
get;
set;
}
public int 毫秒
{
get;
set;
}
public int 纳秒
{
get;
set;
}
public 自定义时间()
{
时间数据 = 0;
}
public override string ToString()
{
return string.Format("{0}-{1}-{2} {3}:{4}:{5}.{6}",年,月,日,时,分,秒,毫秒);
}
public string ToLongString()
{
return string.Format("{0}-{1}-{2} {3}:{4}:{5}.{6}", 年, 月, 日, 时, 分, 秒, 纳秒);
}
public static void Test()
{
自定义时间 time = new 自定义时间();
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));//参数初始化
int year = 2011;
int month = 6;
int day = 30;
int hour = 12;
int minute = 10;
int second = 10;
int millisecond = 333;
int ns = 333333333;
time.年 = year;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToString());
time.月 = month;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToString());
time.日 = day;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToString());
time.时 = hour;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToString());
time.分 = minute;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToString());
time.秒 = second;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToString());
time.毫秒 = millisecond;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToString());
time.纳秒 = ns;
Console.WriteLine("当前数据二进制输出 {0}", Convert.ToString(time.时间数据, 2));
Console.WriteLine(time.ToLongString());
}
}
在这个示例代码中省略了大长度位操作的代码(秒、毫秒、钠秒),如各位有兴趣,可以自行处理。大长度位操作会在第四篇随笔中进行探讨。
下一篇: