Существует ли лучший путь в C# к раунду DateTime к ближайшим 5 секундам?

После игры с несколькими вариациями я получил эту работу. Я не уверен на 100%, если это лучший способ сделать это .... но это работает

date_checker = Draft7Validator.TYPE_CHECKER.redefine_many({
    "date": lambda _, instance: isinstance(instance, date),
    "pos_int": lambda _, instance: isinstance(instance, int) and instance >= 0
})

custom_validator = validators.extend(Draft7Validator, type_checker=date_checker)
validator = custom_validator(schema)
validator.validate(config)
18
задан Community 23 May 2017 в 11:53
поделиться

5 ответов

Счетчик тиков DateTime представляет интервалы в 100 наносекунд, поэтому вы можете округлить до ближайших 5 секунд, округлив до ближайший интервал в 50000000 тиков, например, такой:

  DateTime now = DateTime.Now;
  DateTime rounded = new DateTime(((now.Ticks + 25000000) / 50000000) * 50000000);

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

29
ответ дан 30 November 2019 в 05:42
поделиться

Я не могу придумать лучшего способа, хотя я, вероятно, выбрал бы метод округления:

static int Round(int n, int r)
{
    if ((n % r) <= r / 2)
    {
        return n - (n % r); 
    }
    return n + (r - (n % r));
}

Также % возвращает целое число, поэтому сравнение его с 2,5 кажется мне немного странным, хотя это и правильно. Я бы использовал> = 3.

1
ответ дан 30 November 2019 в 05:42
поделиться

Как вы упомянули, обрезать довольно легко. Итак, просто добавьте 2,5 секунды, а затем обрежьте.

2
ответ дан 30 November 2019 в 05:42
поделиться

Как насчет этого (смешать несколько ответов вместе)? Я думаю, что он хорошо передает смысл и должен элегантно обрабатывать крайние случаи (округление до следующей минуты) благодаря AddSeconds .

// truncate to multiple of 5
int second = 5 * (int) (now.Second / 5);
DateTime dt = new DateTime(..., second);

// round-up if necessary
if (now.Second % 5 > 2.5)
{
    dt = dt.AddSeconds(5);
}

Подход Ticks , как показал Джей, более лаконичен , но может быть немного менее читабельным. Если вы используете этот подход, по крайней мере, ссылка TimeSpan.TicksPerSecond .

1
ответ дан 30 November 2019 в 05:42
поделиться

Я не мог распознать разницу между C # и кусочком мыла (ну, я не мог, когда я изначально написал этот ответ, с тех пор все немного изменилось) но, если вы ищете более сжатое решение, я бы просто поместил все это в функцию - мало что будет более кратким в вашем коде, чем простой вызов указанной функции:

DateTime rounded = roundTo5Secs (DateTime.Now);

Затем вы можете поместить в функцию все, что захотите, и просто задокументировать, как она работает, например (при условии, что это все целочисленные операции):

secBase = now.Second / 5;
secExtra = now.Second % 5;
if (secExtra > 2) {
    return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute,
        secBase + 5);
}
return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute,
    secBase);

Вы также можете нужны дополнительные проверки, если secBase достигает 60 (если только объекты C # DateTime не достаточно умны, чтобы увеличить минуту (и час, если минута достигает 60 и т. д.).

1
ответ дан 30 November 2019 в 05:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: