【问题标题】:Find time occurence and duration in certain time range查找特定时间范围内的时间发生和持续时间
【发布时间】:2011-07-28 04:51:41
【问题描述】:

我用 C# 做了一个小停车应用程序。根据车辆类型和时区,有一些不同的定价。一天可以分为时区(例如早上、白天、晚上和晚上)。现在,如果客户停止停车,我想计算客户在哪个时区停车以及停了多长时间。

例如,早上时区从 6:00 开始到 12:00 结束,白天时区从 12:00 开始到 16:00 结束,晚上时区从 16:00 开始到 23:00 结束,夜间时区区域从 23:00 开始,到 6:00 结束。客户在 00:30 开始停车,并在 6:32 结束停车。目前我有 4 个变量:停车开始时间、停车结束时间和时区开始时间和时区结束时间。

第二个例子就像客户 24 小时停车,那么停车时间涵盖了所有时区。

如何计算客户在不同时区停车的小时数和分钟数的最简单方法是什么?

问候, 恶人

编辑:

从 MSDN 获得此答案并将其发布在此处,以便其他人也可以从中学习。

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            DateTime start = new DateTime(2011, 7, 25, 0, 30, 0);
            DateTime end = new DateTime(2011, 7, 26, 6, 32, 0);
            List<DateTime> listTimeZones = CalculateTotalTime(start, end);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < listTimeZones.Count; i++)
            {
                sb.AppendLine(String.Format("{0}. {1}: from {2} to {3}",
                                            i + 1,
                                            GetZoneInWords(listTimeZones[i].Hour),
                                            String.Format("{0:dd.MM.yyyy hh:mm}", listTimeZones[i]),
                                            (i + 1) < listTimeZones.Count
                                                ? String.Format("{0:dd.MM.yyyy hh:mm}", listTimeZones[i + 1])
                                                : "Parking ended"));
            }
            MessageBox.Show(sb.ToString());
        }

        private List<DateTime> CalculateTotalTime(DateTime start, DateTime end)
        {
            DateTime temp = start;

            int hour = start.Hour;
            int minute = start.Minute;

            int morning = 6;
            int day = 12;
            int evening = 17;
            int night = 23;

            List<DateTime> timeZones = new List<DateTime>();

            do
            {
                temp = temp.AddHours(1);
                if (temp.Hour == morning || temp.Hour == day ||
                    temp.Hour == evening || temp.Hour == night)
                {
                    timeZones.Add(temp);
                }
            } while (temp < end);

            return timeZones;
        }

        private string GetZoneInWords(int time)
        {
            string timeOfDay = "";
            if (time.Equals(6))
                timeOfDay = "Morning";
            else if (time.Equals(12))
                timeOfDay = "Day";
            else if (time.Equals(17))
                timeOfDay = "Evening";
            else if (time.Equals(23))
                timeOfDay = "Night";

            return timeOfDay + " parking";
        }
    }

【问题讨论】:

    标签: c# datetime time range


    【解决方案1】:

    遍历所有“时区”,并为每个“时区”计算出该时区与客户停车位之间的重叠。例如,作为伪代码:

    private static TimeSpan FindOverlap(ParkingTime parkingTime, TimeZone timeZone)
    {
        // Handle wraparound zones like 23-6. Note that this doesn't attempt
        // to handle *parking* which starts at 11.30pm etc.
        if (timeZone.Start > timeZone.End)
        {
            return FindOverlap(parkingTime,
                         new TimeZone(timeZone.Start.Date, timeZone.End)
                 + FindOverlap(parkingTime,
                         new TimeZone(timeZone.End, timeZone.Start.Date.AddDays(1));
        }
    
        DateTime overlapStart = Max(parkingTime.Start, timeZone.Start);
        DateTime overlapEnd = Min(parkingTime.End, timeZone.End);
        TimeSpan overlap = overlapEnd - overlapStart;
    
        // If the customer arrived after the end or left before the start,
        // the overlap will be negative at this point.
        return overlap < TimeSpan.Zero ? TimeSpan.Zero : overlap;
    }
    
    private static DateTime Min(DateTime x, DateTime y)
    {
        return x < y ? x : y;
    }
    
    private static DateTime Max(DateTime x, DateTime y)
    {
        return x > y ? x : y;
    }
    

    顺便说一句,我强烈鼓励你重命名你的“时区”概念,因为它已经有一个众所周知的(如果不是很好理解:)含义。

    也许你应该叫它ParkingInterval?或者ParkingPriceInterval,如果差异真的是在成本方面?

    【讨论】:

    • C# 真的没有针对IComparable 对象的最小/最大值的内置方法吗?
    • @jdmichal:嗯,C# 是一门语言 - 拥有这些方法的应该是 .NET。它们可能以通用形式存在于某处,但我不知道它们。你当然可以使用 LINQ 方法。
    • @Jon Skeet 这对我不起作用...我的范围是 6-12、12-17、17-23 和 23-6。如果如果从 00:30 到 6:32 停车,那么首先比较只能让我得到正确的 32 分钟。其他都是零。虽然这个停车时间在 23-6 范围内,5 小时 30 分钟我在这里错过了什么?
    • @evilone:啊,我错过了从 23 开始到 6 结束的范围的想法。这基本上是一种痛苦。您是经过一个开始在结束之前的区域,还是在正常停车日的前一天开始,还是在第二天结束?我们可以适当地调整代码,但我需要知道你会怎么称呼它。
    • 我做了一个 ParkingTimeZone 类。在类构造函数中有太多参数。区域开始和区域结束。我也玩过 DateTime.Today.AddHours,但仍然没有运气。
    猜你喜欢
    • 2020-07-28
    • 1970-01-01
    • 2021-07-02
    • 2020-03-16
    • 1970-01-01
    • 2020-12-20
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多