0

我目前正在开发一个应用程序,该应用程序根据用户使用该服务的时间来计算用户必须为服务支付的价格。第一小时收费 3.30 美元,之后每半小时收费 1.15 美元。我的计时器看起来像这样:

    private void timer()
    {
        DispatcherTimer timer = new DispatcherTimer();

        timer.Tick +=
            delegate(object s, EventArgs args)
            {
                TimeSpan time = (DateTime.Now - StartTime);

                this.Time.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
            };
        timer.Interval = new TimeSpan(0, 0, 1); // one second
        timer.Start();
    }

关键是计时器和支付的价格应该显示在屏幕上,并随着时间的推移自动更新(计时器已经这样做了。)

至于价格本身,我想过使用 if/else 和 foreach 的组合,但到目前为止,我什么也没做......

4

3 回答 3

2

像这样的东西。(您忽略了部分时间的处理方式,所以我忽略了它们。)

double span = (DateTime.Now - StartTime).TotalHours;
decimal cost = 0.0;
if (span > 0)
    cost = 3.30 + ((span - 1) * 1.15);
于 2013-01-19T16:25:45.537 回答
1

如果该方案是这样的,即在一个段开始时立即添加成本,那么您可以计算在初始小时之后已经开始的半小时数,如下所示:

Math.Round((hours - 1) / 0.5 + 0.5)

然后成本计算为:

double hours = (DateTime.UtcNow - StartTime).TotalHours;
double cost;
if (hours < 1)
    cost = 3.30;
else
    cost = 3.30 + Math.Round((hours - 1) / 0.5 + 0.5) * 1.15;
于 2013-01-19T16:39:33.603 回答
1

几点注意事项:

  1. 使用 UTC 时间,而不是当地时间(参见 Eric Lippert 的评论)
  2. 使用decimal而不是double代表金钱
  3. 计算开始的时间间隔,Math.Ceiling很棒。无需跳过箍Math.Round来做你想做的事。
  4. 将您的定价逻辑封装到一个不与外部服务(例如时钟)交互的简单无副作用方法中。

    这使得单独测试该方法变得容易。

  5. 对所有定期 UI 更新使用单个计时器(除非它们需要不同的时间间隔)

我会这样写:

public decimal CostByTime(TimeSpan t)
{
  if(t < TimeSpan.Zero)
      throw new ArgumentOutOfRangeExeception("t", "Requires t>=0");
  if(t ==  TimeSpan.Zero)
      return 0;
  double hours = t.TotalHours;
  if(hours <= 1)
      return 3.30m;
  else
      return 3.30m + (int)Math.Ceiling((hours-1)*2) * 1.15m
}

然后在您看来,您可以使用:

TimeSpan billableTime = DateTime.UtcNow - StartTime;
decimal cost = CostByTime(billableTime);

Time.Text = billableTime.ToString(...);
Cost.Text = cost.ToString();
于 2013-01-20T11:35:47.727 回答