改变时间向前

时间:2018-08-30 22:07:23

标签: c# datetime timespan

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

例如,如果数据库中的日期为[7/6/2017 5:00:00 AM],并且给定的“固定时间”为10:00 PM,那么我想获取[7/6/2017 10:00: 00 PM]。

但是,如果固定时间为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 AM时,此操作未按预期工作。差异变为负数(不全天候),日期将为[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;

    }

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

非常感谢您。

3 个答案:

答案 0 :(得分:2)

在这种方法中,我使用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());

这是我的输出:

enter image description here


编辑:

基于注释建议的简化方法:

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);
}

答案 1 :(得分:1)

您的逻辑几乎是正确的,但是您不应该检查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

答案 2 :(得分: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作为返回值,因为date.Date将返回日期,时间设置为00:00,并且向其添加目标时间将已经设置目标小时,而无需计算差额。