改变时间向前

Change the time forward

我正在从数据库中获取日期,对于每个日期,我都想从从数据库中获取的 DateTime 开始向前更改时间,直到到达给定的固定时间 (Y)。但是,(Y) 可能会在第二天。

例如,如果数据库中的日期是 [7/6/2017 5:00:00 AM] 并且给定的固定时间是 10:00 PM 那么我想得到 [7/6/2017 10:00:00 点。

但是如果固定时间是 02:00 AM 那么我想得到 [7/7/2017 02:00:00 AM] (注意日期增加了一个)

注意:代码是 运行,但我修改了代码以使其更短且更有意义。因此,可能存在语法或拼写错误。

我的第一个解决方案是这样的:

    private DateTime setTimeForeward(DateTime date) {

        DateTime today = DateTime.ParseExact(FixedTime, "hh:mm tt", CultureInfo.InvariantCulture);

        TimeSpan difference = today.TimeOfDay - date.TimeOfDay;

        return date + difference;

    }

当固定时间是 02:00 上午时,这没有按预期工作。差异变为负数(它不会全天候运行)并且日期将是 [7/6/2017 02:00:00 AM]。

我得到了以下代码

   private DateTime setTimeForeward(DateTime date) {

        DateTime today = DateTime.ParseExact(FixedTime "hh:mm tt", CultureInfo.InvariantCulture);

        TimeSpan difference = today.TimeOfDay - date.TimeOfDay;

        if (difference.Hours < 0) {

            difference += new TimeSpan(24, 0, 0);

        }

        return date + difference;

    }

我不确定我的函数在逻辑上是否正确,我觉得我想多了。另外,我不确定是否有更好的方法或内置函数可以满足我的需求。基本上,我正在寻找一个正确而优雅的解决方案。

非常感谢你。

您的逻辑 几乎 是正确的,但您不应该检查 difference.Hours 因为可能会在几分钟内有所不同(如果您更改格式甚至几秒钟)稍后)。

我调整了你的函数并更改了一些变量名以使其更易于理解:

private DateTime SetTimeForward(DateTime originalDate)
{
    TimeSpan newTime = DateTime.ParseExact(FixedTime, 
                                           "hh:mm tt", 
                                           CultureInfo.InvariantCulture).TimeOfDay;
    TimeSpan diff = newTime - originalDate.TimeOfDay;

    if (diff.Ticks < 0)
        diff = diff.Add(new TimeSpan(24, 0, 0));

    return originalDate.Add(diff);
}

一些备注:

  • 如果您的 FixedTime 确实 固定的,您可能希望将其直接存储为 TimeSpan,这样您就不需要每次都要解析。

  • 如果你解析 FixedTime 因为它是可变的,你可以将它作为第二个参数传递:

    private DateTime SetTimeForward(DateTime originalDate, string fixedTime)
    

    或:

    private DateTime SetTimeForward(DateTime originalDate, TimeSpan newTime)
    
  • 当前的实现 不会 如果 newTime 等于 originalDate.TimeOfDay。即,如果 originalDate7/6/2017 2:00 AM 并且 FixedTime/newTime02:00 AM,则返回的日期将等于 originalDate。如果这不是您想要的行为,您可以将 diff.Ticks < 0 更改为 diff.Ticks <= 0

在这个方法中,我使用 DateTime fixedTime 来表示时间。我真的不关心它的 Day, Month, and Year 值。

static DateTime GetClosingTime(DateTime fixedTime, DateTime dbTime)
{
    var cutoff = new DateTime(dbTime.Year, dbTime.Month, dbTime.Day, fixedTime.Hour, fixedTime.Minute, fixedTime.Second);
    if (dbTime < cutoff)
        return cutoff;
    else
    {
        cutoff = cutoff.AddDays(1);
        return cutoff;
    }
}

这里使用您提供的示例输入来调用它。

var FixedTime10PM = new DateTime(1, 1, 1, 22, 0, 0);
var FixedTime02AM = new DateTime(1, 1, 1, 2, 0, 0);

var dbTime = new DateTime(2018, 6, 20, 5, 0, 0);

var dt1 = GetClosingTime(FixedTime10PM, dbTime);
var dt2 = GetClosingTime(FixedTime02AM, dbTime);

Console.WriteLine(dt1.ToLongDateString() + " " + dt1.ToLongTimeString());
Console.WriteLine(dt2.ToLongDateString() + " " + dt2.ToLongTimeString());

这是我的输出:


编辑:

根据评论中的建议简化的方法:

static DateTime GetClosingTime(DateTime fixedTime, DateTime dbTime)
{
    var cutoff = new DateTime(dbTime.Year, dbTime.Month, dbTime.Day, fixedTime.Hour, fixedTime.Minute, fixedTime.Second);
    return dbTime < cutoff ? cutoff : cutoff.AddDays(1);
}

方法略有不同:

private DateTime setTimeForeward(DateTime date)
{
    var targetTimeOfDay = TimeSpan.ParseExact(FixedTime, "hh:mm tt", CultureInfo.InvariantCulture);

    if (targetTimeOfDay < date.TimeOfDay)
    {
        date = date.AddDays(1);
    }

    return date.Date + targetTimeOfDay;
}

我从一开始就将目标时间设置为 TimeSpan,而不是创建 DateTime 并获取 TimeOfDay(即 TimeSpan)。 然后我检查一天中的目标时间是否低于要修改的时间,如果是我添加一天。 我使用 date.Date + targetTimeOfDay 作为 return 值,因为 date.Date 将 return 日期设置为 00:00 并向其添加目标时间将已经设置目标小时而不计算区别。