【问题标题】:DateTime shift to next predefined dateDateTime 转移到下一个预定义日期
【发布时间】:2014-02-06 19:09:29
【问题描述】:

假设我有一个有效的日程安排日期列表。像:23、27、29

我想根据上面的列表将给定的日期修改为下一个有效的日月。

如果您给定的日期是“23/11/2013”​​,那么下一个有效日期将是“27/11/2013” 但如果您给定的日期是“30/11/2013”​​,它必须返回“23/12/2013” 如果给定的日期是“30/12/2013”​​,它必须返回“23/01/2014”

我已经在 SQL 中完成了该操作,但现在我将其转换为 C#,这有点棘手。 我正在尝试在 SQL 相似性列表中使用 LINQ 来完成此操作,但它会让人感到困惑。

SQL 语句是(是的,我知道它不会很快):

SELECT TOP 1 @DATE = ISNULL(DateAdd(yy, YEAR(@DATE)-1900, DateAdd(m,  (MONTH(@DATE)+CASE WHEN DATEPART(day,@DATE)>[DAY] THEN 1 ELSE 0 END) - 1, [DAY] - 1)),@DATE)
FROM @DAYS WHERE DateAdd(yy, YEAR(@DATE)-1900, DateAdd(m,  (MONTH(@DATE)+CASE WHEN DATEPART(day,@DATE)>[DAY] THEN 1 ELSE 0 END) - 1, [DAY] - 1))>=@DATE
ORDER BY [DAY]

@DAYS 是一张工作表。

【问题讨论】:

  • 你的 C# 和 LINQ 代码在哪里?
  • 调度是访问成本低(已经在内存变量中)还是成本高(SQL 查询)?如果它们便宜,迭代解决方案将是最简单的。
  • @Tarec 如果我给你它有什么乐趣? ;)
  • @david.pfx 这是一个列表 只包含白天部分。
  • @Sergio 您可以使用 LINQ 使这变得非常简单,请参阅我的回答 :)

标签: c# linq datetime


【解决方案1】:

我认为您正在寻找的是这样的东西(使用 LINQ):

    public static DateTime NextDate(DateTime seed, int[] days)
    {
        if (Enumerable.Range(1, 31).Intersect(days).Any())  //Check to stop a very long running lookup!
        {
            return Enumerable.Range(0, int.MaxValue)
                .Select(i => seed.AddDays(i))
                .First(d => days.Contains(d.Day));
        }

        return seed;
    }

用法:

var nextDate = NextDate(DateTime.Now, new[] { 23, 27, 29 });

【讨论】:

  • 这正是我想要的。谢谢奥利弗。
【解决方案2】:

我认为你需要这样的东西:

    public static DateTime GetNextValidDate(DateTime date)
    {
        var validDays = new List<short> { 23, 27, 29 };

        var nextDay = validDays.FirstOrDefault(n => n >= date.Day);

        if (nextDay != default(int))
        {
            // The next valid day is in the current month
            return date.AddDays(nextDay - date.Day);
        }
        // The next valid day is next month
        nextDay = validDays.Min();
        return new DateTime(date.Year, date.Month, nextDay, date.Hour, date.Minute, date.Second).AddMonths(1);
    }

我已经用几个值测试了这段代码,它工作正常:

        Console.WriteLine(GetNextValidDate(new DateTime(2014, 1, 20)));
        Console.WriteLine(GetNextValidDate(new DateTime(2014, 1, 24)));
        Console.WriteLine(GetNextValidDate(new DateTime(2014, 1, 30)));

有一个限制:如果第一个有效日期不超过 28 天,您可能会遇到 2 月的一些问题(4 月有 31 天等......)

【讨论】:

  • 这段代码是一个正确的解决方案(现在你已经修复了那个错误!)
  • 这很好。很抱歉,我更喜欢 Oliver 的只是因为我可以轻松地将它嵌入到内联中。这就是我正在做的事情。谢谢。
【解决方案3】:

以下不是 LINQ,但应该可以工作(随着年份的增加):

    private IList<int> days = new[] {23, 27, 29};

    public DateTime Next(DateTime current)
    {
        int i = days.IndexOf(current.Day);
        if(i<0) throw new ArgumentException("Wrong date");
        if(i<days.Count-1) return new DateTime(current.Year, current.Month, days[i+1]);
        current = current.AddMonths(1);
        return new DateTime(current.Year, current.Month, days[0]);
    }

【讨论】:

  • 不是一个有效的解决方案。使用 FirstOrDefault()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-05-05
  • 1970-01-01
  • 2021-12-06
相关资源
最近更新 更多