Bonjour Je suis un essayant de créer une fonctionnalité où un utilisateur ajoute un élément qui sera répété sur les intervalles du centre. Mais j'ai quelques problèmes à résoudre les maths, alors j'espérais que certains d'entre vous aient déjà fait quelque chose comme ça.Calendrier avec des éléments répétitifs
Il est basé sur le calendrier Google, où un événement peut être répété par 4 méthodes différentes.
- Daily
- Hebdomadaire
- Mensuel
- annuel
Ensuite, l'utilisateur définit alors quel type de répéter l'utilisateur veut, tous les jours sont simples, il est juste chaque jour. Maintenant hebdomadaire est plus délicate, car l'utilisateur peut choisir 2 options
- intervalle de semaine (Répète toutes les deux semaines, ou troisième et ainsi de suite)
- Quel jour de la semaine (lundi, jeudi et ainsi de suite)
mensuels et annuels seulement ont 1 'option
- intervalle de mois/année
A côté de ces données, j'ai les variables suivantes.
- temps (Le temps du jour l'article sont à ajouter)
- StartsOn (Le jour répéter démarrer le schiste objet)
- Présence (Le nombre de fois que l'article a été exécuté)
- lastrun (la dernière fois que l'article a été exécuté)
- NextRun (la prochaine fois que l'article est à exécuter)
Je n'ai pas à afficher les éléments futurs, est lAPL n pour boucler si tous les éléments où le NextRun est égal à maintenant, et après que l'article a été exécuté sera le NextRun être calculé. Je me suis essayé, mais il semble devenir trop complexe, alors j'espérais qu'il y avait une solution déjà terminée, ou une solution proche, ou simplement un indice pour la mettre en place.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Le résultat, cela a été testé et fonctionne !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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;
}
}
}
semble fonctionner très bien, l'idée est alors d'ajouter un jour à un DateTime jusqu'à ce que je frappe un vrai retour de la méthode à droite? Et la même méthode pourrait être utilisée pendant des mois et des années. Est-ce que je comprends bien? – Androme
Non, il est le calcul de la différence de jours en utilisant 'DateTime.Subtract', compte tenu du début de la semaine du calendrier. Oui, vous pouvez utiliser la même approche pendant des mois et des années. – Jani
Oui je sais, je juste où la pensée du code Application de l'en mon problème – Androme