你好我是一个试图建立一个功能,用户一加一将在中心的时间间隔重复的项目。但是我在数学方面遇到了一些问题,所以我希望你们中的一些人之前做过类似的事情。日历与重复的项目
它是基于谷歌日历,其中,事件可通过4种不同的方法重复。
- 日报
- 周刊
- 每月
- 年
然后用户再定义什么类型的重复用户的希望,每天很简单,它只是每一天。 现在每周更加棘手,因为用户可以选择2个选项
- 周的时间间隔(重复每隔一周或第三等)
- 一周何日(星期一,四等)
每月和每年只有1个选项
- 月/年间隔
除此数据外,我还有以下变量。
- 时间(该项目被添加天的时间)
- StartsOn(项目页岩开始重复的那一天)
- 发生
- (次项已执行的次数) LASTRUN(上次该项目已执行)
- NextRun(要执行的下一次产品)
所以我没有显示未来项目,是解放军n循环所有NextRun与现在相同的项目,并且在项目执行后,将计算NextRun。 我曾尝试自己,但它似乎变得过于复杂,所以我希望能在那里有一个已经完成的解决方案在那里,或者一个接近,或者干脆只是表示正轨。
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 结果,这已经过测试并workes !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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;
}
}
}
似乎工作正常,然后将一天添加到DateTime,直到我点击从方法的真正回报吧?同样的方法可以使用数月和数年。我是否理解正确? – Androme 2011-06-14 11:18:58
不,它考虑日历的一周开始时使用'DateTime.Subtract'来计算天数的差异。 是的,您可以使用相同的方法数月和数年。 – Jani 2011-06-14 11:37:16
是的,我知道,我只想到这个代码的实现到我的问题 – Androme 2011-06-14 11:44:59