Convert seconds to hhh:mm:ss in a chart

后端 未结 3 1860
南旧
南旧 2021-01-22 06:19

I have a MsSql database which calculates the timespan between two dates in seconds. That works fine. I use this column afterwards in C# and write them in an array.

This

3条回答
  •  猫巷女王i
    2021-01-22 06:33

    Your task involves two parts:

    • displaying seconds in the hhh:mm:ss format
    • putting them as labels on the y-axis

    There is no suitable date-time formatting string for this in c#, so we can't make use of the built-in automatic labels and their formatting.

    There also no way to use expressions that call a function on the automatic labels, unfortunately.

    So we can't use those.

    Instead we will have to add CustomLabels. This is not very hard but does take a few steps..

    But let's start with a function that converts an int to the hhh:mm:ss string we want; this should do the job:

    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");
    }
    

    Maybe it can be optimized, but for our purpose it'll do.

    Next we need to create the CustomLabels. They will replace the normal axis labels and we need to add them in a separate loop over the data after each binding.

    One special thing about them is their positioning. Which is smack between two values we need to give them: the FromPosition and ToPosition, both in the unit of the axis-values.

    Another difference to normal, automatic Labels is that it is up to us to create as many or few of them as we need..

    This function tries to create a number that will go up to the maximum y-value and space the CustomLabels at a given interval:

    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);
        }
    }
    

    The first parameters to call this are obvious; the last one however is tricky:

    You need to decide to interval you want your labels to have. It will depend on various details of your chart:

    • the range of values
    • the size of the chart area
    • the size of the font of the axis

    I didn't set any special Font in the function; CustomLabels use the same Font as normal axis labels, i.e. AxisY.LabelStyle.Font.

    For my screenshot I prepared the chart like this:

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

    I have also added DataPoint Labels for testing to show the values..:

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

    Here is the result:

自定义标题
段落格式
字体
字号
代码语言
提交回复
热议问题