После игры с несколькими вариациями я получил эту работу. Я не уверен на 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)
Счетчик тиков DateTime представляет интервалы в 100 наносекунд, поэтому вы можете округлить до ближайших 5 секунд, округлив до ближайший интервал в 50000000 тиков, например, такой:
DateTime now = DateTime.Now;
DateTime rounded = new DateTime(((now.Ticks + 25000000) / 50000000) * 50000000);
Это более кратко, но не обязательно лучше. Это зависит от того, предпочитаете ли вы краткость и скорость перед ясностью кода. Ваш, возможно, легче понять.
Я не могу придумать лучшего способа, хотя я, вероятно, выбрал бы метод округления:
static int Round(int n, int r)
{
if ((n % r) <= r / 2)
{
return n - (n % r);
}
return n + (r - (n % r));
}
Также % возвращает целое число, поэтому сравнение его с 2,5 кажется мне немного странным, хотя это и правильно. Я бы использовал> = 3.
Как вы упомянули, обрезать довольно легко. Итак, просто добавьте 2,5 секунды, а затем обрежьте.
Как насчет этого (смешать несколько ответов вместе)? Я думаю, что он хорошо передает смысл и должен элегантно обрабатывать крайние случаи (округление до следующей минуты) благодаря 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
.
Я не мог распознать разницу между 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 и т. д.).