How to check if string dateformat is sortable?

Viewed 68

Given a string that contains a datetime format, I want to tell the user whether it can be sorted as string or not.

For instance:

  • '%Y-%m-%d %H:%M:%S' is sortable
  • '%m-%d %H:%M' is sortable
  • '%d-%m %H:%M' is not (28-05 will appear before 29-04 if we sort it in string)

My approach would be to parse the string and check if we follow the following order:

  • Y before m before d
  • H before M before S

This approach is tedious, is there an easy effective way to accomplish this ?

3 Answers

The key is selecting only the markers that are present, then see if they are in the right order:

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)

If the indices are not in the right order, the string is not sortable.

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

Cheers

To perform the check in linear time you can create an iterator from the sequence of formatting tokens so that you can validate the order of a given formatting string by iterating through the relevant tokens in the formatting string to find the next match from the iterator using the in opeartor:

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

I would do it following way:

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

Explanation: I use regular expression to extract specifier from format string, then I compare if they preserve order when sorted using their position in order as key. order is string where near end smaller unit is therefore lower .index indicates bigger unit and thus using sorted with key=order.index give used units from biggest to lowest. Keep in mind that this solution will fail if there is specifier used which is absent in order.

Related