关于DateTime里的MinValue

Alaska_Lee 2014-04-01 10:35:29
最近做重构,主要解决系统有个页面数据加载慢的问题,页面调用WebService返回一个DataTable,表中字段基本囊括了所有常用类型,返回数据大概400行。开始以为是WebService传输数据多的原因,对传输数据进行了优化,分批次传回部分数据,测试下来还是慢;然后想到将DataTable压缩传输,解决了传输慢的问题,可是发现解压缩的过程成了一个瓶颈。甚至这个过程比直接传输DataTable还慢。于是拆开每个列做成DataTable解压和传输,发现了问题所在:DataTable中有大量的DateTime类型的数据,且其值为0000-00-00,也就是DateTime.MinValue,当换成其他时间时就挺快的了。上网查了下原因,说是SOAP序列化和传输时处理0000-00-00会有异常,具体不太明白,而且我用的序列化方法是二进制序列化,应该与SOAP无关,请大神给解释下。
代码参考liyiding23,贴如下:

public class ZipHelp
{
public static void Zip(DataTable dt, out string afterZip)
{
IFormatter formatter = new BinaryFormatter();//定义BinaryFormatter以序列化DataSet对象
MemoryStream unCompressMS = new MemoryStream();//创建内存流对象
// 序列化DataTable
formatter.Serialize(unCompressMS, dt);
MemoryStream compressMs = new MemoryStream();
// gzip压缩
GZipStream gzipStream = new GZipStream(compressMs, CompressionMode.Compress, true);
gzipStream.Write(unCompressMS.ToArray(), 0, unCompressMS.ToArray().Length);
gzipStream.Close();
afterZip = Convert.ToBase64String(compressMs.ToArray(), 0, compressMs.ToArray().Length);
compressMs.Close();
unCompressMS.Close();
}

public static void UnZip(string ziped, out DataTable afterUnZip)
{
byte[] buffer1 = Convert.FromBase64String(ziped);
MemoryStream ms1 = new MemoryStream(buffer1, 0, buffer1.Length);
ms1.Position = 0;
MemoryStream ms2 = new MemoryStream();
byte[] buffer2 = new byte[4096];
int offset = 0;
// 解压
GZipStream gzipStream = new GZipStream(ms1, CompressionMode.Decompress);
while ((offset = gzipStream.Read(buffer2, 0, buffer2.Length)) != 0)
{
ms2.Write(buffer2, 0, offset);
}
gzipStream.Close();
BinaryFormatter formatter1 = new BinaryFormatter();
ms2.Position = 0;
// 反序列化
afterUnZip = formatter1.Deserialize(ms2) as DataTable;
ms2.Close();
ms1.Close();
}
}

测试代码:

class Program
{
static void Main(string[] args)
{
#region 测试DateTime.MinValue解压缩效率
DataTable dt = new DataTable();
dt.Columns.Add("name", typeof(string));
dt.Columns.Add("time", typeof(DateTime));
for (int i = 0; i < 300; i++)
{
dt.Rows.Add(new object[] { "hahhahhaha", DateTime.MaxValue });
}
string afterzip = "";
DataTable afterUnZip = new DataTable();
DateTime time1 = DateTime.Now;
ZipHelp.Zip(dt, out afterzip);
DateTime time2 = DateTime.Now;
ZipHelp.UnZip(afterzip, out afterUnZip);
DateTime time3 = DateTime.Now;
TimeSpan ts1 = time2 - time1; //0.026秒
TimeSpan ts2 = time3 - time2; //0.091秒

DataTable dt1 = new DataTable();
dt1.Columns.Add("name", typeof(string));
dt1.Columns.Add("time", typeof(DateTime));
for (int i = 0; i < 300; i++)
{
dt1.Rows.Add(new object[] { "hahhahhaha", DateTime.MinValue });
}
string afterzip1 = "";
DataTable afterUnZip1 = new DataTable();
DateTime time4 = DateTime.Now;
ZipHelp.Zip(dt1, out afterzip1);
DateTime time5 = DateTime.Now;
ZipHelp.UnZip(afterzip1, out afterUnZip1);
DateTime time6 = DateTime.Now;
TimeSpan ts3 = time5 - time4; //0.01秒
TimeSpan ts4 = time6 - time5; //8.98秒
System.Console.WriteLine("");
#endregion
}
}


...全文
633 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
Alaska_Lee 2014-04-03
  • 打赏
  • 举报
回复
还是自己找到了原因,给大家说下吧: DateTime类型在序列化的时候,会将DateTime类型转为协调世界时,也就是将DateTime的kind属性由本地时间Local转为UTC。我们在创建DateTime类型的时候,会默认Kind为UnSpecified,也就是说DateTime字面值既能表示本地实际也能表示世界时,在序列化的时候,就不会对它进行转化。因此我们在序列化DateTime类型本身的时候,是不会出现异常的! 而我们在DataTable里指定某一列为DateTime类型的时候,这个DateTime的时间模式有4种:local、UTC、Unspecified和UnspecifiedLocal。默认为最后一种。而最后一种在序列化的时候,也会转为UTC并且产生偏移。 在转化为UTC时,应该是将本地的时间减去本地时区与协调世界时的时差,例如我们处于东八区,因此转化为UTC时,是将时间减去8小时。因此本文的实验里,如果将DateTime的值设为0001-1-1 08:0:0就不会出现异常,而设为0001-1-1 07:59:59就会抛出异常:添加或减去的值产生无法表示的DateTime,抛出ArgumentOutOfRangeException。 0001-1-1 08:0:0也就成为我们这边能处理的最小值。
引用 2 楼 lijie19871108 的回复:
但是同时.net平台,最小时间不应该是一致的么? 为什么我这里解压缩的时候,会非常的慢呢?
引用 1 楼 JulioHuang 的回复:
因为个系统的最小,最大时间不一致,我们一般使用自己自定义的最大最小时间,比如1900年1月1日,这样可以避免时间在存储传输时出现问题,当然在显示和处理时要做最大最小时间判断
Alaska_Lee 2014-04-01
  • 打赏
  • 举报
回复
但是同时.net平台,最小时间不应该是一致的么? 为什么我这里解压缩的时候,会非常的慢呢?
引用 1 楼 JulioHuang 的回复:
因为个系统的最小,最大时间不一致,我们一般使用自己自定义的最大最小时间,比如1900年1月1日,这样可以避免时间在存储传输时出现问题,当然在显示和处理时要做最大最小时间判断
黄亮 2014-04-01
  • 打赏
  • 举报
回复
因为个系统的最小,最大时间不一致,我们一般使用自己自定义的最大最小时间,比如1900年1月1日,这样可以避免时间在存储传输时出现问题,当然在显示和处理时要做最大最小时间判断

8,834

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 组件/控件开发
社区管理员
  • 组件/控件开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧