在图表中将秒转换为hhh:mm:ss

时间:2016-03-29 19:59:30

标签: c# time charts

我有一个MsSql数据库,它以秒为单位计算两个日期之间的时间跨度。这很好。我之后在C#中使用此列并将其写入数组。

此数组是稍后的图表输入。 到目前为止,这种方法效果很好,但我无法找到以hhh:mm:ss格式显示秒数的方法,因为时间跨度可能大于24小时。

我试过ChartArea.AxisY.LabelStyle.Format =“hhmmss”;但它根本不起作用。

有人知道我该怎么做吗?

修改 我这样添加数据:

chart2.Series.Clear();
chart2.ChartAreas.Clear();

Series BoxPlotSeries = new Series();

ChartArea ChartArea2 = new ChartArea();
ChartArea ChartArea3 = new ChartArea();

chart2.ChartAreas.Add(ChartArea2);
chart2.ChartAreas.Add(ChartArea3);
ChartArea2.Name = "Data Chart Area";
ChartArea3.Name = "BoxPlotArea";

BoxPlotSeries.Name = "BoxPlotSeries";
BoxPlotSeries.ChartType = SeriesChartType.BoxPlot;
BoxPlotSeries.ChartArea = "BoxPlotArea";

chart2.Series.Add(BoxPlotSeries);

Series Input1 = new Series();
Input1.Name = "Input1";
Input1.ChartType = SeriesChartType.Point;
Input1.ChartArea = "Data Chart Area";
chart2.Series.Add(Input1);
chart2.Series["Input1"].Points.DataBindY(InputArray);
chart2.ChartAreas["BoxPlotArea"].AxisX.CustomLabels.Add(2, 0.0, "BoxPlot1");


chart2.Series["BoxPlotSeries"]["BoxPlotSeries"] = "Input1";
chart2.Series["BoxPlotSeries"]["BoxPlotShowMedian"] = "true";
chart2.Series["BoxPlotSeries"]["BoxPlotShowUnusualValues"] = "false";
chart2.Series["BoxPlotSeries"]["PointWidth"] = "0.5";
chart2.Series["BoxPlotSeries"].IsValueShownAsLabel = false;
ChartArea2.Visible = false;
ChartArea3.BackColor = Color.FromArgb(224,224,224);
//I tried to format it this way but it didn't work
//ChartArea3.AxisY.LabelStyle.Format = "{0:HHHmmss}";
chart2.ChartAreas["BoxPlotArea"].AxisX.LabelStyle.Angle = -90;

EDIT2: 这是我填充输入数组的方法

int[] InputArray = new int[1000000];

int c = 0;
con.Open();
dr = cmd.ExecuteReader();
if (dr.HasRows)         
{
     while (dr.Read())
     {
          int n;
          if (int.TryParse(dr[0].ToString(),out n) == true)
          {
               InputArray[c] = Convert.ToInt32(dr[0].ToString());
               c++;
          }
     }
}
if (c == 0) { c = 1; }
Array.Resize(ref InputArray, c - 1);

编辑3: Boxplot最终看起来应该是这样的: enter image description here

在Excel中,显示小于24的小时的格式称为“[h]:mm:ss; @”

EDIT4:

感谢@TAW,我几乎设法解决了我的问题。我对他的解决方案进行了一些调整,并想出了这个:

在图表代码块中:

之前设置值“max”。

    ChartArea3.AxisY.MajorTickMark.Interval = addCustomLabels(ChartArea3, BoxPlotSeries, 60 * 60, max);





 int addCustomLabels(ChartArea ca, Series series, int interval, int max)
    {
        int tickNo = 0;
        ca.AxisY.CustomLabels.Clear();
        if(max / interval > 10)
        {
            interval = (max / 10) - (max / 10) % (60*30);
            tickNo = (max / 10) - (max / 10) % (60*30);
        }
        if (max / interval <= 2 )
        {
            interval = (max / 4) - (max / 4) % (60 * 15);
            tickNo = (max / 4) - (max / 4) % (60 * 15);
        }
        for (int i = 0; i < max; i += interval)
        {
        CustomLabel cl = new CustomLabel();
        cl.FromPosition = i - interval / 2;
        cl.ToPosition = i + interval / 2;
        cl.Text = hhh_mm_ss(i);
        ca.AxisY.CustomLabels.Add(cl);
        }
        return tickNo;
    }

我现在的问题是,即使代码在没有任何问题的情况下运行,有时也不会显示轴标记(除了0:00)。

有人和想法有什么可能是错的吗?

3 个答案:

答案 0 :(得分:0)

如果您尝试显示超过2位小时,我认为这应该适合您

//yourTimeSpan is the TimeSpan that you already have
var hoursDouble = Math.Floor(yourTimeSpan.TotalHours);
string hours;
string minutes;
string seconds;

//check hours
if(hoursDouble < 10)
{
    hours = string.Format("0{0}", hoursDouble);
}
else
{
    hours = hoursDouble.ToString();
}
//check minutes
if (yourTimeSpan.Minutes < 10)
{
    minutes = string.Format("0{0}", yourTimeSpan.Minutes);
}
else
{
    minutes = yourTimeSpan.Minutes.ToString();
}
//check seconds
if (yourTimeSpan.Seconds < 10)
{
    seconds = string.Format("0{0}", yourTimeSpan.Seconds);
}
else
{
    seconds = yourTimeSpan.Seconds.ToString();
}

string formattedSpan = String.Format("{0}:{1}:{2}", hours, minutes, seconds);

更新:我认为这可以解决您用单位数字看到的问题

答案 1 :(得分:0)

更新:这个答案可能对其他读者非常有用,但它几乎错过了OP的问题。我会保留它的原样,但它无助于创建特殊格式的y轴标签..

大多数图表问题源于无效或无用的x值。以下讨论试图帮助避免或绕过它们。

数字是一个数字而您无法只是将其显示为DateTime,或者TimeSpan

因此,您需要将X-Values添加为包含可转换为DateTime的值的doubleDateTime。我更喜欢这个...

因此,不是直接添加秒,而是将它们添加为给定DateTime的偏移量:

改变这样的事情

series.Points.AddXY(sec, yValues);

对此:

var dt = new DateTime(0).AddSeconds(sec);
series.Points.AddXY(dt, yValues);   

现在您可以根据需要使用日期和时间格式字符串..:

chartArea.AxisX.LabelStyle.Format = "{mm:ss}";

您还可以将doubles添加为DateTimes实际上通过ToOADate series.Points.AddXY(dt.ToOADate(), yValues); 计算:

ChartValueType.DateTime

但现在您必须设置AxisX.IntervalType,也可能设置AxisX.Intervals.XValueType = ChartValueType.DateTime; ca.AxisX.Interval = 5; ca.AxisX.IntervalType = DateTimeIntervalType.Seconds; ca.AxisX.LabelStyle.Format = "{mm:ss}"; ,以确保图表格式正确..:

X-Values

选择适合您数据的值!

注意原始代码的问题在于doubles 内部始终 ToOADate,但秒数不是整数值它们是分数部分;所以你需要某种计算。这是OADate double的作用。这是一个简短的测试,显示一秒实际上相当于X-Values

enter image description here

最好将DateTimes添加为Points.DataBindY,以便所有进一步处理都可以依赖于类型..

更新我刚看到您最终在您的问题中添加了真实代码,并且使用了Points.DataBindXY。这不会创造有意义的X值,我很害怕。尝试切换到 int[] seconds = new int[5] { 1, 3, 88, 123, 3333 }; double[] oaSeconds = seconds.Select(x => new DateTime(0).AddSeconds(x).ToOADate()) .ToArray(); !当然,你绑定的X值也需要遵循我上面解释的规则..!

你可以在数组上循环并转换上面显示的数字;这是一个简单的例子:

onmouseover="this.stop();" onmouseout="this.start();"

答案 2 :(得分:0)

您的任务涉及两个部分:

  • 以hhh:mm:ss格式显示秒数
  • 将它们作为标签放在y轴上

c#中没有合适的date-time formatting string,因此我们无法使用内置的自动标签及其格式。

不幸的是,也无法使用在自动标签上调用函数的表达式。

所以我们不能使用它们。

相反,我们必须添加CustomLabels。这不是很难,但确实需要几步。

但是让我们从一个将int转换为我们想要的hhh:mm:ss字符串的函数开始吧。这应该做的工作:

string hhh_mm_ss(int seconds)
{
    int sec = seconds % 60;
    int min = ((seconds - sec)/60) % 60;
    int hhh = (seconds - sec - 60 * min) / 3600;
    return hhh > 0 ? string.Format("{2}:{1:00}:{0:00}", sec, min, hhh) 
                   : min + ":" + sec.ToString("00");
}

也许它可以被优化,但为了我们的目的,它会做。

接下来,我们需要创建CustomLabels。它们将替换普通轴标签,我们需要在每次绑定后在数据的单独循环中添加它们。

关于他们的一个特别之处是他们的定位。我们需要给出它们的两个值,即FromPositionToPosition,它们都以轴值为单位。

普通自动标签的另一个不同之处在于,我们可以根据需要创建尽可能多的或少数的标签。

此函数尝试创建一个数字,该数字将以给定的间隔达到CustomLabels的最大y值和空间:

void addCustomLabels(ChartArea ca, Series series, int interval)
{
    // we get the maximum form the 1st y-value
    int max = (int)series.Points.Select(x => x.YValues[0]).Max();
    // we delete any CLs we have
    ca.AxisY.CustomLabels.Clear();
    // now we add new custom labels
    for (int i = 0; i < max; i += interval)
    {
        CustomLabel cl = new CustomLabel();
        cl.FromPosition = i - interval / 2;
        cl.ToPosition = i + interval / 2;
        cl.Text = hhh_mm_ss(i);
        ca.AxisY.CustomLabels.Add(cl);
    }
}

调用它的第一个参数是显而易见的;然而最后一个是棘手的:

您需要决定您希望标签的间隔时间。这取决于图表的各种细节:

  • 值范围
  • 图表区域的大小
  • 轴的字体大小

我没有在函数中设置任何特殊的Font; CustomLabels使用与普通轴标签相同的Font,即AxisY.LabelStyle.Font

对于我的截图,我准备了这样的图表:

ca.AxisX.Minimum = 0;
ca.AxisY.MajorTickMark.Interval = 60 * 60;  // one tick per hour
addCustomLabels(ca, s, 60 * 30);            // one label every 30 minutes

我还添加了DataPoint Labels用于测试以显示值..:

series.Points[p].Label = hhh_mm_ss((int)y) + "\n" + y;

结果如下:

enter image description here