简体   繁体   English

如何从字符串中累积C#中的TimeOfDay

[英]How to accumulate TimeOfDay in c# from strings

I want to accumulate a string array of time values and check if the total time is greater than one day. 我想累积一个时间值的字符串数组,并检查总时间是否大于一天。 In this test case, I start at 12:00 am and add 12 hours. 在此测试用例中,我从12:00 am开始,然后增加12个小时。 I then add 12 hours and 5 minutes. 然后,我增加12小时5分钟。 the total time should be 24 hours and 5 minutes. 总时间应为24小时5分钟。

The problem is that the calculation from 12:00 PM to 12:05 AM is calculating 11 hours and 55 minutes instead of 12 hours and 5 minutes. 问题在于,从12:00 PM到12:05 AM的计算将计算11小时55分钟,而不是12小时5分钟。

How can I accumulate these times correctly for my use case? 如何为用例正确累积这些时间?

string[] times = {"12:00 AM", "12:00 PM", "12:05 AM"};
const string timePattern = "h:mm tt";

double totalMillis = 0;
var prevTimeSpan = new TimeSpan(0);

foreach (var time in times)
{
    var parsedDate = DateTime.ParseExact(time, timePattern, null, DateTimeStyles.None);
    var currTimeSpan = parsedDate.TimeOfDay;
    var millis = Math.Abs((prevTimeSpan - currTimeSpan).TotalMilliseconds);
    prevTimeSpan = currTimeSpan;
    totalMillis += millis;
}

// 24 hours = 86400000
Console.WriteLine("Result is more than 24 hours? {0}", totalMillis >= 86400000 ? "Yes" : "No");

Problem is that you're ignoring the fact that 12:05 AM after 12:00 PM is next day. 问题是您忽略了第二天12:00 PM之后的12:05 AM这一事实。

Try this 尝试这个

string[] times = { "12:00 AM", "12:00 PM", "12:05 AM" };
const string timePattern = "h:mm tt";
TimeSpan prev = TimeSpan.Zero;
var spans = times.Select(x =>
{
    var span = DateTime.ParseExact(x, timePattern, null, DateTimeStyles.None).TimeOfDay;
    if (span < prev)
    {
        span = span.Add(TimeSpan.FromDays(1.0) - prev);
    }
    prev = span;
    return span;
});
var totalMillis = spans.Sum(x => x.TotalMilliseconds);

// 24 hours = 86400000
Console.WriteLine("Result is more than 24 hours? {0}", totalMillis >= 86400000 ? "Yes" : "No");

One thing to note is that you are making assumptions about your times. 要注意的一件事是您在假设自己的时间。 You are assuming that each time is later than the last time and therefore if it's an earlier time of day that is must be in the next day. 您假设每次时间都比上次时间晚,因此,如果它是一天中的更早时间,则必须在第二天。

Based on that assumption here is how you can calculate the total TimeSpan from the set of times of day: 基于此假设,这里是您如何从一天中的时间组中计算总TimeSpan的方法:

string[] times = { "12:00 AM", "12:00 PM", "12:05 AM" };
const string timePattern = "h:mm tt";

DateTime[] dates = times.Select(x => DateTime.ParseExact(x, timePattern, null)).ToArray();

TimeSpan totalTimeSpan = new TimeSpan();

for (int i = 1; i < dates.Length; i++)
{
    // Assume that each time is at least the same date as the previous time
    dates[i] = dates[i - 1].Date + dates[i].TimeOfDay;

    // If this time is earlier than the previous time then assume it must be on the next day
    if (dates[i - 1].TimeOfDay > dates[i].TimeOfDay)
        dates[i] = dates[i].AddDays(1);

    totalTimeSpan += dates[i] - dates[i - 1];
}

Console.WriteLine("Result is more than 24 hours? {0}", totalTimeSpan.TotalHours > 24);

You can do this easily with LINQ: 您可以使用LINQ轻松做到这一点:

string[] times = { "12:00 AM", "12:00 PM", "12:05 AM" };
const string timePattern = "h:mm tt";

var timesOfDay = times.Select(x => DateTime.ParseExact(x, timePattern, CultureInfo.InvariantCulture).TimeOfDay).ToList();
var elapsedTimes = timesOfDay.Zip(timesOfDay.Skip(1), (a, b) => b - a + TimeSpan.FromDays(a > b ? 1 : 0));
TimeSpan totalElapsedTime = elapsedTimes.Aggregate((s, t) => s.Add(t));

It's calculating it correctly if you add a date part. 如果添加日期部分,它将正确计算。

1/1/2013 12:00 - 1/1/2013 00:05 = 11 hours 55 mins. 1/1/2013 12:00-1/1/2013 00:05 = 11小时55分钟

I think you are expecting it to be 1/2/2013 00:05 - one day ahead. 我认为您预计会在2013年1月2日00:05-提前一天。 12 hours 5 mins. 12小时5分钟。

A solution for this specific use case is: 此特定用例的解决方案是:

string[] times = {"12:00 AM", "12:00 PM", "12:00 AM"};
const string timePattern = "h:mm tt";

double totalMillis = 0;
var prevTimeSpan = new TimeSpan(0);

foreach (var time in times)
{
    var parsedDate = DateTime.ParseExact(time, timePattern, null, DateTimeStyles.None);
    var currTimeSpan = parsedDate.TimeOfDay;
    var millis = (prevTimeSpan - currTimeSpan).TotalMilliseconds;
    prevTimeSpan = currTimeSpan;
    totalMillis += millis;
}

// 24 hours = 86400000
Console.WriteLine("Result is more than 24 hours? {0}", totalMillis >= 0 ? "No" : "Yes");

Notice that instead of checking for totalMillis being greater than a day, I just check to see if it becomes negative. 请注意,我没有检查totalMillis是否大于一天,而是检查它是否变为负数。 I still think it would be interesting to convert the string array into a time span that totals without a date involved. 我仍然认为将字符串数组转换为总的时间跨度而不涉及日期会很有趣。

So maybe operate on DateTime: 因此,也许在DateTime上进行操作:

string[] times = { "12:00 AM", "12:00 PM", "12:05 AM" };
         const string timePattern = "h:mm tt";

         var dateTime = new DateTime(2010,1,1,0,0,0,0);
         foreach (var time in times)
         {
            var parsedDate = DateTime.ParseExact(time, timePattern, null, DateTimeStyles.None);
            dateTime = dateTime.AddHours(parsedDate.Hour);
            dateTime = dateTime.AddMinutes(parsedDate.Minute);
         }
         Console.WriteLine(a.ToShortTimeString());
         Console.ReadKey();

now the computer know you are on a new day 现在计算机知道您正在新的一天

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM