c# 划份时间段之一 (按自然月)

最近做项目中,发现这两个方法非常不错,记下来。以备后用
  /// <summary>
/// //按自然月计算应收日期
/// </summary>
public partial class WYTableFunction
{

public enum enumPeroiod
{
NotSplit=0,//不分隔,起始与截止整个是一周期。
First=1,//只取第一期
AllPeroid=2//取所有周期。
}
//如果有应收日,那就以合同的应收日为准,否刚就为应收日期就为自然月最后一天
/// <summary>
/// 计算应收日期及所属期
/// CybleBeginDate:周期实际的起始日
/// CybleEndDate:周期实际的结束日。
/// </summary>
/// <param name="UnitType">周期单位</param>
/// <param name="Cycle">周期</param>
/// <param name="sBeginDate">起始日期</param>
/// <param name="sEndDate">截止日期</param>
/// <param name="ExesType">应收类别,1代表提前,2代表本期,3代表延后</param>
/// <param name="ExesMonth">指定月份,0代表本期</param>
/// <param name="AccDate">指定应收天数,0代表每期最后一天</param>
/// <returns></returns>
[SqlFunction(TableDefinition = @" BeginDate DateTime,EndDate DateTime,GatheringDate DateTime,CybleBeginDate DateTime,CycleEndDate DateTime", FillRowMethodName = "FillRow2")]
public static IEnumerable CW_F_CalDateTable_CLR(int UnitType, int Cycle, string sBeginDate,
string sEndDate, int ExesType, int ExesMonth, int AccDate, int iEnumPeroiod,bool ReturnDataRow)
{
enumPeroiod Peroid = (enumPeroiod)iEnumPeroiod;
DateTime BeginDate = Convert.ToDateTime(sBeginDate);
DateTime EndDate = Convert.ToDateTime(sEndDate);

DateTime AccountDate = DateTime.MinValue;

List<DateTime[]> rowList = new List<DateTime[]>();

DateTime dtBegin = BeginDate, dtEnd = DateTime.MinValue;
DateTime dtCybleBeginDate = new DateTime(dtBegin.Year, dtBegin.Month, 1), dtCycleEndDate = EndDate;

//Globe.SendString(string.Format("生成周期,从{0}至{1}",BeginDate,EndDate));

switch (UnitType)
{
#region 年交
case 1://年

while (dtBegin <= EndDate)
{
if (Peroid == enumPeroiod.NotSplit)
{
dtEnd = EndDate;
}
else
{
/*2011-6-14,首期,是算到当前期间的最后一天,之后才是加一个周期*/
if (dtEnd == DateTime.MinValue)
dtEnd = new DateTime(dtBegin.Year, 12, 31).AddYears(Cycle - 1);//按自然月,则首期,加上周期减1(有可能是每2年或每3年)
else
dtEnd = new DateTime(dtEnd.Year, 12, 31).AddYears(Cycle);
}

dtCycleEndDate = dtEnd;
dtCybleBeginDate = dtEnd.AddDays(1).AddYears(-Cycle);//例:2011-12-31,变2012-1-1,再减1年(设Cycle为1)

if (dtEnd > EndDate)
dtEnd = EndDate;


AccountDate = CalAccountDate(dtBegin, dtEnd, ExesType, ExesMonth, AccDate);



rowList.Add(new DateTime[] { dtBegin, dtEnd, AccountDate,dtCybleBeginDate, dtCycleEndDate });
if (Peroid!=enumPeroiod.AllPeroid) break;
dtBegin = dtEnd.AddDays(1);
}

break;
#endregion

#region 季交
case 2://季
while (dtBegin <= EndDate)
{
if (Peroid == enumPeroiod.NotSplit)
{
dtEnd = EndDate;
}
else
{
if (dtEnd == DateTime.MinValue)
dtEnd = new DateTime(dtBegin.Year, dtBegin.Month, 1).AddMonths((Cycle - 1) * 3);
else
dtEnd = new DateTime(dtEnd.Year, dtEnd.Month, 1).AddMonths(Cycle * 3);

switch (dtEnd.Month)
{
case 1:
case 2:
case 3:
dtEnd = new DateTime(dtEnd.Year, 3, 31);
break;
case 4:
case 5:
case 6:
dtEnd = new DateTime(dtEnd.Year, 6, 30);
break;
case 7:
case 8:
case 9:
dtEnd = new DateTime(dtEnd.Year, 9, 30);
break;
case 10:
case 11:
case 12:
dtEnd = new DateTime(dtEnd.Year, 12, 31);
break;
}
}
dtCycleEndDate = dtEnd;
dtCybleBeginDate = dtEnd.AddDays(1).AddMonths(-(Cycle * 3));//倒退到起始日。例:结束日期是2011-3-31,则先变为2011-4-1,再减一季(3个月),则变为2011-1-1

if (dtEnd > EndDate)
dtEnd = EndDate;

AccountDate = CalAccountDate(dtBegin, dtEnd, ExesType, ExesMonth, AccDate);


rowList.Add(new DateTime[] { dtBegin, dtEnd, AccountDate, dtCybleBeginDate, dtCycleEndDate });
if (Peroid != enumPeroiod.AllPeroid) break;
dtBegin = dtEnd.AddDays(1);
}
break;
#endregion

#region 月交
case 3://月
while (dtBegin <= EndDate)
{
if (Peroid == enumPeroiod.NotSplit)
{
dtEnd = EndDate;
}
else
{
if (dtEnd == DateTime.MinValue)
dtEnd = new DateTime(dtBegin.Year, dtBegin.Month, 1).AddMonths(Cycle).AddDays(-1);//本
else
dtEnd = new DateTime(dtEnd.Year, dtEnd.Month, 1).AddMonths(Cycle + 1).AddDays(-1);//注意:这个dtEnd,每次都是上一周期所在月的最后一天,所以取当月,加上周期Cycle加1,得到后月(设Cycle=1)第1天,再减1天。
}
dtCycleEndDate = dtEnd;
dtCybleBeginDate = new DateTime(dtCycleEndDate.Year, dtCycleEndDate.Month, 1);

if (dtEnd > EndDate)
dtEnd = EndDate;


//Globe.SendString(string.Format("计算自然月时:起始{0:yyyy-MM-dd},结束{1:yyyy-MM-dd},周期:{2}", dtBegin,dtEnd,Cycle));

AccountDate = CalAccountDate(dtBegin, dtEnd, ExesType, ExesMonth, AccDate);

//Globe.SendString(string.Format("计算应收日:ExesType={0},ExesMonth={1},AccDate={2},AccountDate={3:yyyy-MM-dd}", ExesType, ExesMonth, AccDate, AccountDate));

rowList.Add(new DateTime[] { dtBegin, dtEnd, AccountDate, dtCybleBeginDate, dtCycleEndDate });
if (Peroid != enumPeroiod.AllPeroid) break;
dtBegin = dtEnd.AddDays(1);
}

break;
#endregion

#region 周交
case 4://周

while (dtBegin <= EndDate)
{
/*2011-6-15,这里有些问题没有按星期来计周。以后再改,ljh*/
if (Peroid == enumPeroiod.NotSplit)
{
dtEnd = EndDate;
}
else
{
dtEnd = dtBegin.AddDays(Cycle * 7);
}
dtCycleEndDate = dtEnd.AddDays(-1);
dtCybleBeginDate = dtCycleEndDate.AddDays(-7 * Cycle);

if (dtEnd > EndDate)
dtEnd = EndDate;
else
dtEnd = dtEnd.AddDays(-1);

AccountDate = CalAccountDate(dtBegin, dtEnd, ExesType, ExesMonth, AccDate);

rowList.Add(new DateTime[] { dtBegin, dtEnd, AccountDate, dtCybleBeginDate, dtCycleEndDate });
if (Peroid != enumPeroiod.AllPeroid) break;
dtBegin = dtEnd.AddDays(1);
}

break;
#endregion

#region 日交
case 5://日
while (dtBegin <= EndDate)
{
dtEnd = dtBegin.AddDays(Cycle);

if (dtEnd > EndDate)
dtEnd = EndDate;
else
dtEnd = dtEnd.AddDays(-1);

dtCycleEndDate = dtBegin;
dtCybleBeginDate = dtBegin;


AccountDate = CalAccountDate(dtBegin, dtEnd, ExesType, ExesMonth, AccDate);

rowList.Add(new DateTime[] { dtBegin, dtEnd, AccountDate, dtCybleBeginDate, dtCycleEndDate });
if (Peroid != enumPeroiod.AllPeroid) break;
dtBegin = dtEnd.AddDays(1);
}

break;
#endregion

#region 其他
case 6:
{
dtEnd = EndDate;
dtCycleEndDate = dtEnd;
dtCybleBeginDate = dtBegin;

AccountDate = CalAccountDate(dtBegin, dtEnd, ExesType, ExesMonth, AccDate);


rowList.Add(new DateTime[] { BeginDate, EndDate, AccountDate, dtCybleBeginDate, dtCycleEndDate });
if (Peroid != enumPeroiod.AllPeroid) break;
}

break;
#endregion
}
DataTable dt=new DataTable();
dt.Columns.Add("BeginDate",typeof(DateTime));
dt.Columns.Add("EndDate",typeof(DateTime));
dt.Columns.Add("GatheringDate",typeof(DateTime));
dt.Columns.Add("CycleBeginDate", typeof(DateTime));
dt.Columns.Add("CycleEndDate", typeof(DateTime));

for (int i = 0; i < rowList.Count; i++)
{
DataRow row = dt.NewRow();
row["BeginDate"] = rowList[i][0];
row["EndDate"] = rowList[i][1];
row["GatheringDate"] = rowList[i][2];
row["CycleBeginDate"] = rowList[i][3];
row["CycleEndDate"] = rowList[i][4];
dt.Rows.Add(row);
}

if (ReturnDataRow==true)
return dt.Rows as IEnumerable;
else
return rowList as IEnumerable;
//返回一个string 数组,这个数组符合IEnumerable接口,当然你也可以返回hashtable等类型。

//return (IEnumerable)dt.Rows.GetEnumerator();
}
private static DateTime CalAccountDate(DateTime dtBegin,DateTime dtEnd, int DelayType,int DelayMonth, int DelayDay)
{
DateTime dtAccount = dtEnd;
//Globe.SendString(string.Format("\r\n************{0},{1},{2}", DelayType, DelayMonth, DelayDay));
switch (DelayType)
{

case 1://提前提前N个月
dtAccount = new DateTime(dtBegin.Year, dtBegin.Month, 1);
dtAccount = dtAccount.AddMonths(-DelayMonth);

break;
case 3://延后
dtAccount = new DateTime(dtEnd.Year, dtEnd.Month, 1);
dtAccount = dtAccount.AddMonths(DelayMonth);

break;
case 4://指定月份
if (DelayMonth<1 || DelayMonth>12)
dtAccount = new DateTime(dtEnd.Year, dtEnd.Month, 1);
else
dtAccount = new DateTime(dtEnd.Year, DelayMonth, 1);
break;
case 2://本期
default:
dtAccount = new DateTime(dtEnd.Year, dtEnd.Month, 1);
break;
}
DateTime dtMonthLast=new DateTime(dtAccount.Year, dtAccount.Month, 1).AddMonths(1).AddDays(-1);
int MonthDays = dtMonthLast.Day;//应收所在月份的天数。

if (DelayDay <= 0 || DelayDay > MonthDays)
dtAccount = dtMonthLast;
else
dtAccount = new DateTime(dtAccount.Year, dtAccount.Month, DelayDay);
return dtAccount;
}
}



测试

select * from CW_F_CalDateTable_CLR(3,1,'2013-01-15','2014-01-14',3,1,15,2,0)

运行结果

[img]http://dl2.iteye.com/upload/attachment/0089/9667/3c2745ed-302b-3b3e-bef1-0a6103148fe5.jpg[/img]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值