您好我正在尝试创建一个功能,其中用户添加将在中心间隔重复的项目。但是我在数学方面遇到了一些问题,所以我希望你们中的一些人之前做过类似的事情。
它基于Google日历,可以通过4种不同的方法重复事件。
然后用户然后定义用户想要的重复类型,每天都很简单,它只是每一天。 现在每周更棘手,因为用户可以选择2个选项
每月和每年只有1个选项
除了这些数据,我还有以下变量。
所以我不必显示未来的项目,是计划循环NextRun现在所有的项目,并且在项目执行之后将计算NextRun。 我已经尝试过了,但它似乎变得过于复杂,所以我希望那里有一个已经完成的解决方案,或者一个接近,或者只是一个提示让它走上正轨。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 结果,这已经过测试和工作 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Itenso.TimePeriod;
namespace ShoppingList.Library.Objects
{
public class RepeatingItem
{
public int? Id { get; set; }
public int ListId { get; set; }
public string Item { get; set; }
public int Quantity { get; set; }
public RepeatsType Repeats { get; set; }
public string RepeatsVar { get; set; }
public TimeSpan Time { get; set; }
public DateTime StartsOn { get; set; }
public EndsType Ends { get; set; }
public string EndsVar { get; set; }
public int Occurrences { get; set; }
public DateTime? LastRun { get; set; }
public DateTime? NextRun { get; set; }
public enum RepeatsType
{
Daily = 0,
Weekly = 1,
Monthly = 2,
Yearly = 3,
}
public enum EndsType
{
Never = 0,
After = 1,
On = 2
}
public DateTime? CalculateNextRun()
{
DateTime? next = null;
if (Repeats == RepeatsType.Daily)
next = HandelDailyRepeating();
else if (Repeats == RepeatsType.Weekly)
next = HandelWeeklyRepeating();
else if (Repeats == RepeatsType.Monthly)
next = HandelMonthlyRepeating();
else if (Repeats == RepeatsType.Yearly)
next = HandelYearlyRepeating();
if (Ends != EndsType.Never && next != null)
{
if (Ends == EndsType.After)
{
if (Occurrences >= int.Parse(EndsVar))
next = null;
}
else if (Ends == EndsType.On)
{
if (next >= DateTime.Parse(EndsVar))
next = null;
}
}
return next;
}
private DateTime? HandelDailyRepeating()
{
DateTime last;
// If there where a last run no problem.
// but we are not sure that the time on
// start on are right.
if (LastRun != null)
last = GetDateTime((DateTime)LastRun, Time);
else
last = GetDateTime(StartsOn, Time);
DateTime next;
while (last < DateTime.UtcNow || last == LastRun)
{
last = last.AddDays(1);
}
return last;
}
private DateTime? HandelWeeklyRepeating()
{
DateTime last;
// If there where a last run no problem.
// but we are not sure that the time on
// start on are right.
if (LastRun != null)
last = GetDateTime((DateTime)LastRun, Time);
else
last = GetDateTime(StartsOn, Time);
string[] split = RepeatsVar.Split(';');
int recuringInterval = int.Parse(split[0]);
if (recuringInterval > 52)
recuringInterval = 52;
DayOfWeek[] weekDays = new DayOfWeek[split.Count() - 1];
for (int i = 1; i < split.Count(); i++)
{
weekDays[i-1] = (DayOfWeek)int.Parse(split[i]);
}
int days = 0;
bool validFound = false;
while (!validFound && days <= (7 * (recuringInterval + 1)))
{
if (last >= DateTime.UtcNow && IsWeekRecuringDay(StartsOn, last, recuringInterval, weekDays)
&& last != LastRun)
{
return last;
}
else
{
last = last.AddDays(1);
if(last > DateTime.UtcNow) days++;
}
}
return null;
}
private DateTime? HandelMonthlyRepeating()
{
DateTime last;
if (LastRun != null)
last = GetDateTime((DateTime)LastRun, Time);
else
last = GetDateTime(StartsOn, Time);
int recuringInterval = int.Parse(RepeatsVar);
int c = 0;
bool validFound = false;
while (!validFound && c <= (recuringInterval + 1))
{
if (last >= DateTime.UtcNow && IsMonthlyRecuringDay(StartsOn, last, recuringInterval)
&& last != LastRun)
{
return last;
}
else
{
last = last.AddMonths(1);
if (last > DateTime.UtcNow) c++;
}
}
return null;
}
private DateTime? HandelYearlyRepeating()
{
DateTime last;
// If there where a last run no problem.
// but we are not sure that the time on
// start on are right.
if (LastRun != null)
last = GetDateTime((DateTime)LastRun, Time);
else
last = GetDateTime(StartsOn, Time);
int recuringInterval = int.Parse(RepeatsVar);
int c = 0;
bool validFound = false;
while (!validFound && c <= (recuringInterval + 1))
{
if (last >= DateTime.UtcNow && IsYearlyRecuringDay(StartsOn, last, recuringInterval)
&& last != LastRun)
{
return last;
}
else
{
last = last.AddYears(1);
if (last > DateTime.UtcNow) c++;
}
}
return null;
}
public bool IsWeekRecuringDay(DateTime start, DateTime test, int recuringInterval, params DayOfWeek[] weekDays)
{
if (test < start || recuringInterval <= 0)
return false;
bool isValidDayOfWeek = false;
DayOfWeek testDayOfWeek = test.DayOfWeek;
// Is the given day a valid day
foreach (DayOfWeek weekDay in weekDays)
{
if (weekDay == testDayOfWeek)
{
isValidDayOfWeek = true;
break;
}
}
// If the day is not in the list, no need to go further
if (!isValidDayOfWeek)
return false;
DateDiff dateDiff = new DateDiff(GetDateTime(start, new TimeSpan(0, 0, 0)), GetDateTime(test, new TimeSpan(0, 0, 0)));
return (dateDiff.Weeks % recuringInterval) == 0;
}
public bool IsMonthlyRecuringDay(DateTime start, DateTime test, int recuringInterval)
{
if (test < start || recuringInterval <= 0)
return false;
DateDiff dateDiff = new DateDiff(GetDateTime(start, new TimeSpan(0, 0, 0)), GetDateTime(test, new TimeSpan(0, 0, 0)));
return (dateDiff.Months % recuringInterval) == 0;
}
public bool IsYearlyRecuringDay(DateTime start, DateTime test, int recuringInterval)
{
if (test < start || recuringInterval <= 0)
return false;
DateDiff dateDiff = new DateDiff(GetDateTime(start, new TimeSpan(0, 0, 0)), GetDateTime(test, new TimeSpan(0, 0, 0)));
return (dateDiff.Years % recuringInterval) == 0;
}
private DateTime GetDateTime(DateTime d, TimeSpan t)
{
return new DateTime(d.Year, d.Month, d.Day, t.Hours, t.Minutes, t.Seconds); ;
}
private TimeSpan GetTimeSpanFromDateTime(DateTime s)
{
DateTime zero = new DateTime(s.Year, s.Month, s.Day, 0, 0, 0);
return s - zero;
}
}
}
答案 0 :(得分:2)
一种方法是检查测试和开始日期之间的周差异。
以下示例使用Time Period Library for .NET的 DateDiff 类来计算周差异:
// ----------------------------------------------------------------------
public bool IsWeekRecuringDay( DateTime start, DateTime test, int recuringInterval, params DayOfWeek[] weekDays )
{
if ( test < start || recuringInterval <= 0 )
{
return false;
}
bool isValidDayOfWeek = false;
DayOfWeek testDayOfWeek = test.DayOfWeek;
foreach ( DayOfWeek weekDay in weekDays )
{
if ( weekDay == testDayOfWeek )
{
isValidDayOfWeek = true;
break;
}
}
if ( !isValidDayOfWeek )
{
return false;
}
DateDiff dateDiff = new DateDiff( start, test );
return ( dateDiff.Weeks % recuringInterval ) == 0;
} // IsWeekRecuringDay
这里的用法:
// ----------------------------------------------------------------------
public void WeekRepeatSample()
{
DateTime start = new DateTime( 2011, 06, 1 );
DayOfWeek[] weekDays = new DayOfWeek[] { DayOfWeek.Monday, DayOfWeek.Thursday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday };
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 06, 08 ), 2, weekDays ) ); // false
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 06, 11 ), 2, weekDays ) ); // false
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 06, 15 ), 2, weekDays ) ); // true
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 06, 18 ), 2, weekDays ) ); // false
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 06, 22 ), 2, weekDays ) ); // false
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 06, 25 ), 2, weekDays ) ); // false
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 06, 29 ), 2, weekDays ) ); // true
Console.WriteLine( "IsWeekRecuringDay: {0}", IsWeekRecuringDay( start, new DateTime( 2011, 07, 02 ), 2, weekDays ) ); // false
} // WeekRepeatSample
答案 1 :(得分:0)
您可以使用Quartz.Net作为您的计划引擎。它非常强大,可以满足您的所有日程安排需求。它支持以后在实现自己的调度程序时可能遇到的各种事情,例如例外日(假日,停电日等)。