Как проверить, является ли строковый формат даты сортируемым?

#python #sorting #datetime

#python #сортировка #дата-время

Вопрос:

Учитывая строку, содержащую формат datetime, я хочу сообщить пользователю, можно ли ее сортировать как string или нет.

Например:

  • '%Y-%m-%d %H:%M:%S' сортируется
  • '%m-%d %H:%M' сортируется
  • '%d-%m %H:%M' нет (28-05 появится перед 29-04, если мы отсортируем его в строке)

Мой подход состоял бы в том, чтобы проанализировать строку и проверить, следуем ли мы следующему порядку:

  • Y перед m перед d
  • H перед M перед S

Этот подход утомителен, есть ли простой эффективный способ добиться этого?

Комментарии:

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

2. «‘%m-%d %H:%M’ сортируется» при условии, что все они относятся к одному году.

3. @tobias_k и в том же часовом поясе.

Ответ №1:

Ключ выбирает только те маркеры, которые присутствуют, а затем проверяет, находятся ли они в правильном порядке:

 def is_sortable(format_string):
     markers = ['%Y', '%m', '%d', '%H', '%M', '%s']
     indices = [format_string.index(marker) for marker in markers if marker in format_string]
     return indices == sorted(indices)
 

Если индексы расположены не в правильном порядке, строка не подлежит сортировке.

 is_sortable('%Y-%m-%d %H:%M:%S')
True
is_sortable('%d-%m')
False
 

Приветствия

Ответ №2:

Чтобы выполнить проверку в линейное время, вы можете создать итератор из последовательности токенов форматирования, чтобы вы могли проверить порядок заданной строки форматирования, перебрав соответствующие токены в строке форматирования, чтобы найти следующее совпадение из итератора с помощью in оператора:

 def is_sortable(format, order='YmdHMS'):
    tokens = set(order)
    seq = iter(order)
    return all(char in seq for char in format if char in tokens)

print(is_sortable('%Y-%m-%d %H:%M:%S')) # True
print(is_sortable('%m-%d %H:%M'))       # True
print(is_sortable('%d-%m %H:%M'))       # False
 

Ответ №3:

Я бы сделал это следующим образом:

 import re
order = 'YmdHMS'
f1 = '%Y-%m-%d %H:%M:%S'
f2 = '%m-%d %H:%M'
f3 = '%d-%m %H:%M'
def is_sortable(x):
    elems = re.findall(r'%(w)', x)
    return elems == sorted(elems, key=order.index)
print(is_sortable(f1))  # True
print(is_sortable(f2))  # True
print(is_sortable(f3))  # False
 

Объяснение: я использую регулярное выражение для извлечения спецификатора из строки формата, затем сравниваю, сохраняют ли они порядок при sorted использовании их позиции в order as key . order строка, в которой ближний к концу меньший блок, следовательно, ниже .index , указывает на больший блок и, таким образом, используя sorted с key=order.index , дает используемые единицы от наибольшего до наименьшего. Имейте в виду, что это решение завершится неудачей, если используется спецификатор, который отсутствует в order .

Комментарии:

1. Ваша функция завершится с ошибкой, если какая-либо буква включена в формат, но не является частью маркера. Например, формат ISO %Y-%m-%dT%H:%M:%s