Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中计算重复日期的正确方法#_C#_Datetime_Timezone - Fatal编程技术网

C# C语言中计算重复日期的正确方法#

C# C语言中计算重复日期的正确方法#,c#,datetime,timezone,C#,Datetime,Timezone,在我的项目中,我需要计算重复事件的日期。在开始时,我只知道开始日期/时间以及该事件必须如何重复的信息: Every Day Every Week Every 2 Weeks Every 3 Weeks Every Month Every 2 Months ... 正确的方法是什么?它应该在不同的时区和省时设置下正常工作。我想我应该在本地日期时间中加上天/周/月,然后将其转换为UTC。但我对此不确定。如果我加上几天,这将是我们需要将时钟向前调整一小时的时间,会发生什么。在这种情况下,这个时间将不

在我的项目中,我需要计算重复事件的日期。在开始时,我只知道开始日期/时间以及该事件必须如何重复的信息:

Every Day
Every Week
Every 2 Weeks
Every 3 Weeks
Every Month
Every 2 Months
...
正确的方法是什么?它应该在不同的时区和省时设置下正常工作。我想我应该在本地日期时间中加上天/周/月,然后将其转换为UTC。但我对此不确定。如果我加上几天,这将是我们需要将时钟向前调整一小时的时间,会发生什么。在这种情况下,这个时间将不存在

下面是我编写的代码,但我不确定它是否在所有情况下都能正常工作:

private static List<DateTime> FindOccurrences(DateTime localStart, Repeat repeat, int occurrences)
{
    var result = new List<DateTime> { localStart };
    switch (repeat)
    {
        case Repeat.Daily:
            for (int i = 1; i <= occurrences; i++)
                result.Add(localStart.AddDays(i));
            break;
        case Repeat.Every2Weeks:
            for (int i = 1; i <= occurrences; i++)
                result.Add(localStart.AddDays((7 * 2) * i));
            break;
        ...
    }
    return result;
}

public List<Event> CreateRepeating(string timeZone, Repeat repeat, int repeatEnds, DateTime localStart, int eventDuration)
{
    var events = new List<Event>();
    var occurrences = FindOccurrences(localStart, repeat, repeatEnds);
    foreach (var occurrence in occurrences)
    {
        var item = new Event();
        item.Start = occurrence.ToUtcTime(timeZone);
        item.End = occurrence.ToUtcTime(timeZone).AddMinutes(eventDuration);
        events.Add(item);
    }
    return events;
}
private静态列表FindOccurrences(DateTime localStart、Repeat Repeat、int引用)
{
var result=新列表{localStart};
开关(重复)
{
病例重复。每日:

对于(inti=1;i部分答案,我宁愿将实现更改为

  public enum TimePeriod {
    None = 0,
    Day = 1,
    // Just week, no "two weeks, three weeks etc."  
    Week = 2,
    Month = 3
  }

  public static class Occurrencies {
    // May be you want to convert it to method extension: "this DateTime from" 
    public static IEnumerable<DateTime> FindInterval(DateTime from,
                                                     TimePeriod period, 
                                                     int count) {
      while (true) {
        switch (period) {
          case TimePeriod.Day:
            from = from.AddDays(count); 

            break;  
          case TimePeriod.Week:
            from = from.AddDays(7 * count);    

            break;
          case TimePeriod.Month:
            from = from.AddMonths(count);    

            break;  
        } 

        yield return from;
      }
    }
  }
公共枚举时间段{
无=0,
天=1,
//只有一周,没有“两周,三周等等”
周=2,
月份=3
}
公共静态类发生率{
//您可能希望将其转换为方法扩展:“this DateTime from”
公共静态IEnumerable FindInterval(日期时间从,
时间段,
整数计数){
while(true){
转换(周期){
案例时间段。天:
from=from.AddDays(计数);
打破
案例时间段。周:
from=from.AddDays(7*计数);
打破
案例时间段。月份:
from=from.AddMonths(计数);
打破
} 
收益率;
}
}
}
使用:

//每隔两周获得5次
列表间隔2周=发生率
.FindInterval(DateTime.Now,TimePeriod.Week,2)
.采取(5)
.ToList();
//获得11个3个月的间隔
列表间隔3个月=发生率
.FindInterval(DateTime.Now,TimePeriod.Month,3)
.Take(11)
.ToList();

安排或计算未来事件的日期,特别是重复发生的事件,是一个非常复杂的主题。我已经写过几次了,不过是从其他语言的角度(请参见:,,)

恐怕这一主题太宽泛,无法提供您要运行的确切代码。详细信息将针对您的应用程序而定。但这里有一些提示

一般而言:

  • 仅在单个事件发生的预计时间内使用UTC

  • 以本地时间存储实际事件。还存储时区id

  • 不要存储时区偏移。应分别查找每个事件的时区偏移

  • 将即将发生的事件预测为UTC,以便您知道如何根据事件(或对您的场景有意义的任何事件)执行操作

  • 在夏时制期间,当某个事件发生前跳时差或后跳时差重叠时,决定要做什么。您的需求可能会有所不同,但通常的策略是跳到前跳时差,然后选择秋季的第一个事件。如果您不确定我的意思,请参阅

  • 仔细考虑如何处理接近月底的日期。并非所有月份都有相同的天数,日历数学很难。
    dt.AddMonths(1)。AddMonths(1)
    不一定与
    dt.AddMonths(2)
    相同

  • 随时掌握时区数据更新。没有人能预测未来,世界各国政府都喜欢改变现状

  • 您需要保留计划的原始本地时间值,以便可以重新投影事件的UTC值。您应该定期执行此操作,或者在应用时区更新时执行此操作(如果手动跟踪)。提供了有关不同时区数据库及其更新方式的详细信息

  • 考虑使用和时区。与Microsoft提供的内置类型和时区相比,它们更适合此类工作

  • 小心避免使用本地时区。您不应该调用
    日期时间。现在
    本地时间
    、或
    本地时间
    。请记住,本地时区基于运行代码的机器,这不应该影响代码的行为。请阅读中的详细信息

  • 如果你做所有这些只是为了开始一个计划的工作,你可能应该看看一个预先封装的解决方案,例如。它是免费的,开源的,功能强大的,并且涵盖了很多你可能没有想到的边缘案例

看看-它考虑了日期和时区固有的许多挑战。
  // Get 5 2-week intervals 
  List<DateTime> intervals2Weeks = Occurrencies
    .FindInterval(DateTime.Now, TimePeriod.Week, 2)
    .Take(5)
    .ToList();

  // Get 11 3-month intervals 
  List<DateTime> intervals3Months = Occurrencies
    .FindInterval(DateTime.Now, TimePeriod.Month, 3)
    .Take(11)
    .ToList();