【问题标题】:With a percentage, how do I get the time between two datetimes?使用百分比,我如何获得两个日期时间之间的时间?
【发布时间】:2019-08-26 18:58:42
【问题描述】:

我认为描述这一点的最佳方式是使用示例。范围在上午 4:00 到下午 4:00 之间。在 0% 时,我想找回 4:00am。在 100% 的情况下,我想找回 4:00pm。在 50% 时,我想找回 10:00am

问题是,如何通过此签名获得此功能?

string GetTime(percentage, startTime, endTime)

【问题讨论】:

  • startTimeendTime 的类型是 DateTime 还是 string
  • @phuzi 日期时间
  • 如果 startTime 和 endTime 是DateTimes,那么你可以减去它们得到一个TimeSpan。从TimeSpan,您可以获得Ticks 属性。将其转换为double,乘以您的百分比,将结果转换回long。用它来构造一个新的TimeSpan。最后将新的 TimeSpan 添加到原始 startTime 并将其返回为 DateTime
  • 如果这些是 DateTime.Kind == DateTimeKind.Utc,那么当然 - 只需减去它们。但如果它们是其他任何东西,请小心,因为在减去 DateTime 值时,NOT 会考虑时区转换,例如夏令时和标准时间的变化。根据您的用例,您最好从 DateTimeOffset 值开始。
  • @MattJohnson 好点。对于这个问题,我想忽略 DST 的概念,并假装它不存在。

标签: c# datetime


【解决方案1】:

假设两个 DateTime 都在同一个时区,并且没有转换(DST 开始/结束、本地时间更改等):

public static void Main()
{
    var startTime = new DateTime(2019, 01, 01, 4, 0, 0);
    var endTime = new DateTime(2019, 01, 01, 16, 0 , 0);

    // prints 10:00 AM
    Console.WriteLine(GetTime(0.5, startTime, endTime));
}

private static string GetTime(double percentage, DateTime startTime, DateTime endTime)
{
    // get the difference between the dates
    // you could use TotalSeconds or a higher precision if needed
    var diff = (endTime - startTime).TotalMinutes;

    // multiply the result by the percentage
    // assuming a range of [0.0, 1.0]
    double minutes = diff * percentage;

    // add the minutes (or precision chosen) to the startTime
    var result = startTime.AddMinutes(minutes);

    // and get the result
    return result.ToShortTimeString();
}

你可以在这个小提琴中测试它:https://dotnetfiddle.net/g4gHLJ

【讨论】:

    【解决方案2】:

    您应该返回 TimeSpan 而不是 string。以下是我的做法:

    static TimeSpan GetTime(double percentage, TimeSpan startTime, TimeSpan endTime)
    {
        var percentageInTicks = (long)((endTime - startTime).Ticks * percentage);
        return startTime.Add(TimeSpan.FromTicks(percentageInTicks));
    }
    

    用法:

    TimeSpan startTime = new TimeSpan(4, 0, 0);
    TimeSpan endTime = new TimeSpan(16, 0, 0);
    double[] percentages = new[] { 0, 0.5, 1 };
    
    foreach (double percentage in percentages)
    {
        var result = GetTime(percentage, startTime, endTime);
        Console.WriteLine(result.ToString());
    }
    

    输出:

    04:00:00
    10:00:00
    16:00:00
    

    编辑:如果您愿意,您可以使用 DateTime 进行基本相同的操作:

    static TimeSpan GetTime(double percentage, DateTime startDate, DateTime endDate)
    {
        var percentageInTicks = (long)((endDate - startDate).Ticks * percentage);
        return startDate.TimeOfDay.Add(TimeSpan.FromTicks(percentageInTicks));
    }
    

    用法:

    DateTime startDate = DateTime.Today.Add(new TimeSpan(4, 0, 0));
    DateTime endDate = DateTime.Today.Add(new TimeSpan(16, 0, 0));
    double[] percentages = new[] { 0, 0.5, 1 };
    
    foreach (double percentage in percentages)
    {
        var result = GetTime(percentage, startDate, startDate);
        Console.WriteLine(result.ToString());
    }
    

    【讨论】:

    • 返回 DateTime 比返回 TimeSpan 更有意义。
    • @TheodorZoulias 为什么? OP想要两个日期之间的百分比差异。所以不,应该返回 TimeSpanstring(取决于 OP 的意愿)。我不明白DateTime 的好处。
    • @FranzHuber23 OP 给出了他想要的一个明确的例子。对于凌晨 4:00 到下午 4:00 之间的范围以及 0% 的百分比,他希望结果是凌晨 4:00。他不想要TimeSpan.Zero
    • @TheodorZoulias:你是对的。我没有正确阅读此内容。对于 OP 的建议,返回 DateTime 也没有意义(除非您稍后对其进行格式化,这实际上意味着像 @Camilo Terevinto 那样返回 string)。
    • 返回一个字符串是可怕的恕我直言。格式化属于表现层。
    【解决方案3】:

    以下是仅使用 DateTimes 作为输入和输出的方法:

     public static DateTime GetTime(double percentage, DateTime startTime, DateTime endTime)
     {
         TimeSpan diff = endTime - startTime;
         long percentOfTimeAsTicks = (long) (percentage * diff.Ticks);
         return startTime + new TimeSpan(percentOfTimeAsTicks);
     }
    

    正如@MattJohnson 指出的那样,两个 DateTimes 需要基于相同的基础(要么都是 UTC,要么都在同一个时区,具有相同的夏季/冬季状态)。

    使用Ticks 而不是秒或分钟会给你最精确的。

    这是一个简单的测试:

      var start = DateTime.Today;
      var end = DateTime.Now;
      Debug.WriteLine(Struct128.GetTime(0.5, start, end));
    

    打印出上午 9:00 之前的时间(此处当前为下午 6:00 之前)。

    【讨论】:

      【解决方案4】:

      首先,您需要计算开始时间和结束时间之间的时间长度,并计算需要添加到开始时间的部分...

      DateTime GetTime(double percentage, DateTime startTime, DateTime endTime)
      {
          var duration = endTime - startTime;
          var partDuration = percentage * (double)duration.TotalMilliseconds;
          return startTime.AddMilliseconds(partDuration);
      }
      
      
      GetTime(0.5, DateTime.Today.AddHours(4), DateTime.Today.AddHours(16)).Dump();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-08
        • 1970-01-01
        • 1970-01-01
        • 2013-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多