生成时间段标签,最小时间跨度以增加日期时间格式

时间:2011-03-21 23:31:06

标签: c# datetime timespan datetime-format

我想出了一个我认为是个好问题:我如何获得指定日期格式的两个DateTimes之间的每个标签。 想知道是否有人比我想出的更优雅的解决方案。 (除了在编译时知道格式)或任何优化它的方法。

我正在使用它生成一个图表,其中并非所有时间段都有值(因此.GroupBy(date => date.ToString(dateFormat))会导致跳过任何零元素的时间段)

例如:输出2011/01/01和2011/03/21之间的每个标签,日期格式为“yyyyMM” GetTimeSegmentLables(new DateTime(2011,1,1), new DateTime(2011,3,21), "yyyyMM").Dump(); 这也应该支持"yyyy MM 'Month' dddd\\'\\s"

等格式

这就是我想出的:

public static List<string> GetTimeSegmentLabels(DateTime startDate, DateTime endDate, string dateFormat)
{
    DateTime incrementedDate = startDate;
    TimeSpan increment = GetSmallestUnitInDateFormat(dateFormat);

    int estimatedCount = (int)((endDate - startDate).TotalMilliseconds / increment.TotalMilliseconds + 1);
    List<string> Formats = new List<string>(estimatedCount);

    string LastFormat = "";
    while (incrementedDate < endDate)
    {
        string next = incrementedDate.ToString(dateFormat);
        if (next != LastFormat)
        {
            Formats.Add(next);
            LastFormat = next;
        }
        incrementedDate = incrementedDate.Add(increment);
    }
    if (LastFormat != endDate.ToString(dateFormat))
        Formats.Add(endDate.ToString(dateFormat));

    return Formats;
}

public static TimeSpan GetSmallestUnitInDateFormat(string dateFormat)
{
    //Remove escaped characters
    string stripped = Regex.Replace(dateFormat, "(\\\\.|'[^']+'|\"[^\"]+\")", "");

    //Check for format strings in increasing order
    if (stripped.Contains("F") || stripped.Contains("F"))
    {
        //TODO find longest [fF]+ string
    }
    if (stripped.Contains("s"))
    {
        return new TimeSpan(0, 0, 1);
    }
    if (stripped.Contains("m"))
    {
        return new TimeSpan(0, 1, 0);
    }
    if (stripped.Contains("h") || stripped.Contains("H"))
    {
        return new TimeSpan(1, 0, 0);
    }
    if (stripped.Contains("d"))
    {
        return new TimeSpan(1, 0, 0, 0);
    }
    if (stripped.Contains("M"))
    {
        //30 is the average month (365.25/12) but there is a chance it would skip Feburary...
        //So 28 should hit every month for each year, hitting one twice
        return new TimeSpan(28, 0, 0, 0);
    }
    if (stripped.Contains("y"))
    {
        return new TimeSpan(365, 0, 0, 0);
    }

    throw new ArgumentOutOfRangeException("Unable to find any supported Format Specifier");
}

0 个答案:

没有答案