Подтвердить что ты не робот

Можете ли вы объединить объект .NET TimeSpan?

Можно ли объединить объект .NET TimeSpan?

У меня есть значение TimeSpan: 00: 00: 00.6193789

Есть ли простой способ сохранить объект TimeSpan, но округлить его до чего-то вроде 00: 00: 00,62

4b9b3361

Ответ 1

Извините, ребята, но оба вопрос и популярный ответ до сих пор ошибочны: -)

Вопрос неверен, потому что Tyndall запрашивает способ round, но показывает пример усечения.

Не ответит ли Дин, потому что он также относится к усечению, а не к округлению. (Я полагаю, можно было бы утверждать, что ответ подходит для одного из двух вопросов, но на мгновение оставим философию...)

Вот простой способ округления:

int precision = 2; // Specify how many digits past the decimal point
TimeSpan t1 = new TimeSpan(19365678); // sample input value

const int TIMESPAN_SIZE = 7; // it always has seven digits
// convert the digitsToShow into a rounding/truncating mask
int factor = (int)Math.Pow(10,(TIMESPAN_SIZE - precision));

Console.WriteLine("Input: " + t1);
TimeSpan truncatedTimeSpan = new TimeSpan(t1.Ticks - (t1.Ticks % factor));
Console.WriteLine("Truncated: " + truncatedTimeSpan);
TimeSpan roundedTimeSpan =
    new TimeSpan(((long)Math.Round((1.0*t1.Ticks/factor))*factor));
Console.WriteLine("Rounded: " + roundedTimeSpan);

При входном значении и количестве цифр в примере кода это результат:

Input: 00:00:01.9365678
Truncated: 00:00:01.9300000
Rounded: 00:00:01.9400000

Измените точность от 2 цифр до 5 цифр и получите вместо этого:

Input: 00:00:01.9365678
Truncated: 00:00:01.9365600
Rounded: 00:00:01.9365700

И даже измените его на 0, чтобы получить этот результат:

Input: 00:00:01.9365678
Truncated: 00:00:01
Rounded: 00:00:02

Наконец, если вы хотите получить немного больше контроля над выходом, добавьте некоторое форматирование. Вот один пример, показывающий, что вы можете отделить точность от числа отображаемых цифр. Точность снова установлена ​​на 2, но отображаются 3 цифры, как указано в последнем аргументе строки управления форматированием:

Console.WriteLine("Rounded/formatted: " + 
  string.Format("{0:00}:{1:00}:{2:00}.{3:000}",
      roundedTimeSpan.Hours, roundedTimeSpan.Minutes,
      roundedTimeSpan.Seconds, roundedTimeSpan.Milliseconds));
// Input: 00:00:01.9365678
// Truncated: 00:00:01.9300000
// Rounded: 00:00:01.9400000
// Rounded/formatted: 00:00:01.940

2010.01.06 UPDATE: готовое решение

Этот материал полезен, если вы ищете идеи; С тех пор я успел реализовать пакетное решение для тех, кто ищет готовый к использованию код.

Обратите внимание, что это код без комментирования. Полностью прокомментированная версия с комментариями XML-doc будет доступна в моей

Этот код улучшает мой код, который, хотя он округлен, все еще показывает 7 мест, заполненных нулями. Эта завершенная версия обходит и обрезает указанное количество цифр.

Вот пример вызова:

Console.Write(new RoundedTimeSpan(19365678, 2).ToString());
// Result = 00:00:01.94

И вот полный файл RoundedTimeSpan.cs:

using System;

namespace CleanCode.Data
{
    public struct RoundedTimeSpan
    {

        private const int TIMESPAN_SIZE = 7; // it always has seven digits

        private TimeSpan roundedTimeSpan;
        private int precision;

        public RoundedTimeSpan(long ticks, int precision)
        {
            if (precision < 0) { throw new ArgumentException("precision must be non-negative"); }
            this.precision = precision;
            int factor = (int)System.Math.Pow(10, (TIMESPAN_SIZE - precision));

            // This is only valid for rounding milliseconds-will *not* work on secs/mins/hrs!
            roundedTimeSpan = new TimeSpan(((long)System.Math.Round((1.0 * ticks / factor)) * factor));
        }

        public TimeSpan TimeSpan { get { return roundedTimeSpan; } }

        public override string ToString()
        {
            return ToString(precision);
        }

        public string ToString(int length)
        { // this method revised 2010.01.31
            int digitsToStrip = TIMESPAN_SIZE - length;
            string s = roundedTimeSpan.ToString();
            if (!s.Contains(".") && length == 0) { return s; }
            if (!s.Contains(".")) { s += "." + new string('0', TIMESPAN_SIZE); }
            int subLength = s.Length - digitsToStrip;
            return subLength < 0 ? "" : subLength > s.Length ? s : s.Substring(0, subLength);
        }
    }
}

2010.02.01 UPDATE: теперь доступно упакованное решение

Я только что выпустил новую версию моих open-source библиотек вчера, скорее, чем ожидалось, включая RoundedTimeSpan, описанную выше. Код здесь; для запуска API здесь, перейдите к RoundedTimeSpan в пространстве имен CleanCode.Data. Библиотека CleanCode.DLL включает в себя код, показанный выше, но предоставляет его в готовом пакете. Обратите внимание, что я немного улучшил метод ToString(int) выше, так как я опубликовал его в 2010.01.06.

Ответ 2

TimeSpan - это немного больше, чем обертка вокруг члена 'Ticks'. Очень легко создать новый TimeSpan из закругленной версии других TimeSpan Ticks.

TimeSpan t1 = new TimeSpan(2345678);
Console.WriteLine(t1);
TimeSpan t2 = new TimeSpan(t1.Ticks - (t1.Ticks % 100000));
Console.WriteLine(t2);

дает:

00:00:00.2345678
00:00:00.2300000

Ответ 3

Если вы хотите TimeSpan, его простой однострочный:

public static TimeSpan RoundSeconds( TimeSpan span, int nDigits ) {
    return TimeSpan.FromSeconds( Math.Round( span.TotalSeconds, nDigits ) );
}

Если вам нужна строка:

public static string RoundSecondsAsString( TimeSpan span, int nDigits ) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < nDigits; i++)
        sb.Append( "f" );
    return span.ToString( @"hh\:mm\:ss\." + sb );
}

Credits:

cc1960 answer показывает использование FromSeconds, но округляется до целых секунд. Мой ответ обобщается на указанное количество цифр.

Ответ Ed предлагает использовать строку формата и включает ссылку на документ форматирования.

Ответ 4

new TimeSpan(tmspan.Hours, tmspan.Minutes, tmspan.Seconds, (int)Math.Round(Convert.ToDouble(tmspan.Milliseconds / 10)));

Ответ 5

Учитывая некоторые комментарии о округлении до секунд, я думал, что округление до любого TimeSpan было бы приятным:

    public static TimeSpan Round(this TimeSpan ts, TimeSpan rnd) {
        if (rnd == TimeSpan.Zero)
            return ts;

        var rndticks = rnd.Ticks;
        var ansTicks = ts.Ticks + rndticks / 2;
        ansTicks -= ansTicks % rndticks;
        return TimeSpan.FromTicks(ansTicks);
    }

    public static TimeSpan Round(this TimeSpan ts) {
        return ts.Round(TimeSpan.FromSeconds(1));
    }

Ответ 7

Вот хороший метод расширения:

    public static TimeSpan RoundToSeconds(this TimeSpan timespan, int seconds = 1)
    {
        long offset = (timespan.Ticks >= 0) ? TimeSpan.TicksPerSecond / 2 : TimeSpan.TicksPerSecond / -2;
        return TimeSpan.FromTicks((timespan.Ticks + offset) / TimeSpan.TicksPerSecond * TimeSpan.TicksPerSecond);
    }

И вот несколько примеров:

DateTime dt1 = DateTime.Now.RoundToSeconds();  // round to full seconds
DateTime dt2 = DateTime.Now.RoundToSeconds(5 * 60);  // round to full 5 minutes

Ответ 8

Еще один способ округления миллисекунд до ближайшей секунды.

private const long TicksPer1000Milliseconds = 1000 * TimeSpan.TicksPerMillisecond;

// Round milliseconds to nearest second
// To round up, add the sub-second ticks required to reach the next second
// To round down, subtract the sub-second ticks
elapsedTime = new TimeSpan(elapsedTime.Ticks + (elapsedTime.Milliseconds >= 500 ? TicksPer1000Milliseconds - (elapsedTime.Ticks % TicksPer1000Milliseconds) : -(elapsedTime.Ticks % TicksPer1000Milliseconds)));

Ответ 9

Мое решение:

    static TimeSpan RoundToSec(TimeSpan ts)
    {
        return TimeSpan.FromSeconds((int)(ts.TotalSeconds));
    }

Ответ 10

Вместо того, чтобы математически пытаться округлить значение, вы можете просто отображать только те компоненты TimeSpan, которые вы хотите показать.

TimeSpan currentTimeLapsed = DateTime.Now.Subtract(startTime);
Console.WriteLine (currentTimeLapsed.Hours.ToString() + ":" + currentTimeLapsed.Minutes.ToString() + ":" + currentTimeLapsed.Seconds.ToString());