可能做过报表的朋友和我有同样的感受,就是老板可能会说,我要****年**月**日到****年**月**日之间各年度、各季度、各月份的销售情况比较的报表。 
        马上我们想的就是如何来划分这些时间段吧。举个例子,比如日期是从2006年3月15日到2007年3月15日,如何来划分呢?我们知道.NET有System.DateTime类,今天我们讲的就是如何来灵活的使用它,构建我们划分时间段的组件。
        当然我想我需要先讲讲我们的划分原则,如上面的时间段所示,如果我们分年度来比较,那就是从06年3月15日到06年12月31日为一段,07年1月1日到3月15日为另一段;分季度的话当然是06-3-15至06-03-31、06-04-01至06-06-30... ...以此类推,再加上07-01-01至07-03-15一共5段;分月份不用多说,也是06-03-15至06-03-31、06-04-01至06-04-30... ... 07-02-01至07-02-28、07-03-01至07-03-15,一共13段。
         好了,原则讲了,接下来就是看代码的实现了,我们这里假设销售的日期就是订单下达的日期(OrderDate)。
         我们先建一个类DateDiffObject,并让它可序列化:

[Serializable]
    
public class DateDiffObject
    
{
        
public ArrayList SeperateDateByYear = new ArrayList();
        
public ArrayList SeperateDateByQuarter = new ArrayList();
        
public ArrayList SeperateDateByMonth = new ArrayList();

        
public DateDiffObject()
        
{

        }

    }

          上面三个ArrayList分别就是记录我把时间段按不同标准划分后的结果。
           然后,我们需要对用户输入进来的时间段进行各类分割了:

public DateDiffObject GetDateDiffObject(DateTime BeginDate,DateTime EndDate)
        
{
            DateDiffObject dateobj 
= new DateDiffObject();
                        
//string[] quarter length is 12, record the quarter of each month
            string[] quarter = {"1","1","1","2","2","2","3","3","3","4","4","4"};

            
if(BeginDate.Year==EndDate.Year)
            
{
                
//Same Year
                if(quarter[BeginDate.Month - 1== quarter[EndDate.Month - 1])
                
{
                    
//Same Quarter
                    if(BeginDate.Month!=EndDate.Month)
                    
{
                        
//Different Month
                        for(int i=0; i<=EndDate.Month - BeginDate.Month; i++)
                        
{
                            
if(i==0)
                            
{
                                    
//Seperate the first date period
                                this.dateobj.SeperateDateByMonth.Add(" and OrderDate between '"+BeginDate.ToString("yyyy-MM-dd")+"' and '"+GetMonthLastDay(BeginDate)+"");
                            }

                            
else if(i==EndDate.Month - BeginDate.Month)
                            
{
                                    
//Seperate the last date period
                                this.dateobj.SeperateDateByMonth.Add(" and OrderDate between '"+GetMonthFirstDay(EndDate)+"' and '"+EndDate.ToString("yyyy-MM-dd")+"");
                            }

                            
else
                            
{
                                    
//Seperate the middle date period
                                this.dateobj.SeperateDateByMonth.Add(" and OrderDate between '"+GetMonthFirstDay(BeginDate.AddMonths(i))+"' and '"+GetMonthLastDay(BeginDate.AddMonths(i))+"");
                            }

                        }

                    }

                }

                
else
                
{
                    
//Different Quarter
                    for(int j=0; j<=Convert.ToInt32(quarter[EndDate.Month - 1]) - Convert.ToInt32(quarter[BeginDate.Month - 1]); j++)
                    
{
                        
if(j==0)
                        
{
                               
//Seperate the first date period
                            this.dateobj.SeperateDateByQuarter.Add(" and OrderDate between '"+BeginDate.ToString("yyyy-MM-dd")+"' and '"+GetQuarterLastDay(BeginDate)+"");
                        }

                        
else if(j==EndDate.Month - BeginDate.Month)
                        
{
                                
//Seperate the last date period
                            this.dateobj.SeperateDateByQuarter.Add(" and OrderDate between '"+GetQuarterFirstDay(EndDate)+"' and '"+EndDate.ToString("yyyy-MM-dd")+"");
                        }

                        
else
                        
{
                                
//Seperate the middle date period
                            this.dateobj.SeperateDateByQuarter.Add(" and OrderDate between '"+GetQuarterFirstDay(BeginDate.AddMonths(3*- ((BeginDate.Month - 1% 3)))+"' and '"+GetQuarterLastDay(BeginDate.AddMonths(3*- ((BeginDate.Month - 1% 3)))+"");
                        }

                    }

                }

            }

            
else
            
{
                
//Different Year
                for(int k=0; k<=EndDate.Year - BeginDate.Year; k++)
                
{
                    
if(k==0)
                    
{
                            
//Seperate the first date period  --- Year
                        this.dateobj.SeperateDateByYear.Add(" and OrderDate between '"+BeginDate.ToString("yyyy-MM-dd")+"' and '"+GetYearLastDay(BeginDate)+"");
                        DateDiffObject newdateobj 
= new DateDiffObject();
                        
//Use itself --- Recursion Method
                        newdateobj = GetDateDiffObject(DateType,BeginDate,DateTime.Parse(GetYearLastDay(BeginDate)));
                        
for(int p=0; p<newdateobj.SeperateDateByQuarter.Count;p++)
                        
{
                            dateobj.SeperateDateByQuarter.Add(newdateobj.SeperateDateByQuarter[p]);
                        }

                        
for(int p=0; p<newdateobj.SeperateDateByMonth.Count;p++)
                        
{
                            dateobj.SeperateDateByMonth.Add(newdateobj.SeperateDateByMonth[p]);
                        }
                
                    }

                    
else if(k==EndDate.Year - BeginDate.Year)
                    
{
                            
//Seperate the last date period  --- Year
                        this.dateobj.SeperateDateByYear.Add(" and OrderDate between '"+GetYearFirstDay(EndDate)+"' and '"+EndDate.ToString("yyyy-MM-dd")+"");
                        DateDiffObject newdateobj 
= new DateDiffObject();
                        
//Use itself --- Recursion Method
                        newdateobj = GetDateDiffObject(DateType,DateTime.Parse(GetYearFirstDay(EndDate)),EndDate);
                        
for(int p=0; p<newdateobj.SeperateDateByQuarter.Count;p++)
                        
{
                            dateobj.SeperateDateByQuarter.Add(newdateobj.SeperateDateByQuarter[p]);
                        }

                        
for(int p=0; p<newdateobj.SeperateDateByMonth.Count;p++)
                        
{
                            dateobj.SeperateDateByMonth.Add(newdateobj.SeperateDateByMonth[p]);
                        }
        
                    }

                    
else
                    
{
                            
//Seperate the middle date period  --- Year
                        this.dateobj.SeperateDateByYear.Add(" and OrderDate between '"+GetYearFirstDay(BeginDate.AddYears(k))+"' and '"+GetYearLastDay(BeginDate.AddYears(k))+"");
                        DateDiffObject newdateobj 
= new DateDiffObject();
                        
//Use itself --- Recursion Method
                        newdateobj = GetDateDiffObject(DateType,DateTime.Parse(GetYearFirstDay(BeginDate.AddYears(k))),DateTime.Parse(GetYearLastDay(BeginDate.AddYears(k))));
                        
for(int p=0; p<newdateobj.SeperateDateByQuarter.Count;p++)
                        
{
                            dateobj.SeperateDateByQuarter.Add(newdateobj.SeperateDateByQuarter[p]);
                        }

                        
for(int p=0; p<newdateobj.SeperateDateByMonth.Count;p++)
                        
{
                            dateobj.SeperateDateByMonth.Add(newdateobj.SeperateDateByMonth[p]);
                        }
        
                    }

                }

            }

            
return dateobj;
        }

          以上方法是用递归算法来截取个时间段然后返回一个DateDiffObject的对象。 其实大家可以看出来填入对象中各个ArrayList的数据就是SQL语句的一段,作为我们查询数据库的条件。
          接下来就是我们在上面看到的例如GetMonthFirstDay(EndDate),GetMonthLastDay(BeginDate.AddMonths(i))等方法的实现,大家可以从方法名里看出它们将要实现的功能,就是获得每年、每季度、每月的第一天和最后一天:

public string GetMonthFirstDay(DateTime date)
        
{
            
return date.ToString("yyyy-MM-01");
        }


        
public string GetMonthLastDay(DateTime date)
        
{
            
return DateTime.Parse(date.ToString("yyyy-MM-01")).AddMonths(1).AddDays(-1).ToShortDateString();
        }


        
public string GetQuarterFirstDay(DateTime date)
        
{
            
return date.AddMonths(0 - ((date.Month - 1% 3)).ToString("yyyy-MM-01");
        }


        
public string GetQuarterLastDay(DateTime date)
        
{
            
return DateTime.Parse(date.AddMonths(3 - ((date.Month - 1% 3)).ToString("yyyy-MM-01")).AddDays(-1).ToShortDateString();
        }


        
public string GetYearFirstDay(DateTime date)
        
{
            
return DateTime.Parse(date.ToString("yyyy-01-01")).ToShortDateString();
        }


        
public string GetYearLastDay(DateTime date)
        
{
            
return DateTime.Parse(date.ToString("yyyy-01-01")).AddYears(1).AddDays(-1).ToShortDateString();
        }

       都是用DateTime类来实现的,原理很简单,每个月的第一天当然是****-**-01,最后一天就是下个月的第一天减去一天所得到的,季度和年份也是同理,大家有兴趣可以推敲一下,这里就不再赘述了。^^
       最后,就是调用它的时候了,我们先讲它序列化为一个XML文档,存放在一个特定目录下,我们这里用一个组件来管理它:
public class DateDiffObjectSerialize : iDateObjectSerialize
    
{
        
private string strPath = "./XMLDoc/"+HttpContext.Current.Request.Cookies["UserID"].Value + "/DateDiffObject.xml";
        
private DateDiffObject dateobj = new DateDiffObject();

        
public DateDiffObjectSerialize()
        
{

        }


        
public DateDiffObjectSerialize(string Path)
        
{
            
this.strPath = Path;
        }


        
public void SerializeDateObject(DateDiffObject dateobj)
        
{
            FileInfo fi 
= new FileInfo(strPath);
            
if(fi.Exists)
            
{
                fi.Delete();
            }

            XmlSerializer s 
= new XmlSerializer(typeof(DateDiffObject));
            Stream stream 
= new FileStream(HttpContext.Current.Server.MapPath(strPath),FileMode.Create);
            s.Serialize(stream, dateobj);
            stream.Close();
        }


        
public void SerializeDateObject(DateDiffObject dateobj,string FilePath)
        
{
            strPath 
= FilePath;

            FileInfo fi 
= new FileInfo(strPath);
            
if(fi.Exists)
            
{
                fi.Delete();
            }

            XmlSerializer s 
= new XmlSerializer(typeof(DateDiffObject));
            Stream stream 
= new FileStream(HttpContext.Current.Server.MapPath(strPath),FileMode.Create);
            s.Serialize(stream, dateobj);
            stream.Close();
        }


        
public DateDiffObject DeserializeDateObject()
        
{
            FileStream s 
= File.OpenRead(HttpContext.Current.Server.MapPath(strPath));
            XmlSerializer xs 
= new XmlSerializer(typeof(DateDiffObject));
            dateobj 
= (DateDiffObject)xs.Deserialize(s);
            s.Close();
            
return dateobj;
        }


        
public DateDiffObject DeserializeDateObject(string FilePath)
        
{
            strPath 
= FilePath;
            FileStream s 
= File.OpenRead(HttpContext.Current.Server.MapPath(strPath));
            XmlSerializer xs 
= new XmlSerializer(typeof(DateDiffObject));
            dateobj 
= (DateDiffObject)xs.Deserialize(s);
            s.Close();
            
return dateobj;
        }

    }

       要调用DateDiffObject时只是需要将它反序列化出来,按需提取里面的数据,然后组装到你查询语句中就行了。
      结束语:
      至于为什么要把它进行序列化,主要是我对方便使用的考量在里面,我就碰到这样的要求,不但要看报表,还要看相应的图片显示,年度、季度、月份的比较可以随时切换,当然你也可以不讲他序列化了,这个就见仁见智吧。
posted on 2007-03-17 14:20  DotNETer  阅读(465)  评论(0编辑  收藏  举报