每日学习总结:根据给定的时间段,返回时间段内的月(年/季度)的数组、使用JavascriptSerializer类将DataTable序列化和反序列化
Posted on 2013-04-03 23:37 星星之火116 阅读(2332) 评论(0) 编辑 收藏 举报1、根据给定的时间段,返回时间段内的月(年/季度)的数组
解析:
这是上周项目中遇到的一个问题,在sql中通过DatePart()函数,加上group by 分组来实现,获取给定时间段内每月(/年、季度)的相关信息,
但是这样有一个问题,如果数据库里边在符合条件的时间段内没有相关信息的话,返回的信息是不完整的,
示例:返回2012年1月1日,到2012年12月31日范围区间的数据,按月分组,正常情况下该出现12个月的信息,但是如果某个月没有信息,则可能
返回的信息少于12条,但是项目要求,应该返回完整的信息,如果没有值的话,默认为0。刚开始的时候毫无头绪,有想过用List来暂时存储信息,
然后最后再做统一处理,但是这样会带来一些不必要的开销。后来想了到这样的方法,主要思想是分段处理,分三段:开始那一年、中间完整的那几年
、最后那一年,这样就把问题给细化,简单了许多。具体请看下面代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | 示例:startDate:20060116 ,endDate:20121115,type参数:yy(年),mm(月),qq(季度) /// <summary> /// 获取不同日期类型对应的日期数组,yy为年,qq为季度,mm为月 /// </summary> /// <param name="chart"></param> /// <returns></returns> public string [] GetDateCount( string startDate, string endDate, string type) { int startYear = Convert.ToInt32(startDate.Substring(0, 4)); //开始的那一年 int endYear = Convert.ToInt32(endDate.Substring(0, 4)); //结束的那一年 int startMonth, endMonth; //开始/结束的那一月 int yearCount = endYear - startYear + 1; //开始与结束年之差 string [] dates = new string [0]; switch (type) { case "yy" : //返回的时间粒度为年 dates = new string [yearCount]; for ( int i = 0; i < yearCount; i++) { dates[i] = startYear.ToString(); startYear++; } break ; case "qq" : //返回的时间粒度为季度 yearCount = endYear - startYear - 1; //返回完整的年的个数,开始那一年,和结束那一年除外 startMonth = Convert.ToInt32(startTime.Substring(4, 2)); //获取开始的那一年的月份 endMonth = Convert.ToInt32(endTime.Substring(4, 2)); //获取结束那一年的月份 int qsm, qem, qsml, qeml; qsm = GetIntQ(startMonth); //调用GetInQuiry函数,获取开始时间为当年的第几季度 qem = GetIntQ(endMonth); //调用GetInQuiry函数,获取结束时间为当年的第几季度 qsml = 4 - qsm; //获取开始那一年有多个季度在统计范围内 qeml = qsm; //获取结束那一年有多少个季度在统计范围内 dates = new string [qsml + yearCount * 4 + qeml]; //初始化返回的数组,数组大小即为给定范围内的季度 for ( int i = 0; i < qsml; i++) //初始化数组,开始那一年的季度 { dates[i] = startYear.ToString() + qsm.ToString(); qsm++; } for ( int y = 1; y <= yearCount; y++) //完整的那几年的季度 { int j = 1; int qsi = qsml + (y - 1) * 4; for ( int i = qsi; i < y * 4 + qsml; i++) { dates[i] = (startYear + y).ToString() + j.ToString(); j++; } } int qeb = 1; for ( int k = (qsml + yearCount * 4); k < qsml + yearCount * 4 + qeml; k++) //结束那一年的季度 { dates[k] = endYear.ToString() + qeb.ToString(); qeb++; } break ; case "mm" : startMonth = Convert.ToInt32(startTime.Substring(4, 2)); endMonth = Convert.ToInt32(endTime.Substring(4, 2)); int sm = 12 - startMonth + 1; //起始那一年总共的月份 int em = endMonth; //截止那一年总共的月份 yearCount = endYear - startYear - 1; //间隔时间段内完整的年数 dates = new string [sm + yearCount * 12 + em]; //总共有多个月要统计 for ( int i = 0; i < sm; i++) //起始那一年的月份 { dates[i] = startYear.ToString() + startMonth.ToString(); startMonth++; } for ( int y = 1; y <= yearCount; y++) { int j = 1; int si = sm + (y - 1) * 12; for ( int i = si; i < y * 12 + sm; i++) { dates[i] = (startYear + y).ToString() + j.ToString(); j++; } } int eb = 1; for ( int k = (sm + yearCount * 12); k < sm + yearCount * 12 + em; k++) { dates[k] = endYear.ToString() + eb.ToString(); eb++; } break ; default : dates = new string [0]; break ; } return dates; } /// <summary> /// 用来获取当前月对应的季度 /// </summary> /// <param name="i"></param> /// <returns></returns> public static int GetIntQ( int i) { int r = 0; if (i <= 3) { r = 1; } else if (3 < i && i <= 6) { r = 2; } else if (6 < i && i <= 9) { r = 3; } else if (9 < i && i <= 12) { r = 4; } return r; } |
2、使用JavascriptSerializer类将DataTable序列化和反序列化
解析:
JavascriptSerializer类一般多用来将一个List<ClassName>对象序列化,关于这一点我在Serialization全解析一文中有提到,
有不太懂的朋友可以看一下了解了解。虽是这样,JavascriptSerializer类没有专门的序列话DataTable的方法,非官方的有
Nowtonsoft.Json是一个做的很不错的第三放的dll,也可以直接拿来用,但是今天要讲的是用JavascriptSerializer来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | DataTable的序列化和反序列化 /// <summary>DataTable序列化 /// </summary> /// <param name="dt"></param> /// <returns></returns> public string SerializeDataTable(DataTable dt) { JavaScriptSerializer serializer = new JavaScriptSerializer(); List<Dictionary< string , object >> list = new List<Dictionary< string , object >>(); foreach (DataRow dr in dt.Rows) //每一行信息,新建一个Dictionary<string,object>,将该行的每列信息加入到字典 { Dictionary< string , object > result = new Dictionary< string , object >(); foreach (DataColumn dc in dt.Columns) { result.Add(dc.ColumnName, dr[dc].ToString()); } list.Add(result); } return serializer.Serialize(list); //调用Serializer方法 } /// <summary>DataTable反序列化 /// </summary> /// <param name="strJson"></param> /// <returns></returns> public DataTable DeserializerTable( string strJson) { DataTable dt = new DataTable(); JavaScriptSerializer serializer = new JavaScriptSerializer(); // var obj = serializer.DeserializeObject(strJson);//反序列化 ArrayList arralList = serializer.Deserialize<ArrayList>(aaa); //反序列化ArrayList类型 if (arralList.Count > 0) //反序列化后ArrayList个数不为0 { foreach (Dictionary< string , object > row in arralList) { if (dt.Columns.Count == 0) //新建的DataTable中无任何信息,为其添加列名及类型 { foreach ( string key in row.Keys) { dt.Columns.Add(key, row[key].GetType()); //添加dt的列名 } } DataRow dr = dt.NewRow(); foreach ( string key in row.Keys) //讲arrayList中的值添加到DataTable中 { dr[key] = row[key]; //添加列值 } dt.Rows.Add(dr); //添加一行 } } } return dt; } |
上边总结 的这些都是在项目中遇到的问题,然后有了些思路,写成了一些具体的方法,希望能给朋友们一些帮助。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构